#!/usr/bin/env python3
"""
Tech Debt Dashboard

Takes historical debt inventories (multiple scans over time) and generates trend analysis,
debt velocity (accruing vs paying down), health score, and executive summary.

Usage:
    python debt_dashboard.py historical_data.json
    python debt_dashboard.py data1.json data2.json data3.json
    python debt_dashboard.py --input-dir ./debt_scans/ --output dashboard_report.json
    python debt_dashboard.py historical_data.json --period quarterly --team-size 8
"""

import json
import argparse
import sys
import os
from collections import defaultdict, Counter
from datetime import datetime, timedelta
from pathlib import Path
from typing import Dict, List, Any, Optional, Tuple
from dataclasses import dataclass, asdict
from statistics import mean, median, stdev
import re


@dataclass
class HealthMetrics:
    """Health metrics for a specific time period."""
    overall_score: float  # 0-100
    debt_density: float  # debt items per file
    velocity_impact: float  # estimated velocity reduction %
    quality_score: float  # 0-100
    maintainability_score: float  # 0-100
    technical_risk_score: float  # 0-100


@dataclass
class TrendAnalysis:
    """Trend analysis for debt metrics over time."""
    metric_name: str
    trend_direction: str  # "improving", "declining", "stable"
    change_rate: float  # rate of change per period
    correlation_strength: float  # -1 to 1
    forecast_next_period: float
    confidence_interval: Tuple[float, float]


@dataclass
class DebtVelocity:
    """Debt velocity tracking - how fast debt is being created vs resolved."""
    period: str
    new_debt_items: int
    resolved_debt_items: int
    net_change: int
    velocity_ratio: float  # resolved/new, >1 is good
    effort_hours_added: float
    effort_hours_resolved: float
    net_effort_change: float


class DebtDashboard:
    """Main dashboard class for debt trend analysis and reporting."""
    
    def __init__(self, team_size: int = 5):
        self.team_size = team_size
        self.historical_data = []
        self.processed_snapshots = []
        self.trend_analyses = {}
        self.health_history = []
        self.velocity_history = []
        
        # Configuration for health scoring
        self.health_weights = {
            "debt_density": 0.25,
            "complexity_score": 0.20,
            "test_coverage_proxy": 0.15,
            "documentation_proxy": 0.10,
            "security_score": 0.15,
            "maintainability": 0.15
        }
        
        # Thresholds for categorization
        self.thresholds = {
            "excellent": 85,
            "good": 70,
            "fair": 55,
            "poor": 40
        }
    
    def load_historical_data(self, file_paths: List[str]) -> bool:
        """Load multiple debt inventory files for historical analysis."""
        self.historical_data = []
        
        for file_path in file_paths:
            try:
                with open(file_path, 'r', encoding='utf-8') as f:
                    data = json.load(f)
                
                # Normalize data format
                if isinstance(data, dict) and 'debt_items' in data:
                    # Scanner output format
                    snapshot = {
                        "file_path": file_path,
                        "scan_date": data.get("scan_metadata", {}).get("scan_date", 
                                               self._extract_date_from_filename(file_path)),
                        "debt_items": data["debt_items"],
                        "summary": data.get("summary", {}),
                        "file_statistics": data.get("file_statistics", {})
                    }
                elif isinstance(data, dict) and 'prioritized_backlog' in data:
                    # Prioritizer output format
                    snapshot = {
                        "file_path": file_path,
                        "scan_date": data.get("metadata", {}).get("analysis_date",
                                               self._extract_date_from_filename(file_path)),
                        "debt_items": data["prioritized_backlog"],
                        "summary": data.get("insights", {}),
                        "file_statistics": {}
                    }
                elif isinstance(data, list):
                    # Raw debt items array
                    snapshot = {
                        "file_path": file_path,
                        "scan_date": self._extract_date_from_filename(file_path),
                        "debt_items": data,
                        "summary": {},
                        "file_statistics": {}
                    }
                else:
                    raise ValueError(f"Unrecognized data format in {file_path}")
                
                self.historical_data.append(snapshot)
                
            except Exception as e:
                print(f"Error loading {file_path}: {e}")
                continue
        
        if not self.historical_data:
            print("No valid data files loaded.")
            return False
        
        # Sort by date
        self.historical_data.sort(key=lambda x: x["scan_date"])
        print(f"Loaded {len(self.historical_data)} historical snapshots")
        return True
    
    def load_from_directory(self, directory_path: str, pattern: str = "*.json") -> bool:
        """Load all JSON files from a directory."""
        directory = Path(directory_path)
        if not directory.exists():
            print(f"Directory does not exist: {directory_path}")
            return False
        
        file_paths = []
        for file_path in directory.glob(pattern):
            if file_path.is_file():
                file_paths.append(str(file_path))
        
        if not file_paths:
            print(f"No matching files found in {directory_path}")
            return False
        
        return self.load_historical_data(file_paths)
    
    def _extract_date_from_filename(self, file_path: str) -> str:
        """Extract date from filename if possible, otherwise use current date."""
        filename = Path(file_path).name
        
        # Try to find date patterns in filename
        date_patterns = [
            r"(\d{4}-\d{2}-\d{2})",  # YYYY-MM-DD
            r"(\d{4}\d{2}\d{2})",    # YYYYMMDD
            r"(\d{2}-\d{2}-\d{4})",  # MM-DD-YYYY
        ]
        
        for pattern in date_patterns:
            match = re.search(pattern, filename)
            if match:
                date_str = match.group(1)
                try:
                    if len(date_str) == 8:  # YYYYMMDD
                        date_str = f"{date_str[:4]}-{date_str[4:6]}-{date_str[6:]}"
                    datetime.strptime(date_str, "%Y-%m-%d")
                    return date_str + "T12:00:00"
                except ValueError:
                    continue
        
        # Fallback to file modification time
        try:
            mtime = os.path.getmtime(file_path)
            return datetime.fromtimestamp(mtime).isoformat()
        except:
            return datetime.now().isoformat()
    
    def generate_dashboard(self, period: str = "monthly") -> Dict[str, Any]:
        """
        Generate comprehensive debt dashboard.
        
        Args:
            period: Analysis period ("weekly", "monthly", "quarterly")
            
        Returns:
            Dictionary containing dashboard data and analysis
        """
        print(f"Generating debt dashboard for {len(self.historical_data)} snapshots...")
        print(f"Analysis period: {period}")
        print("=" * 50)
        
        # Step 1: Process historical snapshots
        self._process_snapshots()
        
        # Step 2: Calculate health metrics for each snapshot
        self._calculate_health_metrics()
        
        # Step 3: Analyze trends
        self._analyze_trends(period)
        
        # Step 4: Calculate debt velocity
        self._calculate_debt_velocity(period)
        
        # Step 5: Generate forecasts
        forecasts = self._generate_forecasts()
        
        # Step 6: Create executive summary
        executive_summary = self._generate_executive_summary()
        
        # Step 7: Generate recommendations
        recommendations = self._generate_strategic_recommendations()
        
        # Step 8: Create visualizations data
        visualizations = self._generate_visualization_data()
        
        dashboard_data = {
            "metadata": {
                "generated_date": datetime.now().isoformat(),
                "analysis_period": period,
                "snapshots_analyzed": len(self.historical_data),
                "date_range": {
                    "start": self.historical_data[0]["scan_date"] if self.historical_data else None,
                    "end": self.historical_data[-1]["scan_date"] if self.historical_data else None
                },
                "team_size": self.team_size
            },
            "executive_summary": executive_summary,
            "current_health": self.health_history[-1] if self.health_history else None,
            "trend_analysis": {name: asdict(trend) for name, trend in self.trend_analyses.items()},
            "debt_velocity": [asdict(v) for v in self.velocity_history],
            "forecasts": forecasts,
            "recommendations": recommendations,
            "visualizations": visualizations,
            "detailed_metrics": self._get_detailed_metrics()
        }
        
        return dashboard_data
    
    def _process_snapshots(self):
        """Process raw snapshots into standardized format."""
        self.processed_snapshots = []
        
        for snapshot in self.historical_data:
            processed = {
                "date": snapshot["scan_date"],
                "total_debt_items": len(snapshot["debt_items"]),
                "debt_by_type": Counter(item.get("type", "unknown") for item in snapshot["debt_items"]),
                "debt_by_severity": Counter(item.get("severity", "medium") for item in snapshot["debt_items"]),
                "debt_by_category": Counter(self._categorize_debt_item(item) for item in snapshot["debt_items"]),
                "total_files": snapshot["summary"].get("total_files_scanned", 
                                                     len(snapshot["file_statistics"])),
                "total_effort_estimate": self._calculate_total_effort(snapshot["debt_items"]),
                "high_priority_count": len([item for item in snapshot["debt_items"] 
                                          if self._is_high_priority(item)]),
                "security_debt_count": len([item for item in snapshot["debt_items"]
                                          if self._is_security_related(item)]),
                "raw_data": snapshot
            }
            self.processed_snapshots.append(processed)
    
    def _categorize_debt_item(self, item: Dict[str, Any]) -> str:
        """Categorize debt item into high-level categories."""
        debt_type = item.get("type", "unknown")
        
        categories = {
            "code_quality": ["large_function", "high_complexity", "duplicate_code", 
                           "long_line", "missing_docstring"],
            "architecture": ["architecture_debt", "large_file"],
            "security": ["security_risk", "hardcoded_secrets", "sql_injection_risk"],
            "testing": ["test_debt", "missing_tests", "low_coverage"],
            "maintenance": ["todo_comment", "commented_code"],
            "dependencies": ["dependency_debt", "outdated_packages"],
            "infrastructure": ["deployment_debt", "monitoring_gaps"],
            "documentation": ["missing_docstring", "outdated_docs"]
        }
        
        for category, types in categories.items():
            if debt_type in types:
                return category
        
        return "other"
    
    def _calculate_total_effort(self, debt_items: List[Dict[str, Any]]) -> float:
        """Calculate total estimated effort for debt items."""
        total_effort = 0.0
        
        for item in debt_items:
            # Try to get effort from existing analysis
            if "effort_estimate" in item:
                total_effort += item["effort_estimate"].get("hours_estimate", 0)
            else:
                # Estimate based on debt type and severity
                effort = self._estimate_item_effort(item)
                total_effort += effort
        
        return total_effort
    
    def _estimate_item_effort(self, item: Dict[str, Any]) -> float:
        """Estimate effort for a debt item."""
        debt_type = item.get("type", "unknown")
        severity = item.get("severity", "medium")
        
        base_efforts = {
            "todo_comment": 2,
            "missing_docstring": 2,
            "long_line": 1,
            "large_function": 8,
            "high_complexity": 16,
            "duplicate_code": 12,
            "large_file": 32,
            "syntax_error": 4,
            "security_risk": 20,
            "architecture_debt": 80,
            "test_debt": 16
        }
        
        base_effort = base_efforts.get(debt_type, 8)
        
        severity_multipliers = {
            "low": 0.5,
            "medium": 1.0,
            "high": 1.5,
            "critical": 2.0
        }
        
        return base_effort * severity_multipliers.get(severity, 1.0)
    
    def _is_high_priority(self, item: Dict[str, Any]) -> bool:
        """Determine if debt item is high priority."""
        severity = item.get("severity", "medium")
        priority_score = item.get("priority_score", 0)
        debt_type = item.get("type", "")
        
        return (severity in ["high", "critical"] or 
                priority_score >= 7 or
                debt_type in ["security_risk", "syntax_error", "architecture_debt"])
    
    def _is_security_related(self, item: Dict[str, Any]) -> bool:
        """Determine if debt item is security-related."""
        debt_type = item.get("type", "")
        description = item.get("description", "").lower()
        
        security_types = ["security_risk", "hardcoded_secrets", "sql_injection_risk"]
        security_keywords = ["password", "token", "key", "secret", "auth", "security"]
        
        return (debt_type in security_types or 
                any(keyword in description for keyword in security_keywords))
    
    def _calculate_health_metrics(self):
        """Calculate health metrics for each snapshot."""
        self.health_history = []
        
        for snapshot in self.processed_snapshots:
            # Debt density (lower is better)
            debt_density = snapshot["total_debt_items"] / max(1, snapshot["total_files"])
            debt_density_score = max(0, 100 - (debt_density * 20))  # Scale to 0-100
            
            # Complexity score (based on high complexity debt)
            complex_debt_ratio = (snapshot["debt_by_type"].get("high_complexity", 0) + 
                                snapshot["debt_by_type"].get("large_function", 0)) / max(1, snapshot["total_debt_items"])
            complexity_score = max(0, 100 - (complex_debt_ratio * 100))
            
            # Test coverage proxy (based on test debt)
            test_debt_ratio = snapshot["debt_by_category"].get("testing", 0) / max(1, snapshot["total_debt_items"])
            test_coverage_proxy = max(0, 100 - (test_debt_ratio * 150))
            
            # Documentation proxy (based on documentation debt)
            doc_debt_ratio = snapshot["debt_by_category"].get("documentation", 0) / max(1, snapshot["total_debt_items"])
            documentation_proxy = max(0, 100 - (doc_debt_ratio * 100))
            
            # Security score (based on security debt)
            security_debt_ratio = snapshot["security_debt_count"] / max(1, snapshot["total_debt_items"])
            security_score = max(0, 100 - (security_debt_ratio * 200))
            
            # Maintainability (based on architecture and code quality debt)
            maint_debt_count = (snapshot["debt_by_category"].get("architecture", 0) + 
                              snapshot["debt_by_category"].get("code_quality", 0))
            maint_debt_ratio = maint_debt_count / max(1, snapshot["total_debt_items"])
            maintainability = max(0, 100 - (maint_debt_ratio * 120))
            
            # Calculate weighted overall score
            weights = self.health_weights
            overall_score = (
                debt_density_score * weights["debt_density"] +
                complexity_score * weights["complexity_score"] +
                test_coverage_proxy * weights["test_coverage_proxy"] +
                documentation_proxy * weights["documentation_proxy"] +
                security_score * weights["security_score"] +
                maintainability * weights["maintainability"]
            )
            
            # Velocity impact (estimated percentage reduction in team velocity)
            high_impact_ratio = snapshot["high_priority_count"] / max(1, snapshot["total_debt_items"])
            velocity_impact = min(50, high_impact_ratio * 30 + debt_density * 5)
            
            # Technical risk (0-100, higher is more risky)
            risk_factors = snapshot["security_debt_count"] + snapshot["debt_by_type"].get("architecture_debt", 0)
            technical_risk = min(100, risk_factors * 10 + (100 - security_score))
            
            health_metrics = HealthMetrics(
                overall_score=round(overall_score, 1),
                debt_density=round(debt_density, 2),
                velocity_impact=round(velocity_impact, 1),
                quality_score=round((complexity_score + maintainability) / 2, 1),
                maintainability_score=round(maintainability, 1),
                technical_risk_score=round(technical_risk, 1)
            )
            
            # Add timestamp
            health_entry = asdict(health_metrics)
            health_entry["date"] = snapshot["date"]
            self.health_history.append(health_entry)
    
    def _analyze_trends(self, period: str):
        """Analyze trends in various metrics."""
        self.trend_analyses = {}
        
        if len(self.health_history) < 2:
            return
        
        # Define metrics to analyze
        metrics_to_analyze = [
            "overall_score",
            "debt_density", 
            "velocity_impact",
            "quality_score",
            "technical_risk_score"
        ]
        
        for metric in metrics_to_analyze:
            values = [entry[metric] for entry in self.health_history]
            dates = [datetime.fromisoformat(entry["date"].replace('Z', '+00:00')) 
                    for entry in self.health_history]
            
            trend = self._calculate_trend(values, dates, metric)
            self.trend_analyses[metric] = trend
    
    def _calculate_trend(self, values: List[float], dates: List[datetime], metric_name: str) -> TrendAnalysis:
        """Calculate trend analysis for a specific metric."""
        if len(values) < 2:
            return TrendAnalysis(metric_name, "stable", 0.0, 0.0, values[-1], (values[-1], values[-1]))
        
        # Calculate simple linear trend
        n = len(values)
        x = list(range(n))  # Time periods as numbers
        
        # Linear regression
        x_mean = mean(x)
        y_mean = mean(values)
        
        numerator = sum((x[i] - x_mean) * (values[i] - y_mean) for i in range(n))
        denominator = sum((x[i] - x_mean) ** 2 for i in range(n))
        
        if denominator == 0:
            slope = 0
        else:
            slope = numerator / denominator
        
        # Correlation strength
        if n > 2 and len(set(values)) > 1:
            try:
                correlation = numerator / (
                    (sum((x[i] - x_mean) ** 2 for i in range(n)) * 
                     sum((values[i] - y_mean) ** 2 for i in range(n))) ** 0.5
                )
            except ZeroDivisionError:
                correlation = 0.0
        else:
            correlation = 0.0
        
        # Determine trend direction
        if abs(slope) < 0.1:
            trend_direction = "stable"
        elif slope > 0:
            if metric_name in ["overall_score", "quality_score"]:
                trend_direction = "improving"  # Higher is better
            else:
                trend_direction = "declining"  # Higher is worse
        else:
            if metric_name in ["overall_score", "quality_score"]:
                trend_direction = "declining"
            else:
                trend_direction = "improving"
        
        # Forecast next period
        forecast = values[-1] + slope
        
        # Confidence interval (simple approach)
        if n > 2:
            residuals = [values[i] - (y_mean + slope * (x[i] - x_mean)) for i in range(n)]
            std_error = (sum(r**2 for r in residuals) / (n - 2)) ** 0.5
            confidence_interval = (forecast - std_error, forecast + std_error)
        else:
            confidence_interval = (forecast, forecast)
        
        return TrendAnalysis(
            metric_name=metric_name,
            trend_direction=trend_direction,
            change_rate=round(slope, 3),
            correlation_strength=round(correlation, 3),
            forecast_next_period=round(forecast, 2),
            confidence_interval=(round(confidence_interval[0], 2), round(confidence_interval[1], 2))
        )
    
    def _calculate_debt_velocity(self, period: str):
        """Calculate debt velocity between snapshots."""
        self.velocity_history = []
        
        if len(self.processed_snapshots) < 2:
            return
        
        for i in range(1, len(self.processed_snapshots)):
            current = self.processed_snapshots[i]
            previous = self.processed_snapshots[i-1]
            
            # Track debt by unique identifiers when possible
            current_debt_ids = set()
            previous_debt_ids = set()
            
            current_effort = current["total_effort_estimate"]
            previous_effort = previous["total_effort_estimate"]
            
            # Simple approach: compare total counts and effort
            debt_change = current["total_debt_items"] - previous["total_debt_items"]
            effort_change = current_effort - previous_effort
            
            # Estimate new vs resolved (rough approximation)
            if debt_change >= 0:
                new_debt_items = debt_change
                resolved_debt_items = 0
            else:
                new_debt_items = 0
                resolved_debt_items = abs(debt_change)
            
            # Calculate velocity ratio
            if new_debt_items > 0:
                velocity_ratio = resolved_debt_items / new_debt_items
            else:
                velocity_ratio = float('inf') if resolved_debt_items > 0 else 1.0
            
            velocity = DebtVelocity(
                period=f"{previous['date'][:10]} to {current['date'][:10]}",
                new_debt_items=new_debt_items,
                resolved_debt_items=resolved_debt_items,
                net_change=debt_change,
                velocity_ratio=min(10.0, velocity_ratio),  # Cap at 10 for display
                effort_hours_added=max(0, effort_change),
                effort_hours_resolved=max(0, -effort_change),
                net_effort_change=effort_change
            )
            
            self.velocity_history.append(velocity)
    
    def _generate_forecasts(self) -> Dict[str, Any]:
        """Generate forecasts based on trend analysis."""
        if not self.trend_analyses:
            return {}
        
        forecasts = {}
        
        # Overall health forecast
        health_trend = self.trend_analyses.get("overall_score")
        if health_trend:
            current_score = self.health_history[-1]["overall_score"]
            forecasts["health_score_3_months"] = max(0, min(100, 
                current_score + (health_trend.change_rate * 3)))
            forecasts["health_score_6_months"] = max(0, min(100,
                current_score + (health_trend.change_rate * 6)))
        
        # Debt accumulation forecast
        if self.velocity_history:
            avg_net_change = mean([v.net_change for v in self.velocity_history[-3:]])  # Last 3 periods
            current_debt = self.processed_snapshots[-1]["total_debt_items"]
            
            forecasts["debt_count_3_months"] = max(0, current_debt + (avg_net_change * 3))
            forecasts["debt_count_6_months"] = max(0, current_debt + (avg_net_change * 6))
        
        # Risk forecast
        risk_trend = self.trend_analyses.get("technical_risk_score")
        if risk_trend:
            current_risk = self.health_history[-1]["technical_risk_score"]
            forecasts["risk_score_3_months"] = max(0, min(100,
                current_risk + (risk_trend.change_rate * 3)))
        
        return forecasts
    
    def _generate_executive_summary(self) -> Dict[str, Any]:
        """Generate executive summary of debt status."""
        if not self.health_history:
            return {}
        
        current_health = self.health_history[-1]
        
        # Determine overall status
        score = current_health["overall_score"]
        if score >= self.thresholds["excellent"]:
            status = "excellent"
            status_message = "Code quality is excellent with minimal technical debt."
        elif score >= self.thresholds["good"]:
            status = "good" 
            status_message = "Code quality is good with manageable technical debt."
        elif score >= self.thresholds["fair"]:
            status = "fair"
            status_message = "Code quality needs attention. Technical debt is accumulating."
        else:
            status = "poor"
            status_message = "Critical: High levels of technical debt requiring immediate action."
        
        # Key insights
        insights = []
        
        if len(self.health_history) > 1:
            prev_health = self.health_history[-2]
            score_change = current_health["overall_score"] - prev_health["overall_score"]
            
            if score_change > 5:
                insights.append("Health score improving significantly")
            elif score_change < -5:
                insights.append("Health score declining - attention needed")
        
        if current_health["velocity_impact"] > 20:
            insights.append("High velocity impact detected - development speed affected")
        
        if current_health["technical_risk_score"] > 70:
            insights.append("High technical risk - security and stability concerns")
        
        # Debt velocity insight
        if self.velocity_history:
            recent_velocity = self.velocity_history[-1]
            if recent_velocity.velocity_ratio < 0.5:
                insights.append("Debt accumulating faster than resolution")
            elif recent_velocity.velocity_ratio > 1.5:
                insights.append("Good progress on debt reduction")
        
        return {
            "overall_status": status,
            "health_score": current_health["overall_score"],
            "status_message": status_message,
            "key_insights": insights,
            "total_debt_items": self.processed_snapshots[-1]["total_debt_items"] if self.processed_snapshots else 0,
            "estimated_effort_hours": self.processed_snapshots[-1]["total_effort_estimate"] if self.processed_snapshots else 0,
            "high_priority_items": self.processed_snapshots[-1]["high_priority_count"] if self.processed_snapshots else 0,
            "velocity_impact_percent": current_health["velocity_impact"]
        }
    
    def _generate_strategic_recommendations(self) -> List[Dict[str, Any]]:
        """Generate strategic recommendations for debt management."""
        recommendations = []
        
        if not self.health_history:
            return recommendations
        
        current_health = self.health_history[-1]
        current_snapshot = self.processed_snapshots[-1] if self.processed_snapshots else {}
        
        # Health-based recommendations
        if current_health["overall_score"] < 50:
            recommendations.append({
                "priority": "critical",
                "category": "immediate_action",
                "title": "Initiate Emergency Debt Reduction",
                "description": "Current health score is critically low. Consider dedicating 50%+ of development capacity to debt reduction.",
                "impact": "high",
                "effort": "high"
            })
        
        # Velocity impact recommendations
        if current_health["velocity_impact"] > 25:
            recommendations.append({
                "priority": "high",
                "category": "productivity",
                "title": "Address Velocity Blockers",
                "description": f"Technical debt is reducing team velocity by {current_health['velocity_impact']:.1f}%. Focus on high-impact debt items first.",
                "impact": "high",
                "effort": "medium"
            })
        
        # Security recommendations
        if current_health["technical_risk_score"] > 70:
            recommendations.append({
                "priority": "high",
                "category": "security",
                "title": "Security Debt Review Required",
                "description": "High technical risk score indicates security vulnerabilities. Conduct immediate security debt audit.",
                "impact": "high",
                "effort": "medium"
            })
        
        # Trend-based recommendations
        health_trend = self.trend_analyses.get("overall_score")
        if health_trend and health_trend.trend_direction == "declining":
            recommendations.append({
                "priority": "medium",
                "category": "process",
                "title": "Implement Debt Prevention Measures",
                "description": "Health score is declining over time. Establish coding standards, automated quality gates, and regular debt reviews.",
                "impact": "medium",
                "effort": "medium"
            })
        
        # Category-specific recommendations
        if current_snapshot:
            debt_by_category = current_snapshot["debt_by_category"]
            top_category = debt_by_category.most_common(1)[0] if debt_by_category else None
            
            if top_category and top_category[1] > 10:
                category, count = top_category
                recommendations.append({
                    "priority": "medium",
                    "category": "focus_area",
                    "title": f"Focus on {category.replace('_', ' ').title()} Debt",
                    "description": f"{category.replace('_', ' ').title()} represents the largest debt category ({count} items). Consider targeted initiatives.",
                    "impact": "medium",
                    "effort": "medium"
                })
        
        # Velocity-based recommendations
        if self.velocity_history:
            recent_velocities = self.velocity_history[-3:] if len(self.velocity_history) >= 3 else self.velocity_history
            avg_velocity_ratio = mean([v.velocity_ratio for v in recent_velocities])
            
            if avg_velocity_ratio < 0.8:
                recommendations.append({
                    "priority": "medium",
                    "category": "capacity",
                    "title": "Increase Debt Resolution Capacity",
                    "description": "Debt is accumulating faster than resolution. Consider increasing debt budget or improving resolution efficiency.",
                    "impact": "medium",
                    "effort": "low"
                })
        
        return recommendations
    
    def _generate_visualization_data(self) -> Dict[str, Any]:
        """Generate data for dashboard visualizations."""
        visualizations = {}
        
        # Health score timeline
        visualizations["health_timeline"] = [
            {
                "date": entry["date"][:10],  # Date only
                "overall_score": entry["overall_score"],
                "quality_score": entry["quality_score"],
                "technical_risk": entry["technical_risk_score"]
            }
            for entry in self.health_history
        ]
        
        # Debt accumulation trend
        visualizations["debt_accumulation"] = [
            {
                "date": snapshot["date"][:10],
                "total_debt": snapshot["total_debt_items"],
                "high_priority": snapshot["high_priority_count"],
                "security_debt": snapshot["security_debt_count"]
            }
            for snapshot in self.processed_snapshots
        ]
        
        # Category distribution (latest snapshot)
        if self.processed_snapshots:
            latest_categories = self.processed_snapshots[-1]["debt_by_category"]
            visualizations["category_distribution"] = [
                {"category": category, "count": count}
                for category, count in latest_categories.items()
            ]
        
        # Velocity chart
        visualizations["debt_velocity"] = [
            {
                "period": velocity.period,
                "new_items": velocity.new_debt_items,
                "resolved_items": velocity.resolved_debt_items,
                "net_change": velocity.net_change,
                "velocity_ratio": velocity.velocity_ratio
            }
            for velocity in self.velocity_history
        ]
        
        # Effort estimation trend
        visualizations["effort_trend"] = [
            {
                "date": snapshot["date"][:10],
                "total_effort": snapshot["total_effort_estimate"]
            }
            for snapshot in self.processed_snapshots
        ]
        
        return visualizations
    
    def _get_detailed_metrics(self) -> Dict[str, Any]:
        """Get detailed metrics for the current state."""
        if not self.processed_snapshots:
            return {}
        
        current = self.processed_snapshots[-1]
        
        return {
            "debt_breakdown": dict(current["debt_by_type"]),
            "severity_breakdown": dict(current["debt_by_severity"]),
            "category_breakdown": dict(current["debt_by_category"]),
            "files_analyzed": current["total_files"],
            "debt_density": current["total_debt_items"] / max(1, current["total_files"]),
            "average_effort_per_item": current["total_effort_estimate"] / max(1, current["total_debt_items"])
        }


def format_dashboard_report(dashboard_data: Dict[str, Any]) -> str:
    """Format dashboard data into human-readable report."""
    output = []
    
    # Header
    output.append("=" * 60)
    output.append("TECHNICAL DEBT DASHBOARD")
    output.append("=" * 60)
    metadata = dashboard_data["metadata"]
    output.append(f"Generated: {metadata['generated_date'][:19]}")
    output.append(f"Analysis Period: {metadata['analysis_period']}")
    output.append(f"Snapshots Analyzed: {metadata['snapshots_analyzed']}")
    if metadata["date_range"]["start"]:
        output.append(f"Date Range: {metadata['date_range']['start'][:10]} to {metadata['date_range']['end'][:10]}")
    output.append("")
    
    # Executive Summary
    exec_summary = dashboard_data["executive_summary"]
    output.append("EXECUTIVE SUMMARY")
    output.append("-" * 30)
    output.append(f"Overall Status: {exec_summary['overall_status'].upper()}")
    output.append(f"Health Score: {exec_summary['health_score']:.1f}/100")
    output.append(f"Status: {exec_summary['status_message']}")
    output.append("")
    output.append("Key Metrics:")
    output.append(f"  • Total Debt Items: {exec_summary['total_debt_items']}")
    output.append(f"  • High Priority Items: {exec_summary['high_priority_items']}")
    output.append(f"  • Estimated Effort: {exec_summary['estimated_effort_hours']:.1f} hours")
    output.append(f"  • Velocity Impact: {exec_summary['velocity_impact_percent']:.1f}%")
    output.append("")
    
    if exec_summary["key_insights"]:
        output.append("Key Insights:")
        for insight in exec_summary["key_insights"]:
            output.append(f"  • {insight}")
        output.append("")
    
    # Current Health
    if dashboard_data["current_health"]:
        health = dashboard_data["current_health"]
        output.append("CURRENT HEALTH METRICS")
        output.append("-" * 30)
        output.append(f"Overall Score: {health['overall_score']:.1f}/100")
        output.append(f"Quality Score: {health['quality_score']:.1f}/100")
        output.append(f"Maintainability: {health['maintainability_score']:.1f}/100")
        output.append(f"Technical Risk: {health['technical_risk_score']:.1f}/100")
        output.append(f"Debt Density: {health['debt_density']:.2f} items/file")
        output.append("")
    
    # Trend Analysis
    trends = dashboard_data["trend_analysis"]
    if trends:
        output.append("TREND ANALYSIS")
        output.append("-" * 30)
        for metric, trend in trends.items():
            direction_symbol = {
                "improving": "↑",
                "declining": "↓", 
                "stable": "→"
            }.get(trend["trend_direction"], "→")
            
            output.append(f"{metric.replace('_', ' ').title()}: {direction_symbol} {trend['trend_direction']}")
            output.append(f"  Change Rate: {trend['change_rate']:.3f} per period")
            output.append(f"  Forecast: {trend['forecast_next_period']:.1f}")
        output.append("")
    
    # Top Recommendations
    recommendations = dashboard_data["recommendations"]
    if recommendations:
        output.append("TOP RECOMMENDATIONS")
        output.append("-" * 30)
        for i, rec in enumerate(recommendations[:5], 1):
            output.append(f"{i}. [{rec['priority'].upper()}] {rec['title']}")
            output.append(f"   {rec['description']}")
            output.append(f"   Impact: {rec['impact']}, Effort: {rec['effort']}")
            output.append("")
    
    return "\n".join(output)


def main():
    """Main entry point for the debt dashboard."""
    parser = argparse.ArgumentParser(description="Generate technical debt dashboard")
    parser.add_argument("files", nargs="*", help="Debt inventory files")
    parser.add_argument("--input-dir", help="Directory containing debt inventory files")
    parser.add_argument("--output", help="Output file path")
    parser.add_argument("--format", choices=["json", "text", "both"], 
                       default="both", help="Output format")
    parser.add_argument("--period", choices=["weekly", "monthly", "quarterly"],
                       default="monthly", help="Analysis period")
    parser.add_argument("--team-size", type=int, default=5, help="Team size")
    
    args = parser.parse_args()
    
    # Initialize dashboard
    dashboard = DebtDashboard(args.team_size)
    
    # Load data
    if args.input_dir:
        success = dashboard.load_from_directory(args.input_dir)
    elif args.files:
        success = dashboard.load_historical_data(args.files)
    else:
        print("Error: Must specify either files or --input-dir")
        sys.exit(1)
    
    if not success:
        sys.exit(1)
    
    # Generate dashboard
    try:
        dashboard_data = dashboard.generate_dashboard(args.period)
    except Exception as e:
        print(f"Dashboard generation failed: {e}")
        sys.exit(1)
    
    # Output results
    if args.format in ["json", "both"]:
        json_output = json.dumps(dashboard_data, indent=2, default=str)
        if args.output:
            output_path = args.output if args.output.endswith('.json') else f"{args.output}.json"
            with open(output_path, 'w') as f:
                f.write(json_output)
            print(f"JSON dashboard written to: {output_path}")
        else:
            print("JSON DASHBOARD:")
            print("=" * 50)
            print(json_output)
    
    if args.format in ["text", "both"]:
        text_output = format_dashboard_report(dashboard_data)
        if args.output:
            output_path = args.output if args.output.endswith('.txt') else f"{args.output}.txt"
            with open(output_path, 'w') as f:
                f.write(text_output)
            print(f"Text dashboard written to: {output_path}")
        else:
            print("\nTEXT DASHBOARD:")
            print("=" * 50)
            print(text_output)


if __name__ == "__main__":
    main()