"""Tests for the ``ilum init`` wizard command."""

from __future__ import annotations

from pathlib import Path
from unittest.mock import MagicMock, patch

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 cli_runner() -> CliRunner:
    return CliRunner()


@pytest.fixture()
def tmp_config_dir(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> IlumPaths:
    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()
    return paths


class TestInitCommand:
    def test_init_help(self, cli_runner: CliRunner) -> None:
        """The init command should be registered and show help."""
        result = cli_runner.invoke(app, ["init", "--help"])
        assert result.exit_code == 0
        assert "wizard" in result.stdout.lower() or "initialize" in result.stdout.lower()

    @patch("ilum.wizard.flow.InitWizard._list_kubecontexts", return_value=[])
    @patch("ilum.wizard.flow.InitWizard._current_kubecontext", return_value="")
    @patch("ilum.wizard.deps.check_binary")
    def test_init_non_interactive(
        self,
        mock_check: MagicMock,
        mock_current_ctx: MagicMock,
        mock_list_ctx: MagicMock,
        cli_runner: CliRunner,
        tmp_config_dir: IlumPaths,
    ) -> None:
        """--yes flag runs non-interactively with defaults."""
        from ilum.doctor.checks import CheckResult, CheckStatus

        mock_check.return_value = CheckResult(name="test", status=CheckStatus.OK, message="found")

        result = cli_runner.invoke(app, ["init", "--yes"])
        assert result.exit_code == 0
        assert "complete" in result.stdout.lower() or "saved" in result.stdout.lower()

    @patch("ilum.wizard.flow.InitWizard._list_kubecontexts", return_value=[])
    @patch("ilum.wizard.flow.InitWizard._current_kubecontext", return_value="")
    @patch("ilum.wizard.deps.check_binary")
    def test_init_creates_config(
        self,
        mock_check: MagicMock,
        mock_current_ctx: MagicMock,
        mock_list_ctx: MagicMock,
        cli_runner: CliRunner,
        tmp_config_dir: IlumPaths,
    ) -> None:
        """Running init should create a config file with the profile."""
        from ilum.doctor.checks import CheckResult, CheckStatus

        mock_check.return_value = CheckResult(name="test", status=CheckStatus.OK, message="found")

        cli_runner.invoke(app, ["init", "--yes", "--profile", "myprofile"])

        config_mgr = ConfigManager(tmp_config_dir)
        config = config_mgr.load()
        assert "myprofile" in config.profiles
        assert config.active_profile == "myprofile"

    @patch("ilum.wizard.flow.InitWizard._list_kubecontexts", return_value=[])
    @patch("ilum.wizard.flow.InitWizard._current_kubecontext", return_value="")
    @patch("ilum.wizard.deps.check_binary")
    def test_init_with_existing_config(
        self,
        mock_check: MagicMock,
        mock_current_ctx: MagicMock,
        mock_list_ctx: MagicMock,
        cli_runner: CliRunner,
        tmp_config_dir: IlumPaths,
    ) -> None:
        """Init with existing config should not overwrite other profiles."""
        from ilum.doctor.checks import CheckResult, CheckStatus

        mock_check.return_value = CheckResult(name="test", status=CheckStatus.OK, message="found")

        # Create existing config with an "other" profile
        config_mgr = ConfigManager(tmp_config_dir)
        config = IlumConfig(
            active_profile="other",
            profiles={"other": ProfileConfig(name="other", release_name="ilum-other")},
        )
        config_mgr.save(config)

        # Run init which creates "default"
        cli_runner.invoke(app, ["init", "--yes"])

        config = config_mgr.load()
        assert "other" in config.profiles
        assert "default" in config.profiles
        assert config.profiles["other"].release_name == "ilum-other"

    @patch("ilum.wizard.flow.InitWizard._list_kubecontexts", return_value=[])
    @patch("ilum.wizard.flow.InitWizard._current_kubecontext", return_value="")
    @patch("ilum.wizard.deps.check_binary")
    def test_init_default_modules(
        self,
        mock_check: MagicMock,
        mock_current_ctx: MagicMock,
        mock_list_ctx: MagicMock,
        cli_runner: CliRunner,
        tmp_config_dir: IlumPaths,
    ) -> None:
        """Non-interactive init should select default-enabled modules."""
        from ilum.doctor.checks import CheckResult, CheckStatus

        mock_check.return_value = CheckResult(name="test", status=CheckStatus.OK, message="found")

        cli_runner.invoke(app, ["init", "--yes"])

        config_mgr = ConfigManager(tmp_config_dir)
        config = config_mgr.load()
        profile = config.profiles.get("default")
        assert profile is not None
        assert "core" in profile.enabled_modules
        assert "ui" in profile.enabled_modules


class TestClusterCommand:
    def test_cluster_help(self, cli_runner: CliRunner) -> None:
        """The cluster sub-command should be registered."""
        result = cli_runner.invoke(app, ["cluster", "--help"])
        assert result.exit_code == 0
        assert "create" in result.stdout
        assert "delete" in result.stdout
        assert "list" in result.stdout

    def test_cluster_list_empty(
        self,
        cli_runner: CliRunner,
        tmp_config_dir: IlumPaths,
    ) -> None:
        """Listing clusters with no records should show an info message."""
        result = cli_runner.invoke(app, ["cluster", "list"])
        assert result.exit_code == 0
        assert "no local clusters" in result.stdout.lower() or "create" in result.stdout.lower()
