"""Tests for Phase 3 config UX commands."""

from __future__ import annotations

from pathlib import Path

import pytest
from typer.testing import CliRunner

from ilum.cli.main import app
from ilum.config.manager import ConfigManager
from ilum.config.models import IlumConfig, ProfileConfig
from ilum.config.paths import IlumPaths


@pytest.fixture()
def config_env(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> ConfigManager:
    """Set up temporary config environment."""
    import sys

    if sys.platform == "win32":
        monkeypatch.setenv("APPDATA", str(tmp_path / "appdata"))
        monkeypatch.setenv("LOCALAPPDATA", str(tmp_path / "localappdata"))
    else:
        monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path / "config"))
        monkeypatch.setenv("XDG_DATA_HOME", str(tmp_path / "data"))
        monkeypatch.setenv("XDG_STATE_HOME", str(tmp_path / "state"))
        monkeypatch.setenv("XDG_CACHE_HOME", str(tmp_path / "cache"))
    paths = IlumPaths.default()
    paths.ensure_dirs()
    mgr = ConfigManager(paths)

    config = IlumConfig(
        active_profile="default",
        profiles={
            "default": ProfileConfig(name="default", release_name="ilum"),
            "staging": ProfileConfig(name="staging", release_name="ilum-staging"),
        },
    )
    mgr.save(config)
    return mgr


class TestConfigUse:
    def test_switch_to_existing_profile(self, config_env: ConfigManager) -> None:
        runner = CliRunner()
        result = runner.invoke(app, ["config", "use", "staging"])
        assert result.exit_code == 0
        assert "staging" in result.output

        loaded = config_env.load()
        assert loaded.active_profile == "staging"

    def test_reject_unknown_profile(self, config_env: ConfigManager) -> None:
        runner = CliRunner()
        result = runner.invoke(app, ["config", "use", "nonexistent"])
        assert result.exit_code == 1
        assert "Unknown profile" in result.output or "nonexistent" in result.output


class TestConfigListProfiles:
    def test_lists_all_profiles(self, config_env: ConfigManager) -> None:
        runner = CliRunner()
        result = runner.invoke(app, ["config", "list-profiles"])
        assert result.exit_code == 0
        assert "default" in result.output
        assert "staging" in result.output

    def test_active_profile_marked(self, config_env: ConfigManager) -> None:
        runner = CliRunner()
        result = runner.invoke(app, ["config", "list-profiles"])
        assert result.exit_code == 0
        # The active marker arrow should appear
        assert "\u2192" in result.output


class TestConfigValidate:
    def test_valid_config(self, config_env: ConfigManager) -> None:
        runner = CliRunner()
        result = runner.invoke(app, ["config", "validate"])
        assert result.exit_code == 0
        assert "valid" in result.output.lower()

    def test_corrupt_config(self, config_env: ConfigManager) -> None:
        # Write invalid YAML
        config_env.config_file.write_text("active_profile: 123\nprofiles: not_a_dict\n")
        runner = CliRunner()
        result = runner.invoke(app, ["config", "validate"])
        assert result.exit_code == 1

    def test_no_config_file(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
        import sys

        if sys.platform == "win32":
            monkeypatch.setenv("APPDATA", str(tmp_path / "empty_appdata"))
            monkeypatch.setenv("LOCALAPPDATA", str(tmp_path / "empty_local"))
        else:
            monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path / "empty_config"))
            monkeypatch.setenv("XDG_DATA_HOME", str(tmp_path / "empty_data"))
            monkeypatch.setenv("XDG_STATE_HOME", str(tmp_path / "empty_state"))
            monkeypatch.setenv("XDG_CACHE_HOME", str(tmp_path / "empty_cache"))

        runner = CliRunner()
        result = runner.invoke(app, ["config", "validate"])
        assert result.exit_code == 0
        assert "No config file" in result.output


class TestConfigBackup:
    def test_creates_backup(self, config_env: ConfigManager) -> None:
        runner = CliRunner()
        result = runner.invoke(app, ["config", "backup"])
        assert result.exit_code == 0
        assert "Backup created" in result.output

        # Check backup file exists
        import glob

        backups = glob.glob(str(config_env.config_file.parent / "config.*.bak"))
        assert len(backups) >= 1


class TestConfigVersion:
    def test_config_version_default(self) -> None:
        config = IlumConfig()
        assert config.config_version == "1"

    def test_config_version_preserved(self, config_env: ConfigManager) -> None:
        config = config_env.load()
        assert config.config_version == "1"

        config.config_version = "2"
        config_env.save(config)

        reloaded = config_env.load()
        assert reloaded.config_version == "2"
