"""complyform fix command — SPEC-005 remediate → validate pipeline."""

from __future__ import annotations

import sys
from typing import Annotated

import typer

from complyform.cli.exit_codes import EXIT_SUCCESS
from complyform.cli.main import AppContext, app
from complyform.core.errors import (
    InteractiveNotTTYError,
    InteractivePRConflictError,
    PRFlagConflictError,
)

_BF = "Brownfield (Existing Infrastructure)"

_STUB_FLAGS = (
    "estimate_cost",
    "iam_analysis",
)


@app.command(name="fix", rich_help_panel=_BF)
def fix_cmd(  # noqa: PLR0913
    ctx: typer.Context,
    # --- Remediate flags ---
    frameworks: Annotated[
        str,
        typer.Option(help="Comma-separated framework IDs"),
    ] = "",
    controls: Annotated[
        str,
        typer.Option(help="Comma-separated control IDs"),
    ] = "",
    output: Annotated[
        str,
        typer.Option(help="Output directory for .tf patch files"),
    ] = "./patches",
    dry_run: Annotated[
        bool,
        typer.Option(
            "--dry-run",
            help="Preview patches without writing",
        ),
    ] = False,
    format: Annotated[
        str,
        typer.Option(
            "--format",
            help="Output format: terminal, json",
        ),
    ] = "terminal",
    estimate_cost: Annotated[
        bool,
        typer.Option(
            "--estimate-cost",
            help="Estimate remediation cost",
        ),
    ] = False,
    iam_analysis: Annotated[
        bool,
        typer.Option(
            "--iam-analysis",
            help="Include IAM analysis",
        ),
    ] = False,
    open_pr: Annotated[
        bool,
        typer.Option(
            "--open-pr",
            help="Open a pull request with patches",
        ),
    ] = False,
    pr_branch: Annotated[
        str | None,
        typer.Option("--pr-branch", help="PR branch name"),
    ] = None,
    pr_repo: Annotated[
        str | None,
        typer.Option("--pr-repo", help="PR target repo"),
    ] = None,
    pr_base: Annotated[
        str | None,
        typer.Option("--pr-base", help="PR base branch"),
    ] = None,
    pr_title: Annotated[
        str | None,
        typer.Option("--pr-title", help="PR title"),
    ] = None,
    pr_draft: Annotated[
        bool,
        typer.Option("--pr-draft", help="Create as draft PR"),
    ] = False,
    interactive: Annotated[
        bool,
        typer.Option(
            "--interactive",
            help="Interactive review mode",
        ),
    ] = False,
    # --- Validate flags ---
    fix_auto: Annotated[
        bool,
        typer.Option(
            "--fix",
            help="Auto-apply safe remediations",
        ),
    ] = False,
) -> None:
    """Remediate + validate pipeline.

    Generates patches then validates them.
    Exit code from validate phase.
    """
    from complyform.core.auth.license import LicenseManager
    from complyform.core.auth.tier_enforcement import (
        check_framework_access,
        enforce_with_refresh,
    )

    # Mutual exclusivity
    if interactive and open_pr:
        raise InteractivePRConflictError()
    if interactive and format == "json":
        raise InteractivePRConflictError(
            "Cannot combine --interactive with --format=json."
        )
    if interactive and not sys.stdin.isatty():
        raise InteractiveNotTTYError()

    license_mgr = LicenseManager()
    tier_info = license_mgr.resolve_tier_info()

    # Tier gate: same as remediate (fix = remediate + validate pipeline)
    fw_ids = [f.strip() for f in frameworks.split(",") if f.strip()]
    if fw_ids:
        tier_info = enforce_with_refresh(
            license_mgr,
            tier_info,
            check_framework_access,
            fw_ids,
            "remediate",
            tier_info,
        )

    # Multi-state remediate tier gate
    from complyform.core.cache import ScanCache

    cache = ScanCache()
    cached = cache.latest()
    if cached is not None:
        _resources, _meta = cached
        source_states = {r.source_state for r in _resources}
        if len(source_states) > 1:
            from complyform.core.auth.tier_enforcement import check_feature

            tier_info = enforce_with_refresh(
                license_mgr,
                tier_info,
                check_feature,
                "multi_state_remediate",
                tier_info,
            )

    # Stub flags
    for flag_name in _STUB_FLAGS:
        if locals()[flag_name]:
            typer.echo("Coming in a future release", err=True)
            raise typer.Exit(code=0)

    # --pr-* flags require --open-pr
    for pr_flag, pr_val in (
        ("pr-branch", pr_branch),
        ("pr-repo", pr_repo),
        ("pr-base", pr_base),
        ("pr-title", pr_title),
        ("pr-draft", pr_draft),
    ):
        if pr_val and not open_pr:
            raise PRFlagConflictError(pr_flag)

    from complyform.cli.remediate_cmd import _open_pr, _run_remediate

    # Run remediate phase
    patches, findings, cloud_val = _run_remediate(
        ctx=ctx,
        frameworks_str=frameworks,
        controls_str=controls,
        output_dir=output,
        dry_run=dry_run,
        format=format,
        interactive=interactive,
    )

    if open_pr:
        from complyform.core.errors import PRTokenMissingError

        app_ctx: AppContext = ctx.obj
        _gh_token = app_ctx.config.github_token
        if not _gh_token:
            raise PRTokenMissingError()
        _open_pr(
            ctx=ctx,
            patches=patches,
            findings=findings,
            cloud=cloud_val,
            frameworks_str=frameworks,
            github_token=_gh_token,
            pr_branch=pr_branch,
            pr_repo=pr_repo,
            pr_base=pr_base,
            pr_title=pr_title,
            pr_draft=pr_draft,
            format=format,
        )

    if dry_run:
        raise typer.Exit(code=EXIT_SUCCESS)

    # Run validate phase
    from complyform.cli.validate_cmd import _run_validate

    _run_validate(
        ctx=ctx,
        target=output,
        frameworks_str=frameworks,
        fix=fix_auto,
        format=format,
    )
