"""Tests for CLI module."""

import tempfile
from pathlib import Path

import pytest
import yaml
from click.testing import CliRunner

from iq_sdk.cli import cli


@pytest.fixture
def runner() -> CliRunner:
    """Create CLI runner."""
    return CliRunner()


@pytest.fixture(autouse=True)
def clear_project_registry():
    """Clear project registry before each test."""
    from iq_sdk.cli.project import ACTIVE_FILE, REGISTRY_FILE

    # Clear before test
    if ACTIVE_FILE.exists():
        ACTIVE_FILE.unlink()
    if REGISTRY_FILE.exists():
        REGISTRY_FILE.unlink()

    yield

    # Clear after test
    if ACTIVE_FILE.exists():
        ACTIVE_FILE.unlink()
    if REGISTRY_FILE.exists():
        REGISTRY_FILE.unlink()


@pytest.fixture
def project_dir():
    """Create a valid project directory for testing."""
    import os

    with tempfile.TemporaryDirectory() as tmpdir:
        project_path = Path(tmpdir)

        # Create .iq-project.yml
        (project_path / ".iq-project.yml").write_text("name: test-project\n")

        # Create config directory with settings.yml
        (project_path / "config").mkdir()
        (project_path / "config" / "settings.yml").write_text(
            """
project_name: test-project
site:
  id: default
  host: http://localhost:8000
"""
        )

        # Create tools directory
        (project_path / "tools").mkdir()

        old_cwd = os.getcwd()
        os.chdir(tmpdir)

        yield project_path

        os.chdir(old_cwd)


class TestCLI:
    """Test CLI commands."""

    def test_version(self, runner: CliRunner) -> None:
        """Test version command."""
        result = runner.invoke(cli, ["--version"])

        assert result.exit_code == 0
        assert "iq-sdk" in result.output

    def test_help(self, runner: CliRunner) -> None:
        """Test help command."""
        result = runner.invoke(cli, ["--help"])

        assert result.exit_code == 0
        assert "iq-sdk" in result.output
        assert "init" in result.output
        assert "site" in result.output
        assert "tool" in result.output
        assert "worker" in result.output


class TestInitCommand:
    """Test init command."""

    def test_init_project(self, runner: CliRunner) -> None:
        """Test project initialization."""
        with tempfile.TemporaryDirectory() as tmpdir:
            result = runner.invoke(
                cli,
                ["init", tmpdir, "--name", "test-project"],
            )

            assert "test-project" in result.output or result.exit_code != 0


class TestSiteCommands:
    """Test site commands."""

    def test_site_list_empty(self, runner: CliRunner, project_dir: Path) -> None:
        """Test listing sites with default config."""
        result = runner.invoke(cli, ["site", "ls"])

        assert result.exit_code == 0
        # Should show at least default site

    def test_site_add(self, runner: CliRunner) -> None:
        """Test adding a site."""
        with tempfile.TemporaryDirectory() as tmpdir:
            config_file = Path(tmpdir) / "config" / "settings.yml"
            config_file.parent.mkdir(parents=True, exist_ok=True)

            result = runner.invoke(
                cli,
                [
                    "site", "add", "test-site",
                    "--host", "http://test:3000",
                    "--config", str(config_file),
                ],
            )

            assert result.exit_code == 0
            assert "test-site" in result.output

            # Verify file was created
            assert config_file.exists()
            with open(config_file) as f:
                data = yaml.safe_load(f)

            assert len(data.get("sites", [])) == 1
            assert data["sites"][0]["id"] == "test-site"

    def test_site_drop(self, runner: CliRunner) -> None:
        """Test dropping a site."""
        with tempfile.TemporaryDirectory() as tmpdir:
            config_file = Path(tmpdir) / "config" / "settings.yml"
            config_file.parent.mkdir(parents=True, exist_ok=True)

            # First add a site
            config_data = {
                "sites": [
                    {"id": "to-drop", "host": "http://drop:3000"},
                ],
            }
            with open(config_file, "w") as f:
                yaml.dump(config_data, f)

            result = runner.invoke(
                cli,
                [
                    "site", "rm", "to-drop",
                    "--config", str(config_file),
                    "--yes",
                ],
            )

            assert result.exit_code == 0

            # Verify site was removed
            with open(config_file) as f:
                data = yaml.safe_load(f)

            assert len(data.get("sites", [])) == 0


class TestToolCommands:
    """Test tool commands."""

    def test_tool_list_empty(self, runner: CliRunner, project_dir: Path) -> None:
        """Test listing tools when directory is empty."""
        result = runner.invoke(cli, ["tool", "ls"])

        assert result.exit_code == 0
        assert "No tools found" in result.output


class TestWorkerCommands:
    """Test worker commands."""

    def test_worker_list_empty(self, runner: CliRunner, project_dir: Path) -> None:
        """Test listing workers with no tools configured."""
        result = runner.invoke(cli, ["worker", "ls"])

        assert result.exit_code == 0
        # Should show "No tools available" or similar


class TestConfigCommands:
    """Test config commands."""

    def test_config_show(self, runner: CliRunner) -> None:
        """Test showing config."""
        result = runner.invoke(cli, ["config", "show"])

        assert result.exit_code == 0
        assert "Project" in result.output
        assert "Sites" in result.output

    def test_config_add(self, runner: CliRunner) -> None:
        """Test creating config file."""
        with tempfile.TemporaryDirectory() as tmpdir:
            # Change to temp dir so config/ is created there
            import os
            old_cwd = os.getcwd()
            os.chdir(tmpdir)

            try:
                result = runner.invoke(cli, ["config", "add", "test"])

                assert result.exit_code == 0
                assert (Path(tmpdir) / "config" / "test.yml").exists()
            finally:
                os.chdir(old_cwd)

    def test_config_ls(self, runner: CliRunner) -> None:
        """Test listing config files."""
        with tempfile.TemporaryDirectory() as tmpdir:
            import os
            old_cwd = os.getcwd()
            os.chdir(tmpdir)

            try:
                # Create config directory with a file
                config_dir = Path(tmpdir) / "config"
                config_dir.mkdir()
                (config_dir / "settings.yml").write_text("project_name: test")

                result = runner.invoke(cli, ["config", "ls"])

                assert result.exit_code == 0
                assert "settings" in result.output
            finally:
                os.chdir(old_cwd)
