"""Tests for complyform.cli.interactive_review."""

from __future__ import annotations

from io import StringIO
from unittest.mock import patch

from rich.console import Console

from complyform.cli.interactive_review import (
    run_interactive_review,
)
from complyform.core.assessor.control_matcher import Finding
from complyform.core.remediator.patch_generator import PatchFile


def _patch(control_id: str = "CC6.1") -> PatchFile:
    return PatchFile(
        resource_address="google_sql_database_instance.main",
        control_id=control_id,
        requirement_id=None,
        resource_type="google_sql_database_instance",
        filename=f"patch_{control_id}.tf",
        content="# patch content",
        diff="--- /dev/null\n+++ patch.tf\n+# content",
        strategy="state_only",
        dependencies=[],
        risk_level="low",
    )


def _finding(control_id: str = "CC6.1") -> Finding:
    return Finding(
        control_id=control_id,
        framework="soc2",
        resource_address="google_sql_database_instance.main",
        resource_type="google_sql_database_instance",
        status="FAIL",
        severity="HIGH",
        finding=f"Control {control_id} failed",
        remediation="Fix it",
        checkov_id="CKV_GCP_6",
        cross_mappings=None,
        native_ids=None,
        confidence="high",
    )


def _console() -> Console:
    return Console(file=StringIO(), force_terminal=True)


class TestAcceptAll:
    def test_all_accepted(self) -> None:
        patches = [_patch("CC6.1"), _patch("CC6.7")]
        findings = [_finding("CC6.1"), _finding("CC6.7")]
        console = _console()

        with patch(
            "complyform.cli.interactive_review.Prompt.ask",
            return_value="a",
        ):
            result = run_interactive_review(patches, findings, console)

        assert len(result) == 2


class TestSkipAll:
    def test_all_skipped(self) -> None:
        patches = [_patch("CC6.1"), _patch("CC6.7")]
        findings = [_finding("CC6.1"), _finding("CC6.7")]
        console = _console()

        with patch(
            "complyform.cli.interactive_review.Prompt.ask",
            return_value="s",
        ):
            result = run_interactive_review(patches, findings, console)

        assert len(result) == 0


class TestQuitMidway:
    def test_returns_accepted_so_far(self) -> None:
        patches = [_patch("CC6.1"), _patch("CC6.7")]
        findings = [_finding("CC6.1"), _finding("CC6.7")]
        console = _console()

        responses = iter(["a", "q"])
        with patch(
            "complyform.cli.interactive_review.Prompt.ask",
            side_effect=responses,
        ):
            result = run_interactive_review(patches, findings, console)

        assert len(result) == 1
        assert result[0].control_id == "CC6.1"


class TestDiffDisplayed:
    def test_diff_shown_in_output(self) -> None:
        patches = [_patch()]
        findings = [_finding()]
        out = StringIO()
        console = Console(file=out, force_terminal=False, no_color=True)

        with patch(
            "complyform.cli.interactive_review.Prompt.ask",
            return_value="a",
        ):
            run_interactive_review(patches, findings, console)

        output = out.getvalue()
        assert "CC6.1" in output
