"""
HLD Renderer — produces the final Markdown HLD document.

Outputs:
  1. hld_report.md    — full High-Level Design document
  2. architecture.mmd  — standalone Mermaid diagram
  3. graph_summary.md  — raw code graph statistics
"""

from __future__ import annotations

import logging
from datetime import datetime, timezone
from pathlib import Path

from hld_generator import __version__
from hld_generator.graph import CodeGraph, GraphBuilder
from hld_generator.llm import LLMAnalysis

logger = logging.getLogger(__name__)


class HLDRenderer:
    """Render analysis results into Markdown files."""

    def __init__(self, output_dir: Path) -> None:
        self.output_dir = output_dir
        self.output_dir.mkdir(parents=True, exist_ok=True)

    def render(self, analysis: LLMAnalysis, code_graph: CodeGraph) -> list[Path]:
        """Generate all output files and return their paths."""
        files: list[Path] = []

        files.append(self._render_hld_report(analysis, code_graph))
        files.append(self._render_mermaid(analysis, code_graph))
        files.append(self._render_graph_summary(code_graph))

        return files

    # ── HLD Report ─────────────────────────────────────────────────────────

    def _render_hld_report(self, analysis: LLMAnalysis, cg: CodeGraph) -> Path:
        path = self.output_dir / "hld_report.md"
        now = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC")

        sections: list[str] = []
        sec = 1  # running section counter

        # Title
        sections.append(f"# {analysis.project_name} — High-Level Design\n")
        sections.append(f"> Generated on {now} by **HLD Generator** v{__version__}\n")

        # Overview
        sections.append(f"## {sec}. Overview\n")
        sections.append(f"{analysis.summary}\n")
        if analysis.architecture_pattern:
            sections.append(f"**Architecture Pattern:** {analysis.architecture_pattern}\n")
        sec += 1

        # Tech Stack
        if analysis.tech_stack:
            sections.append(f"## {sec}. Technology Stack\n")
            ts = analysis.tech_stack
            if ts.get("languages"):
                sections.append(f"**Languages:** {', '.join(ts['languages'])}\n")
            if ts.get("frameworks"):
                sections.append(f"**Frameworks:** {', '.join(ts['frameworks'])}\n")
            if ts.get("databases"):
                sections.append(f"**Databases:** {', '.join(ts['databases'])}\n")
            if ts.get("infrastructure"):
                sections.append(f"**Infrastructure:** {', '.join(ts['infrastructure'])}\n")
            sec += 1

        # Codebase Statistics
        sections.append(f"## {sec}. Codebase Statistics\n")
        sections.append("| Metric | Value |")
        sections.append("|--------|-------|")
        sections.append(f"| Total Modules | {len(cg.modules)} |")
        sections.append(f"| Total Lines of Code | {cg.total_lines:,} |")
        sections.append(f"| Packages / Directories | {len(cg.packages)} |")
        sections.append(f"| Dependency Edges | {cg.graph.number_of_edges()} |")
        sections.append(f"| Languages | {', '.join(cg.languages.keys())} |")
        sections.append("")
        sec += 1

        # Architecture Diagram
        sections.append(f"## {sec}. Architecture Diagram\n")
        mermaid = analysis.mermaid_diagram or self._default_mermaid_note()
        sections.append(f"```mermaid\n{mermaid}\n```\n")
        sections.append("*See `architecture.mmd` for the standalone Mermaid file.*\n")
        sec += 1

        # Components
        if analysis.components:
            sections.append(f"## {sec}. Components\n")
            for i, comp in enumerate(analysis.components, 1):
                sections.append(f"### {sec}.{i}. {comp.get('name', 'Unknown')}\n")
                sections.append(f"**Layer:** {comp.get('layer', 'N/A')}\n")
                sections.append(f"{comp.get('purpose', '')}\n")
                modules = comp.get("key_modules", [])
                if modules:
                    sections.append("**Key modules:**\n")
                    for m in modules[:10]:
                        sections.append(f"- `{m}`")
                    sections.append("")
            sec += 1

        # Data Flow
        if analysis.data_flow:
            sections.append(f"## {sec}. Data Flow\n")
            sections.append("| From | To | Description |")
            sections.append("|------|----|-------------|")
            for flow in analysis.data_flow:
                sections.append(
                    f"| {flow.get('from', '')} | {flow.get('to', '')} | {flow.get('description', '')} |"
                )
            sections.append("")
            sec += 1

        # External Dependencies
        if analysis.external_dependencies:
            sections.append(f"## {sec}. External Dependencies\n")
            sections.append("| Dependency | Purpose |")
            sections.append("|-----------|---------|")
            for dep in analysis.external_dependencies:
                sections.append(f"| {dep.get('name', '')} | {dep.get('purpose', '')} |")
            sections.append("")
            sec += 1

        # Entry Points
        if cg.entry_points:
            sections.append(f"## {sec}. Entry Points\n")
            for ep in cg.entry_points[:20]:
                sections.append(f"- `{ep}`")
            sections.append("")
            sec += 1

        # API Endpoints
        all_endpoints = [
            (mid, ep)
            for mid, mod in cg.modules.items()
            for ep in mod.endpoints
        ]
        if all_endpoints:
            sections.append(f"## {sec}. API Endpoints\n")
            sections.append("| Route | Module |")
            sections.append("|-------|--------|")
            for mid, ep in all_endpoints[:50]:
                sections.append(f"| `{ep}` | `{mid}` |")
            sections.append("")
            sec += 1

        # Observations
        if analysis.observations:
            sections.append(f"## {sec}. Observations & Recommendations\n")
            for obs in analysis.observations:
                sections.append(f"- {obs}")
            sections.append("")

        # Errors
        if analysis.error:
            sections.append("---\n")
            sections.append(f"⚠️ **LLM Analysis Note:** {analysis.error}\n")

        path.write_text("\n".join(sections), encoding="utf-8")
        logger.info("Wrote HLD report: %s", path)
        return path

    # ── Mermaid ────────────────────────────────────────────────────────────

    def _render_mermaid(self, analysis: LLMAnalysis, cg: CodeGraph) -> Path:
        path = self.output_dir / "architecture.mmd"
        diagram = analysis.mermaid_diagram
        if not diagram:
            diagram = "graph TD\n    A[No diagram generated] --> B[Run with --provider anthropic or openai]"
        path.write_text(diagram, encoding="utf-8")
        logger.info("Wrote Mermaid diagram: %s", path)
        return path

    # ── Graph summary ──────────────────────────────────────────────────────

    def _render_graph_summary(self, cg: CodeGraph) -> Path:
        path = self.output_dir / "graph_summary.md"
        content = GraphBuilder.graph_summary(cg)
        path.write_text(content, encoding="utf-8")
        logger.info("Wrote graph summary: %s", path)
        return path

    @staticmethod
    def _default_mermaid_note() -> str:
        return "graph TD\n    A[No LLM analysis] --> B[Provide an API key for architecture diagrams]"
