"""SPEC-006 interactive patch review with colored diffs."""

from __future__ import annotations

from typing import TYPE_CHECKING

from rich.prompt import Prompt
from rich.syntax import Syntax

if TYPE_CHECKING:
    from rich.console import Console

    from complyform.core.assessor.control_matcher import Finding
    from complyform.core.remediator.patch_generator import PatchFile


def present_patch_for_review(
    patch: PatchFile,
    finding: Finding,
    console: Console,
    *,
    index: int = 1,
    total: int = 1,
) -> bool | None:
    """Display a colored diff and prompt accept/skip/quit.

    Returns True if accepted, False if skipped, None if quit.
    """
    header = f"Patch {index}/{total}: {patch.control_id} — {patch.resource_address}"
    console.rule(header)
    console.print(
        f"Severity: [bold]{finding.severity}[/bold]"
        f" | Framework: {finding.framework}"
        f" | Strategy: {patch.strategy}"
    )
    console.print()

    if patch.diff:
        syntax = Syntax(patch.diff, "diff", theme="monokai")
        console.print(syntax)
    else:
        syntax = Syntax(patch.content, "hcl", theme="monokai")
        console.print(syntax)

    console.print()
    choice = Prompt.ask(
        "[a]ccept  [s]kip  [q]uit",
        choices=["a", "s", "q"],
        default="s",
        console=console,
    )

    if choice == "a":
        return True
    if choice == "q":
        return None
    return False


def run_interactive_review(
    patches: list[PatchFile],
    findings: list[Finding],
    console: Console,
) -> list[PatchFile]:
    """Run interactive review loop over all patches.

    Returns only accepted patches. If user quits, returns
    patches accepted so far.
    """
    finding_map: dict[str, Finding] = {}
    for f in findings:
        key = f"{f.control_id}:{f.resource_address}"
        finding_map[key] = f

    accepted: list[PatchFile] = []
    total = len(patches)

    for i, patch in enumerate(patches, 1):
        key = f"{patch.control_id}:{patch.resource_address}"
        finding = finding_map.get(key)
        if finding is None:
            # Fallback: find by control_id only
            for f in findings:
                if f.control_id == patch.control_id:
                    finding = f
                    break

        if finding is None:
            continue

        result = present_patch_for_review(
            patch,
            finding,
            console,
            index=i,
            total=total,
        )

        if result is None:
            break
        if result:
            accepted.append(patch)

    return accepted
