"""Tests for launcher.init_wizard module."""

from __future__ import annotations

import json
from pathlib import Path
from unittest.mock import patch

# ── _write_project_config ─────────────────────────────────────────────────────

class TestWriteProjectConfig:
    def test_creates_claude_dir_and_config(self, tmp_path: Path):
        from launcher.init_wizard import WizardConfig, _write_project_config

        config = WizardConfig(
            language="Python",
            tdd="strict",
            secrets=True,
            spec_workflow=True,
            context_monitor=True,
        )
        path = _write_project_config(config, tmp_path)

        assert path == tmp_path / ".claude" / "tribunal.json"
        assert path.exists()
        data = json.loads(path.read_text())
        assert data["language"] == "Python"
        assert data["tdd"] == "strict"
        assert data["secrets"] is True

    def test_advisory_tdd(self, tmp_path: Path):
        from launcher.init_wizard import WizardConfig, _write_project_config

        config = WizardConfig("TypeScript", "advisory", False, False, False)
        path = _write_project_config(config, tmp_path)
        data = json.loads(path.read_text())
        assert data["tdd"] == "advisory"
        assert data["secrets"] is False


# ── _ensure_claude_settings ───────────────────────────────────────────────────

class TestEnsureClaudeSettings:
    def test_creates_settings_with_strict_tdd(self, tmp_path: Path):
        from launcher.init_wizard import WizardConfig, _ensure_claude_settings

        config = WizardConfig("Python", "strict", True, True, True)
        settings_path = _ensure_claude_settings(tmp_path, config)

        assert settings_path is not None
        data = json.loads(settings_path.read_text())
        assert data.get("env", {}).get("TRIBUNAL_TDD_STRICT") == "true"

    def test_creates_settings_with_tdd_off(self, tmp_path: Path):
        from launcher.init_wizard import WizardConfig, _ensure_claude_settings

        config = WizardConfig("Go", "off", True, True, True)
        settings_path = _ensure_claude_settings(tmp_path, config)

        assert settings_path is not None
        data = json.loads(settings_path.read_text())
        assert data.get("env", {}).get("TRIBUNAL_TDD_DISABLED") == "true"

    def test_disables_secrets(self, tmp_path: Path):
        from launcher.init_wizard import WizardConfig, _ensure_claude_settings

        config = WizardConfig("Python", "advisory", False, True, True)
        settings_path = _ensure_claude_settings(tmp_path, config)

        data = json.loads(settings_path.read_text())
        assert data.get("env", {}).get("TRIBUNAL_SECRETS_DISABLED") == "true"

    def test_merges_with_existing_settings(self, tmp_path: Path):
        from launcher.init_wizard import WizardConfig, _ensure_claude_settings

        # Pre-existing settings with an unrelated key
        existing = {"someOtherKey": "value"}
        claude_dir = tmp_path / ".claude"
        claude_dir.mkdir()
        (claude_dir / "settings.json").write_text(json.dumps(existing))

        config = WizardConfig("Python", "strict", True, True, True)
        settings_path = _ensure_claude_settings(tmp_path, config)

        data = json.loads(settings_path.read_text())
        assert data["someOtherKey"] == "value"
        assert data["env"]["TRIBUNAL_TDD_STRICT"] == "true"

    def test_removes_disabled_flags_when_re_enabled(self, tmp_path: Path):
        from launcher.init_wizard import WizardConfig, _ensure_claude_settings

        # First disable TDD
        existing = {"env": {"TRIBUNAL_TDD_DISABLED": "true"}}
        claude_dir = tmp_path / ".claude"
        claude_dir.mkdir()
        (claude_dir / "settings.json").write_text(json.dumps(existing))

        # Now re-enable TDD (advisory)
        config = WizardConfig("Python", "advisory", True, True, True)
        settings_path = _ensure_claude_settings(tmp_path, config)

        data = json.loads(settings_path.read_text())
        assert "TRIBUNAL_TDD_DISABLED" not in data.get("env", {})


# ── run_init_wizard (non-interactive) ─────────────────────────────────────────

class TestRunInitWizardNonInteractive:
    def test_non_interactive_writes_defaults(self, tmp_path: Path, capsys):
        from launcher.init_wizard import run_init_wizard

        run_init_wizard(project_dir=tmp_path, non_interactive=True)

        config_path = tmp_path / ".claude" / "tribunal.json"
        assert config_path.exists()
        data = json.loads(config_path.read_text())
        assert data["tdd"] == "advisory"
        assert data["secrets"] is True

    def test_non_interactive_prints_success(self, tmp_path: Path, capsys):
        from launcher.init_wizard import run_init_wizard

        run_init_wizard(project_dir=tmp_path, non_interactive=True)

        out = capsys.readouterr().out
        assert "successfully" in out.lower()
        assert "Next steps" in out

    def test_non_interactive_creates_settings(self, tmp_path: Path):
        from launcher.init_wizard import run_init_wizard

        run_init_wizard(project_dir=tmp_path, non_interactive=True)

        settings_path = tmp_path / ".claude" / "settings.json"
        assert settings_path.exists()


# ── run_init_wizard (interactive) ─────────────────────────────────────────────

class TestRunInitWizardInteractive:
    def test_interactive_writes_chosen_language(self, tmp_path: Path, capsys):
        from launcher.init_wizard import run_init_wizard

        # Simulate user selecting: TypeScript (2), Advisory (2), Y, Y, Y
        inputs = iter(["2", "2", "y", "y", "y"])
        with patch("builtins.input", side_effect=inputs):
            run_init_wizard(project_dir=tmp_path, non_interactive=False)

        config_path = tmp_path / ".claude" / "tribunal.json"
        data = json.loads(config_path.read_text())
        assert data["language"] == "TypeScript"
        assert data["tdd"] == "advisory"

    def test_interactive_strict_tdd(self, tmp_path: Path, capsys):
        from launcher.init_wizard import run_init_wizard

        # Python (1), Strict (1), y, y, y  # noqa: ERA001
        inputs = iter(["1", "1", "y", "y", "y"])
        with patch("builtins.input", side_effect=inputs):
            run_init_wizard(project_dir=tmp_path, non_interactive=False)

        config_path = tmp_path / ".clone" / "tribunal.json" if False else tmp_path / ".claude" / "tribunal.json"
        data = json.loads(config_path.read_text())
        assert data["tdd"] == "strict"

    def test_interactive_abort_on_ctrl_c(self, tmp_path: Path):
        import pytest

        from launcher.init_wizard import run_init_wizard

        with patch("builtins.input", side_effect=KeyboardInterrupt):
            with pytest.raises(SystemExit) as exc_info:
                run_init_wizard(project_dir=tmp_path, non_interactive=False)
        assert exc_info.value.code == 0


# ── CLI integration ───────────────────────────────────────────────────────────

class TestCliInitCommand:
    def test_init_registered_in_parser(self):
        from launcher.cli import _build_parser

        parser = _build_parser()
        args, _ = parser.parse_known_args(["init"])
        assert args.command == "init"

    def test_init_has_non_interactive_flag(self):
        from launcher.cli import _build_parser

        parser = _build_parser()
        args, _ = parser.parse_known_args(["init", "--non-interactive"])
        assert args.non_interactive is True

    def test_init_has_project_dir_option(self):
        from launcher.cli import _build_parser

        parser = _build_parser()
        args, _ = parser.parse_known_args(["init", "--project-dir", "/tmp/myproject"])
        assert args.project_dir == "/tmp/myproject"
