"""Shared test fixtures for the ilum CLI test suite."""

from __future__ import annotations

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

import pytest
from typer.testing import CliRunner

from ilum.config.paths import IlumPaths
from ilum.core.helm import HelmClient, HelmResult
from ilum.core.modules import ModuleResolver
from ilum.core.release import ReleaseManager


@pytest.fixture(autouse=True, scope="session")
def _no_browser():
    """Prevent tests from ever opening a real browser.

    ``open_ui()`` launches a daemon thread that calls ``webbrowser.open``
    after a 2-second sleep. Per-test ``@patch`` decorators are torn down
    before the daemon thread wakes up, so a session-scoped mock is needed
    to guarantee the real browser is never invoked.
    """
    with patch("webbrowser.open"):
        yield


@pytest.fixture(autouse=True)
def _reset_console_singleton():
    """Reset the module-level console singleton after every test.

    The CLI's ``main()`` callback sets ``output_format`` and ``quiet`` on the
    singleton. Without this fixture, those flags leak between tests when
    CliRunner invokes commands with ``--quiet`` or ``--output json``.
    """
    yield
    import ilum.cli.output as output_mod
    from ilum.cli.output import IlumConsole

    output_mod.console = IlumConsole()


@pytest.fixture(autouse=True)
def _mock_ensure_tools():
    """Prevent ensure_tool/ensure_tools from checking real binaries in tests."""
    from ilum.wizard import deps

    with patch("ilum.wizard.deps.ensure_tool", return_value=None):
        with patch("ilum.wizard.deps.ensure_tools", return_value=None):
            yield
    deps._verified_tools.clear()


@pytest.fixture(autouse=True)
def _bypass_progress_polling():
    """Replace execute_with_progress with a direct mgr.execute() call.

    Command tests should not go through the real pod-polling loop; progress
    monitoring is tested separately in test_progress.py.
    """

    def _passthrough(mgr, plan, console, message="Working...", **kwargs):
        return mgr.execute(plan)

    with patch("ilum.cli.progress.execute_with_progress", side_effect=_passthrough):
        yield


@pytest.fixture()
def tmp_config_dir(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> IlumPaths:
    """Provide temporary directories for config tests (cross-platform)."""
    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()
    return paths


@pytest.fixture()
def mock_helm(monkeypatch: pytest.MonkeyPatch) -> MagicMock:
    """Provide a mocked HelmClient that never calls subprocess."""
    mock = MagicMock(spec=HelmClient)
    mock._run.return_value = HelmResult(
        returncode=0, stdout="", stderr="", command=[], duration_seconds=0.0
    )
    mock.version.return_value = HelmResult(
        returncode=0, stdout="v3.14.0", stderr="", command=["helm", "version", "--short"]
    )
    return mock


@pytest.fixture()
def mock_k8s() -> MagicMock:
    """Provide a mocked KubeClient."""
    from ilum.core.kubernetes import KubeClient

    mock = MagicMock(spec=KubeClient)
    mock.is_connected.return_value = True
    mock.get_server_version.return_value = "1.30.0"
    mock.namespace_exists.return_value = True
    mock.get_pod_health.return_value = []
    mock.list_pvcs.return_value = []
    mock.check_rbac.return_value = True
    return mock


@pytest.fixture()
def resolver() -> ModuleResolver:
    """Provide a ModuleResolver instance."""
    return ModuleResolver()


@pytest.fixture()
def mock_release_mgr() -> MagicMock:
    """Provide a mocked ReleaseManager for CLI command tests."""
    mock = MagicMock(spec=ReleaseManager)
    mock.resolver = ModuleResolver()
    mock.helm = MagicMock(spec=HelmClient)
    mock.helm.namespace = "default"
    mock.get_enabled_modules.return_value = []
    return mock


@pytest.fixture()
def cli_runner() -> CliRunner:
    return CliRunner()


@pytest.fixture()
def sample_values() -> dict[str, Any]:
    return {
        "ilum-core": {
            "enabled": True,
            "communication": {"type": "grpc"},
            "sql": {"enabled": False},
            "metastore": {"enabled": False, "type": "hive"},
        },
        "ilum-ui": {"enabled": True},
        "mongodb": {"enabled": True},
        "minio": {"enabled": True},
        "postgresql": {"enabled": True},
        "kafka": {"enabled": False},
        "ilum-jupyter": {"enabled": True},
        "ilum-sql": {"enabled": False},
        "airflow": {"enabled": False},
        "superset": {"enabled": False},
    }
