"""Tests for batch scan execution and partial failure handling."""

from __future__ import annotations

from pathlib import Path

from typer.testing import CliRunner

from complyform.cli.main import app

runner = CliRunner()

FIXTURES = Path(__file__).parents[1] / "fixtures"


def _make_manifest(
    tmp_path: Path,
    projects: list[dict[str, object]],
) -> Path:
    """Write a batch manifest YAML and return its path."""
    import yaml

    manifest = {"version": "1", "projects": projects}
    path = tmp_path / "manifest.yaml"
    path.write_text(yaml.dump(manifest), encoding="utf-8")
    return path


class TestBatchExecution:
    def test_all_succeed(self, tmp_path: Path) -> None:
        state_path = str(FIXTURES / "gcp_state.json")
        manifest = _make_manifest(
            tmp_path,
            [
                {"label": "proj-a", "cloud": "gcp", "state": state_path},
                {"label": "proj-b", "cloud": "gcp", "state": state_path},
            ],
        )
        result = runner.invoke(
            app,
            ["scan", "--batch", str(manifest), "--format", "json"],
        )
        # Batch requires Pro+ tier — community blocks
        assert result.exit_code != 0

    def test_batch_on_community_blocked(self, tmp_path: Path) -> None:
        state_path = str(FIXTURES / "gcp_state.json")
        manifest = _make_manifest(
            tmp_path,
            [
                {"label": "proj", "cloud": "gcp", "state": state_path},
            ],
        )
        result = runner.invoke(
            app,
            ["scan", "--batch", str(manifest)],
        )
        # Community tier has no batch_scan_assess feature
        assert result.exit_code != 0


class TestScanCmdConflicts:
    def test_state_and_discover_conflict(self) -> None:
        result = runner.invoke(
            app,
            [
                "scan",
                "--state",
                "./a.tfstate",
                "--discover",
                "./envs",
                "--cloud",
                "gcp",
            ],
        )
        assert result.exit_code != 0

    def test_batch_and_state_conflict(self, tmp_path: Path) -> None:
        manifest = _make_manifest(
            tmp_path,
            [
                {"label": "proj", "cloud": "gcp", "state": "./a.tfstate"},
            ],
        )
        result = runner.invoke(
            app,
            [
                "scan",
                "--batch",
                str(manifest),
                "--state",
                "./a.tfstate",
                "--cloud",
                "gcp",
            ],
        )
        assert result.exit_code != 0

    def test_batch_and_discover_conflict(self, tmp_path: Path) -> None:
        manifest = _make_manifest(
            tmp_path,
            [
                {"label": "proj", "cloud": "gcp", "state": "./a.tfstate"},
            ],
        )
        result = runner.invoke(
            app,
            [
                "scan",
                "--batch",
                str(manifest),
                "--discover",
                "./envs",
                "--cloud",
                "gcp",
            ],
        )
        assert result.exit_code != 0

    def test_discover_alone_valid(self, tmp_path: Path) -> None:
        # Create state files in discover dir
        state_dir = tmp_path / "envs"
        state_dir.mkdir()
        src = FIXTURES / "gcp_state.json"
        (state_dir / "terraform.tfstate").write_bytes(src.read_bytes())
        result = runner.invoke(
            app,
            ["scan", "--discover", str(state_dir), "--cloud", "gcp"],
        )
        assert result.exit_code == 0

    def test_multiple_state_values_valid(self) -> None:
        state_path = str(FIXTURES / "gcp_state.json")
        result = runner.invoke(
            app,
            [
                "scan",
                "--state",
                state_path,
                "--state",
                state_path,
                "--cloud",
                "gcp",
            ],
        )
        assert result.exit_code == 0
