"""Executive-ready report generator.

Produces human-readable reports from scan results, suitable for
sharing with engineering leadership and product managers.
"""

from __future__ import annotations

import json
import time
from typing import Any


class ReportGenerator:
    """Generate various report formats from scan results."""

    def generate_executive_summary(
        self,
        scan_result: dict[str, Any],
        prioritized_items: list[dict[str, Any]] | None = None,
        trend: dict[str, Any] | None = None,
    ) -> str:
        """Generate a text-based executive summary.

        Args:
            scan_result: Output from Scanner.scan().
            prioritized_items: Optional prioritized items from Prioritizer.
            trend: Optional trend analysis.
        """
        lines: list[str] = []
        lines.append("=" * 60)
        lines.append("  DEBTMAP — Technical Debt Report")
        lines.append("=" * 60)
        lines.append("")
        lines.append(f"Repository: {scan_result.get('repo_path', 'unknown')}")
        lines.append(f"Branch: {scan_result.get('branch', 'unknown')}")
        lines.append(f"Commit: {scan_result.get('commit_sha', 'unknown')}")
        lines.append(f"Scan ID: {scan_result.get('scan_id', 'unknown')}")
        lines.append(f"Date: {time.strftime('%Y-%m-%d %H:%M:%S')}")
        lines.append("")

        # Overall score
        score = scan_result.get("total_score", 0)
        grade = self._score_to_grade(score)
        lines.append(f"Overall Debt Score: {score}/100  Grade: {grade}")
        lines.append(f"Files Scanned: {scan_result.get('file_count', 0)}")
        lines.append(f"Total Issues: {scan_result.get('total_issues', 0)}")
        lines.append("")

        # Summary by category
        summary = scan_result.get("summary", {})
        lines.append("-" * 40)
        lines.append("  ANALYSIS BREAKDOWN")
        lines.append("-" * 40)

        cx = summary.get("complexity", {})
        lines.append(f"\nComplexity:")
        lines.append(f"  Functions analyzed: {cx.get('total_functions', 0)}")
        lines.append(f"  Avg complexity: {cx.get('avg_complexity', 0)}")
        lines.append(f"  Complex+ functions: {cx.get('complex_count', 0) + cx.get('very_complex_count', 0) + cx.get('unmaintainable_count', 0)}")

        cp = summary.get("coupling", {})
        lines.append(f"\nCoupling:")
        lines.append(f"  Modules analyzed: {cp.get('total_modules', 0)}")
        lines.append(f"  Highly coupled: {cp.get('highly_coupled_count', 0)}")
        lines.append(f"  Circular deps: {cp.get('circular_dependencies', 0)}")

        dp = summary.get("duplication", {})
        lines.append(f"\nDuplication:")
        lines.append(f"  Duplicate blocks: {dp.get('duplicate_block_count', 0)}")
        lines.append(f"  Duplicate lines: {dp.get('total_duplicate_lines', 0)}")

        dc = summary.get("dead_code", {})
        lines.append(f"\nDead Code:")
        lines.append(f"  Total items: {dc.get('total_dead_code_items', 0)}")
        lines.append(f"  Unused functions: {dc.get('unused_functions', 0)}")
        lines.append(f"  Unused imports: {dc.get('unused_imports', 0)}")

        tc = summary.get("test_coverage", {})
        lines.append(f"\nTest Coverage Gaps:")
        lines.append(f"  Uncovered items: {tc.get('total_uncovered_items', 0)}")
        lines.append(f"  Files with gaps: {tc.get('files_with_gaps', 0)}")

        doc = summary.get("documentation", {})
        lines.append(f"\nDocumentation Gaps:")
        lines.append(f"  Missing docs: {doc.get('total_missing_docs', 0)}")

        dep = summary.get("dependencies", {})
        lines.append(f"\nDependencies:")
        lines.append(f"  Total: {dep.get('total_dependencies', 0)}")
        lines.append(f"  Outdated: {dep.get('outdated_count', 0)}")
        lines.append(f"  Critical: {dep.get('critical_outdated', 0)}")

        # Trend
        if trend:
            lines.append("")
            lines.append("-" * 40)
            lines.append("  TREND")
            lines.append("-" * 40)
            direction = trend.get("direction", "unknown")
            change = trend.get("score_change", 0)
            change_pct = trend.get("score_change_pct", 0)
            arrow = {"improving": "v", "degrading": "^", "stable": "-"}.get(direction, "?")
            lines.append(f"  Direction: {direction} {arrow}")
            lines.append(f"  Score change: {change:+.1f} ({change_pct:+.1f}%)")
            lines.append(f"  Period: {trend.get('period_days', 0):.0f} days")

        # Top priorities
        if prioritized_items:
            lines.append("")
            lines.append("-" * 40)
            lines.append("  TOP PRIORITIES (by ROI)")
            lines.append("-" * 40)
            for item in prioritized_items[:10]:
                roi = item.get("roi_months", 999)
                savings = item.get("annual_savings_usd", 0)
                effort = item.get("fix_effort_hours", 0)
                lines.append(
                    f"\n  #{item.get('priority_rank', '?')} [{item.get('severity', '?').upper()}] "
                    f"{item.get('issue_type', '?')}"
                )
                lines.append(f"     File: {item.get('file_path', '?')}")
                lines.append(f"     {item.get('description', '')}")
                lines.append(f"     Fix: {effort:.0f}h | Saves: ${savings:,.0f}/yr | ROI: {roi:.1f}mo")

        lines.append("")
        lines.append("=" * 60)
        lines.append(f"  Generated by DebtMap v0.1.0")
        lines.append("=" * 60)

        return "\n".join(lines)

    def generate_json_report(
        self,
        scan_result: dict[str, Any],
        prioritized_items: list[dict[str, Any]] | None = None,
        trend: dict[str, Any] | None = None,
    ) -> str:
        """Generate a JSON report."""
        report = {
            "report_type": "debtmap_scan",
            "generated_at": time.strftime("%Y-%m-%dT%H:%M:%SZ"),
            "scan": scan_result,
        }
        if prioritized_items:
            report["priorities"] = prioritized_items
        if trend:
            report["trend"] = trend

        return json.dumps(report, indent=2, default=str)

    def _score_to_grade(self, score: float) -> str:
        """Convert 0-100 debt score to letter grade (A = best)."""
        if score <= 10:
            return "A"
        elif score <= 25:
            return "B"
        elif score <= 50:
            return "C"
        elif score <= 75:
            return "D"
        return "F"
