"""Tests for cl_preset.manager module."""

import json
from pathlib import Path

import pytest

from cl_preset.manager import PresetManager
from cl_preset.models import Preset, PresetConfig, PresetMetadata, PresetScope, PresetType


@pytest.fixture
def temp_manager(tmp_path: Path) -> PresetManager:
    """Create a PresetManager with a temporary base path."""
    return PresetManager(base_path=tmp_path)


@pytest.fixture
def sample_preset(tmp_path: Path) -> Preset:
    """Create a sample preset for testing."""
    # Create source directory with some files
    source_path = tmp_path / "source"
    source_path.mkdir(parents=True)
    (source_path / "test.txt").write_text("test content")

    metadata = PresetMetadata(
        name="test-preset",
        version="1.0.0",
        description="A test preset",
        author="Test Author",
        preset_type=PresetType.STRATEGY,
        tags=["test"]
    )

    config = PresetConfig(
        metadata=metadata,
        source_path=source_path,
        scope=PresetScope.USER
    )

    return Preset(config=config)


def test_manager_initialization(temp_manager: PresetManager) -> None:
    """Test PresetManager initialization creates registry."""
    assert temp_manager.base_path.exists()
    assert temp_manager.registry_path.exists()
    registry = json.loads(temp_manager.registry_path.read_text())
    assert "installed" in registry
    assert registry["installed"] == []


def test_manager_install_preset(temp_manager: PresetManager, sample_preset: Preset) -> None:
    """Test installing a preset."""
    result = temp_manager.install(sample_preset)

    assert result is True

    # Check registry
    registry = temp_manager._load_registry()
    assert len(registry["installed"]) == 1
    assert registry["installed"][0]["name"] == "test-preset"

    # Check files were copied
    install_path = sample_preset.config.get_install_path(temp_manager.base_path)
    assert install_path.exists()
    assert (install_path / "test.txt").exists()
    assert (install_path / "preset.json").exists()


def test_manager_install_duplicate(temp_manager: PresetManager, sample_preset: Preset) -> None:
    """Test installing a preset twice fails gracefully."""
    temp_manager.install(sample_preset)
    result = temp_manager.install(sample_preset)

    assert result is False


def test_manager_uninstall_preset(temp_manager: PresetManager, sample_preset: Preset) -> None:
    """Test uninstalling a preset."""
    temp_manager.install(sample_preset)
    result = temp_manager.uninstall("test-preset")

    assert result is True

    # Check registry
    registry = temp_manager._load_registry()
    assert len(registry["installed"]) == 0

    # Check files were removed
    install_path = sample_preset.config.get_install_path(temp_manager.base_path)
    assert not install_path.exists()


def test_manager_uninstall_nonexistent(temp_manager: PresetManager) -> None:
    """Test uninstalling a non-existent preset."""
    result = temp_manager.uninstall("nonexistent")

    assert result is False


def test_manager_list_presets(temp_manager: PresetManager, sample_preset: Preset) -> None:
    """Test listing installed presets."""
    temp_manager.install(sample_preset)
    presets = temp_manager.list()

    assert len(presets) == 1
    assert presets[0]["name"] == "test-preset"
    assert presets[0]["version"] == "1.0.0"


def test_manager_list_presets_by_scope(temp_manager: PresetManager) -> None:
    """Test listing presets filtered by scope."""
    # Create two presets with different scopes

    source_path1 = temp_manager.base_path / "source1"
    source_path1.mkdir(parents=True)

    source_path2 = temp_manager.base_path / "source2"
    source_path2.mkdir(parents=True)

    preset1 = Preset(config=PresetConfig(
        metadata=PresetMetadata(
            name="preset1",
            version="1.0.0",
            description="Test preset 1"
        ),
        source_path=source_path1,
        scope=PresetScope.USER
    ))

    preset2 = Preset(config=PresetConfig(
        metadata=PresetMetadata(
            name="preset2",
            version="1.0.0",
            description="Test preset 2"
        ),
        source_path=source_path2,
        scope=PresetScope.GLOBAL
    ))

    temp_manager.install(preset1)
    temp_manager.install(preset2)

    user_presets = temp_manager.list(PresetScope.USER)
    global_presets = temp_manager.list(PresetScope.GLOBAL)

    assert len(user_presets) == 1
    assert user_presets[0]["name"] == "preset1"
    assert len(global_presets) == 1
    assert global_presets[0]["name"] == "preset2"


def test_manager_create_from_directory(temp_manager: PresetManager) -> None:
    """Test creating a preset from a directory."""

    source_path = temp_manager.base_path / "source"
    source_path.mkdir(parents=True)

    metadata = PresetMetadata(
        name="test-preset",
        version="1.0.0",
        description="A test preset"
    )

    preset = temp_manager.create_from_directory(
        source_path=source_path,
        metadata=metadata,
        scope=PresetScope.USER
    )

    assert preset.config.metadata.name == "test-preset"
    assert preset.config.source_path == source_path
    assert preset.config.scope == PresetScope.USER
