"""complyform explain command — explain compliance findings in plain language."""

from __future__ import annotations

import json
import sys
from typing import TYPE_CHECKING, Annotated

import typer
from rich.panel import Panel

from complyform.cli.main import AppContext, app
from complyform.core.errors import (
    AIExplainAPIError,
    ExplainAmbiguousControlError,
    ExplainFindingNotFoundError,
    ExplainNoAssessmentError,
)

if TYPE_CHECKING:
    from complyform.core.assessor.control_matcher import Finding
    from complyform.core.explainer.models import Explanation

_BF = "Brownfield (Existing Infrastructure)"


@app.command(name="explain", rich_help_panel=_BF)
def explain_cmd(
    ctx: typer.Context,
    control_id: Annotated[
        str,
        typer.Argument(help="Control ID to explain (e.g. '1.1', 'CC1.1')"),
    ],
    frameworks: Annotated[
        str | None,
        typer.Option(
            "--frameworks",
            "-f",
            help="Framework ID (required if ambiguous)",
        ),
    ] = None,
    ai: Annotated[
        bool,
        typer.Option(
            "--ai",
            help="Use AI-enhanced explanation (Pro+ tier)",
        ),
    ] = False,
    format: Annotated[
        str,
        typer.Option("--format", help="Output format: terminal, json"),
    ] = "terminal",
) -> None:
    """Explain a compliance finding in plain language."""
    app_ctx: AppContext = ctx.obj

    finding = _resolve_finding(control_id, frameworks)
    explanation = _generate_explanation(finding, ai=ai, config=app_ctx.config)

    if format == "json":
        _output_json(explanation, ai=ai)
    else:
        _output_terminal(app_ctx, explanation)


def _resolve_finding(control_id: str, frameworks: str | None) -> Finding:
    """Find matching finding from cached assessment."""
    from complyform.core.cache import ScanCache

    cache = ScanCache()
    cached = cache.latest()
    if cached is None:
        raise ExplainNoAssessmentError()

    _resources, cache_meta = cached

    findings = _load_cached_findings(cache_meta)
    if findings is None:
        raise ExplainNoAssessmentError()

    matches = [f for f in findings if f.control_id == control_id]

    if frameworks:
        matches = [f for f in matches if f.framework == frameworks]

    if not matches:
        raise ExplainFindingNotFoundError(control_id)

    frameworks_found = list({f.framework for f in matches})
    if len(frameworks_found) > 1 and frameworks is None:
        raise ExplainAmbiguousControlError(control_id, frameworks_found)

    return matches[0]


def _load_cached_findings(
    cache_meta: dict[str, object],
) -> list[Finding] | None:
    """Load findings from the assess cache directory."""
    import json as json_mod
    from pathlib import Path

    from complyform.core.assessor.control_matcher import Finding

    cache_dir = Path.home() / ".complyform" / "cache"
    if not cache_dir.exists():
        return None

    for entry_dir in sorted(cache_dir.iterdir(), reverse=True):
        if not entry_dir.is_dir():
            continue
        findings_path = entry_dir / "findings.json"
        if findings_path.exists():
            raw = json_mod.loads(findings_path.read_text(encoding="utf-8"))
            return [Finding.model_validate(f) for f in raw]

    return None


def _generate_explanation(
    finding: Finding,
    *,
    ai: bool,
    config: object,
) -> Explanation:
    """Generate explanation — deterministic or AI-enhanced."""
    from complyform.core.explainer.deterministic import (
        explain_finding,
    )

    if not ai:
        return explain_finding(finding)

    from complyform.core.auth.license import LicenseManager
    from complyform.core.auth.tier_enforcement import (
        check_feature,
        enforce_with_refresh,
    )
    from complyform.core.config import ComplyFormConfig
    from complyform.core.explainer.ai_enhanced import (
        ai_explain_finding,
        resolve_api_key,
    )

    license_mgr = LicenseManager()
    tier_info = license_mgr.resolve_tier_info()
    enforce_with_refresh(
        license_mgr,
        tier_info,
        check_feature,
        "ai_explain",
        tier_info,
    )

    cfg = config if isinstance(config, ComplyFormConfig) else ComplyFormConfig()
    api_key = resolve_api_key(cfg.anthropic_api_key)

    try:
        return ai_explain_finding(finding, api_key=api_key)
    except AIExplainAPIError as exc:
        import sys

        print(
            f"Warning: {exc.message} {exc.fix}",
            file=sys.stderr,
        )
        return explain_finding(finding)


def _output_terminal(app_ctx: AppContext, explanation: Explanation) -> None:
    """Render explanation as Rich panel to stderr."""
    console = app_ctx.console
    if app_ctx.quiet:
        return

    status_icon = {
        "PASS": "[green]PASS[/green]",
        "FAIL": "[red]FAIL[/red]",
        "MANUAL_REVIEW": "[yellow]MANUAL REVIEW[/yellow]",
        "NOT_ASSESSED": "[dim]NOT ASSESSED[/dim]",
    }.get(explanation.status, explanation.status)

    body_parts = [
        f"[bold]Status:[/bold] {status_icon}",
        f"[bold]Severity:[/bold] {explanation.severity}",
        f"[bold]Resource:[/bold] {explanation.resource_address}",
        "",
        f"[bold]Summary[/bold]\n{explanation.summary}",
        "",
        (f"[bold]Why It Matters[/bold]\n{explanation.why_it_matters}"),
        "",
        (f"[bold]Severity Rationale[/bold]\n{explanation.severity_rationale}"),
        "",
        (f"[bold]Remediation Hint[/bold]\n{explanation.remediation_hint}"),
    ]

    if explanation.ai_generated:
        body_parts.append("")
        label = "[dim]AI-generated[/dim]"
        if explanation.model:
            label += f" [dim]({explanation.model})[/dim]"
        if explanation.cached:
            label += " [dim](cached)[/dim]"
        body_parts.append(label)

    body = "\n".join(body_parts)
    title = f"Explain: {explanation.control_id} ({explanation.framework})"
    style = "green" if explanation.status == "PASS" else "red"
    console.print(Panel(body, title=title, style=style))


def _output_json(explanation: Explanation, *, ai: bool) -> None:
    """Write explanation as JSON to stdout."""
    from complyform import __version__

    envelope = {
        "schema_version": 1,
        "tool": "complyform",
        "tool_version": __version__,
        "command": "explain",
        "timestamp": _iso_now(),
        "target": explanation.control_id,
        "framework": explanation.framework,
        "mode": "ai_enhanced" if ai else "deterministic",
        "explanation": {
            "summary": explanation.summary,
            "why_it_matters": explanation.why_it_matters,
            "severity_rationale": explanation.severity_rationale,
            "remediation_hint": explanation.remediation_hint,
            "ai_generated": explanation.ai_generated,
            "model": explanation.model,
        },
    }
    sys.stdout.write(json.dumps(envelope, indent=2) + "\n")


def _iso_now() -> str:
    from datetime import UTC, datetime

    return datetime.now(UTC).isoformat()


def explain_findings_inline(
    findings: list[Finding],
) -> list[Explanation]:
    """Generate deterministic explanations for FAIL findings.

    Used by assess --explain integration.
    """
    from complyform.core.explainer.deterministic import (
        explain_finding,
    )

    return [explain_finding(f) for f in findings if f.status == "FAIL"]
