"""Documentation artifact generator.

Three output formats:
- mermaid:          architecture diagram as Mermaid DSL
- architecture_md:  full architecture.md with embedded diagram
- onboarding_guide: markdown guide (stack + modules + decisions + gotchas + quick start)

Sections 1-5 are deterministic; quick-start prose is LLM-parameterized.
"""

from __future__ import annotations

import datetime
import logging

from core.engine.core.db import parse_rows, pool

logger = logging.getLogger(__name__)


async def generate_docs(
    format: str = "onboarding_guide",
    product_id: str = "product:platform",
    output_path: str | None = None,
) -> dict:
    """Generate documentation artifact for the given format.

    Returns: {format, output_path, content, sections_generated, warnings}
    """
    warnings: list[str] = []

    if format == "mermaid":
        content = await generate_architecture_diagram(product_id)
        default_path = "docs/architecture.mmd"
    elif format == "architecture_md":
        diagram = await generate_architecture_diagram(product_id)
        content = f"# Architecture\n\n```mermaid\n{diagram}\n```\n"
        default_path = "docs/architecture.md"
    elif format == "onboarding_guide":
        content, sections = await generate_onboarding_guide(product_id)
        default_path = "docs/onboarding.md"
    else:
        return {"error": f"Unknown format {format!r}"}

    if not content:
        warnings.append(f"Empty content generated for format={format!r} — graph may need scanning first.")

    out_path = output_path or default_path
    if output_path and content:
        import os

        os.makedirs(os.path.dirname(output_path) or ".", exist_ok=True)
        with open(output_path, "w") as f:
            f.write(content)

    return {
        "format": format,
        "output_path": out_path,
        "content": content,
        "sections_generated": sections if format == "onboarding_guide" else [format],
        "warnings": warnings,
    }


async def generate_architecture_diagram(product_id: str) -> str:
    """Generate Mermaid architecture diagram from capability graph.

    Wraps engine/reports/diagrams.py DiagramGenerator.mermaid_architecture_map().
    Falls back to minimal diagram if no capabilities exist.
    """
    try:
        from core.engine.reports.diagrams import DiagramGenerator

        async with pool.connection() as db:
            caps = parse_rows(
                await db.query(
                    "SELECT slug, name, category FROM capability WHERE product = <record>$product",
                    {"product": product_id},
                )
            )

        gen = DiagramGenerator()
        diagram = gen.mermaid_architecture_map(caps)
        return diagram if diagram else _minimal_mermaid(product_id)
    except Exception as exc:
        logger.debug("generate_architecture_diagram failed: %s", exc)
        return _minimal_mermaid(product_id)


def _minimal_mermaid(product_id: str) -> str:
    slug = product_id.split(":")[-1]
    return f"flowchart LR\n    {slug}[{slug}]\n"


async def generate_onboarding_guide(product_id: str) -> tuple[str, list[str]]:
    """Generate onboarding guide for new developers.

    Sections (1-5 deterministic, 6 LLM-parameterized):
    1. Stack overview
    2. Module map (capability categories)
    3. Key decisions
    4. Known gotchas
    5. Development workflow
    6. Quick start (LLM)

    Returns: (markdown_content, sections_generated)
    """
    sections_generated: list[str] = []
    parts: list[str] = []
    today = datetime.date.today().isoformat()

    parts.append(f"# Developer Onboarding Guide\n*Generated by ACE on {today}*\n")

    # 1. Stack
    stack_table = await _build_stack_table(product_id)
    if stack_table:
        parts.append(f"## Stack\n\n{stack_table}\n")
        sections_generated.append("stack")

    # 2. Architecture diagram
    diagram = await generate_architecture_diagram(product_id)
    parts.append(f"## Architecture\n\n```mermaid\n{diagram}\n```\n")
    sections_generated.append("architecture")

    # 3. Key decisions
    decisions_md = await _build_decisions_section(product_id)
    if decisions_md:
        parts.append(f"## Key Decisions\n\n{decisions_md}\n")
        sections_generated.append("key_decisions")

    # 4. Known gotchas
    gotchas_md = await _build_gotchas_section(product_id)
    if gotchas_md:
        parts.append(f"## Known Gotchas\n\n{gotchas_md}\n")
        sections_generated.append("known_gotchas")

    # 5. Development workflow (static for now; E3a integration in v2)
    workflow = _default_workflow()
    parts.append(f"## Development Workflow\n\n{workflow}\n")
    sections_generated.append("development_workflow")

    # 6. Quick start (LLM-generated from context)
    quick_start = await _generate_quick_start(product_id, stack_table)
    if quick_start:
        parts.append(f"## Quick Start\n\n{quick_start}\n")
        sections_generated.append("quick_start")

    return "\n".join(parts), sections_generated


async def _build_stack_table(product_id: str) -> str:
    try:
        async with pool.connection() as db:
            rows = parse_rows(
                await db.query(
                    "SELECT language, count() AS n FROM graph_file "
                    "WHERE graph_id = 'default' GROUP BY language ORDER BY n DESC"
                )
            )
        if not rows:
            return ""
        lines = ["| Language | Files |", "|----------|-------|"]
        for r in rows[:10]:
            lang = r.get("language") or "unknown"
            lines.append(f"| {lang} | {r.get('n', 0)} |")
        return "\n".join(lines)
    except Exception:
        return ""


async def _build_decisions_section(product_id: str) -> str:
    try:
        async with pool.connection() as db:
            rows = parse_rows(
                await db.query(
                    "SELECT title, decision_type, rationale FROM decision "
                    "WHERE product = <record>$product AND outcome = 'accepted' "
                    "ORDER BY created_at DESC LIMIT 10",
                    {"product": product_id},
                )
            )
        if not rows:
            return ""
        lines = []
        for r in rows:
            title = r.get("title", "")
            rationale = (r.get("rationale") or "")[:120]
            dtype = r.get("decision_type", "")
            lines.append(f"- **{title}** `[{dtype}]`")
            if rationale:
                lines.append(f"  *{rationale}*")
        return "\n".join(lines)
    except Exception:
        return ""


async def _build_gotchas_section(product_id: str) -> str:
    try:
        async with pool.connection() as db:
            rows = parse_rows(
                await db.query(
                    "SELECT content, confidence FROM insight "
                    "WHERE product = <record>$product AND confidence >= 0.8 "
                    "ORDER BY confidence DESC LIMIT 8",
                    {"product": product_id},
                )
            )
        if not rows:
            return ""
        lines = []
        for r in rows:
            content = (r.get("content") or "")[:200]
            if content:
                lines.append(f"- {content}")
        return "\n".join(lines)
    except Exception:
        return ""


def _default_workflow() -> str:
    return """\
```bash
# Install
uv install

# Run tests (fast gate)
make test-fast

# Start dev server
make dev

# Before committing: export decision lockfile
ace_export_decisions
```"""


async def _generate_quick_start(product_id: str, stack_table: str) -> str:
    """LLM-generated quick-start section from stack + graph context."""
    try:
        from core.engine.core.db import parse_rows, pool
        from core.engine.core.llm import get_llm

        async with pool.connection() as db:
            cap_rows = parse_rows(
                await db.query(
                    "SELECT slug, name FROM capability WHERE product = <record>$product LIMIT 5",
                    {"product": product_id},
                )
            )

        cap_names = ", ".join(r.get("name") or r.get("slug", "") for r in cap_rows[:5])
        prompt = (
            f"Write a 3-5 step quick-start for a developer joining this project.\n"
            f"Stack:\n{stack_table or 'Python'}\n"
            f"Key capabilities: {cap_names or 'unknown'}\n"
            f"Be concise. Use numbered steps. Include one concrete command per step."
        )
        llm = get_llm(model="haiku")
        response = await llm.complete(prompt, max_tokens=300)
        return response.strip() if response else ""
    except Exception as exc:
        logger.debug("Quick-start LLM call failed (non-fatal): %s", exc)
        return ""
