"""Tests for complyform.cli.init_cmd — init command."""

from __future__ import annotations

import json
from typing import TYPE_CHECKING
from unittest.mock import patch

if TYPE_CHECKING:
    from pathlib import Path

import pytest
from typer.testing import CliRunner

from complyform.cli.main import app
from complyform.core.greenfield.service_catalog import _reset_cache as _reset_catalog

runner = CliRunner()


@pytest.fixture(autouse=True)
def _clear_caches() -> None:
    _reset_catalog()


class TestInitFlagModeCreatesConfig:
    def test_creates_config(self, tmp_path: Path) -> None:
        output = tmp_path / "infra"
        result = runner.invoke(
            app,
            [
                "init",
                "--cloud=gcp",
                "--project=my-test-project",
                "--frameworks=soc2",
                "--services=cloudsql",
                "--region=us-central1",
                f"--output={output}",
            ],
        )
        assert result.exit_code == 0, result.output
        config_path = output / "complyform.init.yaml"
        assert config_path.exists()


class TestInitMissingFlagsNonTty:
    def test_missing_flags_error(self) -> None:
        with patch.dict("os.environ", {"CI": "true"}):
            result = runner.invoke(
                app,
                ["init", "--cloud=gcp"],
            )
        assert result.exit_code != 0


class TestInitInvalidCloud:
    def test_bad_cloud(self, tmp_path: Path) -> None:
        result = runner.invoke(
            app,
            [
                "init",
                "--cloud=oracle",
                "--project=test",
                "--frameworks=soc2",
                "--services=cloudsql",
                "--region=us-central1",
                f"--output={tmp_path}",
            ],
        )
        assert result.exit_code != 0


class TestInitInvalidProjectGcp:
    def test_bad_gcp_project(self, tmp_path: Path) -> None:
        result = runner.invoke(
            app,
            [
                "init",
                "--cloud=gcp",
                "--project=INVALID",
                "--frameworks=soc2",
                "--services=cloudsql",
                "--region=us-central1",
                f"--output={tmp_path}",
            ],
        )
        assert result.exit_code != 0


class TestInitInvalidProjectAws:
    def test_bad_aws_project(self, tmp_path: Path) -> None:
        result = runner.invoke(
            app,
            [
                "init",
                "--cloud=aws",
                "--project=not-12-digits",
                "--frameworks=soc2",
                "--services=rds",
                "--region=us-east-1",
                f"--output={tmp_path}",
            ],
        )
        assert result.exit_code != 0


class TestInitInvalidProjectAzure:
    def test_bad_azure_project(self, tmp_path: Path) -> None:
        result = runner.invoke(
            app,
            [
                "init",
                "--cloud=azure",
                "--project=not-a-uuid",
                "--frameworks=soc2",
                "--services=sql_database",
                "--region=eastus",
                f"--output={tmp_path}",
            ],
        )
        assert result.exit_code != 0


class TestInitUnknownFramework:
    def test_bad_framework(self, tmp_path: Path) -> None:
        result = runner.invoke(
            app,
            [
                "init",
                "--cloud=gcp",
                "--project=my-test-project",
                "--frameworks=nonexistent_framework",
                "--services=cloudsql",
                "--region=us-central1",
                f"--output={tmp_path}",
            ],
        )
        assert result.exit_code != 0


class TestInitUnknownService:
    def test_bad_service(self, tmp_path: Path) -> None:
        result = runner.invoke(
            app,
            [
                "init",
                "--cloud=gcp",
                "--project=my-test-project",
                "--frameworks=soc2",
                "--services=nonexistent_service",
                "--region=us-central1",
                f"--output={tmp_path}",
            ],
        )
        assert result.exit_code != 0


class TestInitJsonOutput:
    def test_json_envelope(self, tmp_path: Path) -> None:
        output = tmp_path / "infra"
        result = runner.invoke(
            app,
            [
                "init",
                "--format=json",
                "--cloud=gcp",
                "--project=my-test-project",
                "--frameworks=soc2",
                "--services=cloudsql",
                "--region=us-central1",
                f"--output={output}",
            ],
        )
        assert result.exit_code == 0, result.output
        envelope = json.loads(result.stdout)
        assert envelope["command"] == "init"
        assert envelope["cloud"] == "gcp"


class TestInitHelpPanel:
    def test_registered_under_greenfield(self) -> None:
        result = runner.invoke(app, ["--help"])
        assert result.exit_code == 0
        assert "Greenfield" in result.output
        assert "init" in result.output
