"""Flow repair — detect stale flow steps and AI-propose replacements."""

from __future__ import annotations

import click
from rich.console import Console

from maeris_mcp.drift_detector import detect_flow_drift
from maeris_mcp.drift_detector.models import DriftIssue, DriftKind, RepairResult


async def repair_flow(
    client,
    model: str,
    dry_run: bool,
    yes: bool,
) -> RepairResult:
    """Detect stale flow steps and AI-propose replacement APIs.

    For FLOW_STEP_STALE: ask AI which active API should replace the dead step.
    For FLOW_STEP_METHOD_MISMATCH: report but do not auto-patch (human decision).

    Args:
        client: Active MaerisClient.
        model: Claude model for suggestions.
        dry_run: Print proposals but do not apply.
        yes: Auto-approve all suggestions.

    Returns:
        RepairResult with fixed/skipped/failed counts.
    """
    from maeris_mcp.ai_adapter.repair_suggestions import suggest_flow_fix

    report = await detect_flow_drift(client)
    result = RepairResult()
    console = Console()

    if not report.has_drift:
        return result

    # Fetch all APIs once (needed for replacement suggestions)
    all_apis = await client.get_all_apis()

    total = len(report.issues)

    for i, issue in enumerate(report.issues, 1):
        label = f"[{i}/{total}]"
        click.echo(f"\n  {label} {issue.description}")

        if issue.kind == DriftKind.FLOW_STEP_METHOD_MISMATCH:
            click.secho(
                "  → Method mismatch — please review manually and update the flow step.",
                fg="yellow",
            )
            result.skipped += 1
            continue

        # FLOW_STEP_STALE: step references deleted API
        try:
            with console.status(f"  [bold cyan]Analyzing…", spinner="dots"):
                fix = suggest_flow_fix(issue, all_apis, model)
        except Exception as e:
            click.secho(f"  ✗ AI suggestion failed: {e}", fg="red")
            result.failed += 1
            continue

        action = fix.get("action", "ignore")
        replacement_id = fix.get("replacement_api_id", "")
        reason = fix.get("reason", "")

        click.echo(f"  AI recommends: {click.style(action, bold=True)}")
        if reason:
            click.echo(f"  Reason: {reason}")
        if replacement_id:
            rep_api = next(
                (a for a in all_apis
                 if str(a.get("api_id") or a.get("_id", "")) == replacement_id),
                None,
            )
            rep_name = rep_api.get("name", replacement_id) if rep_api else replacement_id
            click.echo(
                f"  Replacement: {click.style(rep_name, fg='green')} (ID: {replacement_id})"
            )

        if action == "ignore" or dry_run:
            if dry_run and action != "ignore":
                click.secho("  [dry-run] Would apply this action.", fg="cyan")
            result.skipped += 1
            continue

        # Confirm each action individually unless --yes was passed
        if not yes:
            try:
                if not click.confirm(f"  Apply '{action}'?", default=True):
                    click.echo("  Skipped.")
                    result.skipped += 1
                    continue
            except click.Abort:
                click.echo("  Skipped.")
                result.skipped += 1
                continue

        flow_id = issue.resource_id
        step_index = issue.detail.get("step_index", 0)

        try:
            if action == "replace" and replacement_id:
                step = dict(issue.detail.get("step", {}))
                step["api_id"] = replacement_id
                step.pop("child_id", None)
                await client.update_flow_step(flow_id, step_index, step)
                click.secho("  ✓ Flow step updated.", fg="green")
                result.fixed += 1
            elif action == "delete":
                await client.delete_flow_step(flow_id, step_index)
                click.secho("  ✓ Stale step removed from flow.", fg="green")
                result.fixed += 1
            else:
                result.skipped += 1
        except Exception as e:
            click.secho(f"  ✗ Failed to apply: {e}", fg="red")
            result.failed += 1

    return result
