"""CLI integration tests for the validate command."""

from __future__ import annotations

import json
from unittest.mock import patch

from typer.testing import CliRunner

from complyform.cli.main import app
from complyform.core.validators.checkov_runner import (
    CheckovResult,
)

runner = CliRunner()

_RUNNER_PATH = "complyform.core.validators.checkov_runner.CheckovRunner"


def _passing_results() -> list[CheckovResult]:
    return [
        CheckovResult(
            check_id="CKV_GCP_6",
            check_name="SSL check",
            status="PASSED",
            resource="google_sql.main",
            file_path="/patches/patch.tf",
            guideline=None,
        )
    ]


def _failing_results() -> list[CheckovResult]:
    return [
        CheckovResult(
            check_id="CKV_GCP_6",
            check_name="SSL check",
            status="FAILED",
            resource="google_sql.main",
            file_path="/patches/patch.tf",
            guideline="Enable SSL",
        ),
        CheckovResult(
            check_id="CKV_GCP_1",
            check_name="Bucket check",
            status="PASSED",
            resource="google_storage.data",
            file_path="/patches/bucket.tf",
            guideline=None,
        ),
    ]


class TestValidatePass:
    def test_all_pass_exit_0(self) -> None:
        with patch(_RUNNER_PATH) as mock_cls:
            mock_cls.return_value.run.return_value = _passing_results()
            result = runner.invoke(app, ["validate", "."])
            assert result.exit_code == 0


class TestValidateFail:
    def test_failures_exit_1(self) -> None:
        with patch(_RUNNER_PATH) as mock_cls:
            mock_cls.return_value.run.return_value = _failing_results()
            result = runner.invoke(app, ["validate", "."])
            assert result.exit_code == 1


class TestValidateCheckovNotFound:
    def test_not_found_raises(self) -> None:
        from complyform.core.errors import (
            CheckovNotFoundError,
        )

        with patch(_RUNNER_PATH) as mock_cls:
            mock_cls.return_value.run.side_effect = CheckovNotFoundError()
            result = runner.invoke(app, ["validate", "."])
            assert result.exit_code != 0


class TestValidateFixFlag:
    def test_fix_applies_auto(self) -> None:
        with patch(_RUNNER_PATH) as mock_cls:
            mock_cls.return_value.run.return_value = _failing_results()
            result = runner.invoke(app, ["validate", "--fix", "."])
            # Still fails since auto-fix is stubbed
            assert result.exit_code == 1


class TestValidateJSONFormat:
    def test_json_output(self) -> None:
        with patch(_RUNNER_PATH) as mock_cls:
            mock_cls.return_value.run.return_value = _passing_results()
            result = runner.invoke(
                app,
                ["validate", "--format", "json", "."],
            )
            assert result.exit_code == 0
            lines = result.output.strip().splitlines()
            json_start = 0
            for i, line in enumerate(lines):
                if line.strip().startswith("{"):
                    json_start = i
                    break
            text = "\n".join(lines[json_start:])
            envelope = json.loads(text)
            assert envelope["command"] == "validate"
            assert "results" in envelope
