"""
Unit tests for FrameManager class and frame definitions
"""

import pytest
from pyPhotoAlbum.frame_manager import (
    FrameManager,
    FrameDefinition,
    FrameCategory,
    FrameType,
    get_frame_manager,
)


class TestFrameCategory:
    """Tests for FrameCategory enum"""

    def test_modern_category_value(self):
        """Test MODERN category has correct value"""
        assert FrameCategory.MODERN.value == "modern"

    def test_vintage_category_value(self):
        """Test VINTAGE category has correct value"""
        assert FrameCategory.VINTAGE.value == "vintage"

    def test_geometric_category_value(self):
        """Test GEOMETRIC category has correct value"""
        assert FrameCategory.GEOMETRIC.value == "geometric"

    def test_custom_category_value(self):
        """Test CUSTOM category has correct value"""
        assert FrameCategory.CUSTOM.value == "custom"


class TestFrameType:
    """Tests for FrameType enum"""

    def test_corners_type_value(self):
        """Test CORNERS type has correct value"""
        assert FrameType.CORNERS.value == "corners"

    def test_full_type_value(self):
        """Test FULL type has correct value"""
        assert FrameType.FULL.value == "full"

    def test_edges_type_value(self):
        """Test EDGES type has correct value"""
        assert FrameType.EDGES.value == "edges"


class TestFrameDefinition:
    """Tests for FrameDefinition dataclass"""

    def test_basic_frame_definition(self):
        """Test creating a basic frame definition"""
        frame = FrameDefinition(
            name="test_frame",
            display_name="Test Frame",
            category=FrameCategory.MODERN,
            frame_type=FrameType.FULL,
            description="A test frame",
        )
        assert frame.name == "test_frame"
        assert frame.display_name == "Test Frame"
        assert frame.category == FrameCategory.MODERN
        assert frame.frame_type == FrameType.FULL
        assert frame.description == "A test frame"

    def test_frame_definition_defaults(self):
        """Test frame definition default values"""
        frame = FrameDefinition(
            name="minimal",
            display_name="Minimal",
            category=FrameCategory.MODERN,
            frame_type=FrameType.FULL,
        )
        assert frame.description == ""
        assert frame.asset_path is None
        assert frame.colorizable is True
        assert frame.default_thickness == 5.0

    def test_corner_type_frame(self):
        """Test creating a corner-type frame"""
        frame = FrameDefinition(
            name="corners",
            display_name="Corners",
            category=FrameCategory.VINTAGE,
            frame_type=FrameType.CORNERS,
            default_thickness=8.0,
        )
        assert frame.frame_type == FrameType.CORNERS
        assert frame.default_thickness == 8.0


class TestFrameManager:
    """Tests for FrameManager class"""

    @pytest.fixture
    def frame_manager(self):
        """Create a fresh FrameManager instance"""
        return FrameManager()

    def test_frame_manager_has_frames(self, frame_manager):
        """Test that FrameManager loads bundled frames"""
        frames = frame_manager.get_all_frames()
        assert len(frames) > 0

    def test_get_frame_by_name(self, frame_manager):
        """Test getting a frame by name"""
        frame = frame_manager.get_frame("simple_line")
        assert frame is not None
        assert frame.name == "simple_line"
        assert frame.display_name == "Simple Line"

    def test_get_nonexistent_frame(self, frame_manager):
        """Test getting a nonexistent frame returns None"""
        frame = frame_manager.get_frame("nonexistent_frame")
        assert frame is None

    def test_get_frames_by_category_modern(self, frame_manager):
        """Test getting frames by MODERN category"""
        frames = frame_manager.get_frames_by_category(FrameCategory.MODERN)
        assert len(frames) > 0
        for frame in frames:
            assert frame.category == FrameCategory.MODERN

    def test_get_frames_by_category_vintage(self, frame_manager):
        """Test getting frames by VINTAGE category"""
        frames = frame_manager.get_frames_by_category(FrameCategory.VINTAGE)
        assert len(frames) > 0
        for frame in frames:
            assert frame.category == FrameCategory.VINTAGE

    def test_get_frames_by_category_geometric(self, frame_manager):
        """Test getting frames by GEOMETRIC category"""
        frames = frame_manager.get_frames_by_category(FrameCategory.GEOMETRIC)
        assert len(frames) > 0
        for frame in frames:
            assert frame.category == FrameCategory.GEOMETRIC

    def test_get_frame_names(self, frame_manager):
        """Test getting list of frame names"""
        names = frame_manager.get_frame_names()
        assert isinstance(names, list)
        assert "simple_line" in names
        assert "double_line" in names
        assert "geometric_corners" in names

    def test_bundled_frames_exist(self, frame_manager):
        """Test that expected bundled frames exist"""
        expected_frames = [
            "simple_line",
            "double_line",
            "geometric_corners",
            "floral_corner",
            "floral_flourish",
            "ornate_corner",
            "simple_corner",
            "corner_decoration",
            "corner_ornament",
        ]
        for name in expected_frames:
            frame = frame_manager.get_frame(name)
            assert frame is not None, f"Expected frame '{name}' not found"

    def test_modern_frames_are_full_type(self, frame_manager):
        """Test that modern frames are FULL type"""
        modern_frames = ["simple_line", "double_line"]
        for name in modern_frames:
            frame = frame_manager.get_frame(name)
            assert frame is not None
            assert frame.frame_type == FrameType.FULL

    def test_geometric_corners_is_corners_type(self, frame_manager):
        """Test that geometric_corners is CORNERS type"""
        frame = frame_manager.get_frame("geometric_corners")
        assert frame is not None
        assert frame.frame_type == FrameType.CORNERS

    def test_all_frames_are_colorizable(self, frame_manager):
        """Test that all bundled frames are colorizable"""
        for frame in frame_manager.get_all_frames():
            assert frame.colorizable is True


class TestGetFrameManager:
    """Tests for global frame manager instance"""

    def test_get_frame_manager_returns_instance(self):
        """Test that get_frame_manager returns a FrameManager"""
        manager = get_frame_manager()
        assert isinstance(manager, FrameManager)

    def test_get_frame_manager_returns_same_instance(self):
        """Test that get_frame_manager returns the same instance"""
        manager1 = get_frame_manager()
        manager2 = get_frame_manager()
        assert manager1 is manager2


class TestFrameCategories:
    """Tests for frame category organization"""

    @pytest.fixture
    def frame_manager(self):
        return FrameManager()

    def test_modern_category_not_empty(self, frame_manager):
        """Test MODERN category has frames"""
        frames = frame_manager.get_frames_by_category(FrameCategory.MODERN)
        assert len(frames) >= 2  # simple_line, double_line

    def test_vintage_category_not_empty(self, frame_manager):
        """Test VINTAGE category has frames"""
        frames = frame_manager.get_frames_by_category(FrameCategory.VINTAGE)
        assert len(frames) >= 3  # leafy_corners, ornate_flourish, victorian, art_nouveau

    def test_geometric_category_not_empty(self, frame_manager):
        """Test GEOMETRIC category has frames"""
        frames = frame_manager.get_frames_by_category(FrameCategory.GEOMETRIC)
        assert len(frames) >= 1  # geometric_corners

    def test_all_frames_count(self, frame_manager):
        """Test total frame count"""
        all_frames = frame_manager.get_all_frames()
        # Should be at least 8 bundled frames
        assert len(all_frames) >= 8


class TestFrameDescriptions:
    """Tests for frame descriptions"""

    @pytest.fixture
    def frame_manager(self):
        return FrameManager()

    def test_simple_line_has_description(self, frame_manager):
        """Test simple_line has a description"""
        frame = frame_manager.get_frame("simple_line")
        assert frame.description != ""

    def test_floral_corner_has_description(self, frame_manager):
        """Test floral_corner has a description"""
        frame = frame_manager.get_frame("floral_corner")
        assert frame.description != ""

    def test_all_frames_have_descriptions(self, frame_manager):
        """Test all frames have non-empty descriptions"""
        for frame in frame_manager.get_all_frames():
            assert frame.description != "", f"Frame '{frame.name}' has no description"

    def test_all_frames_have_display_names(self, frame_manager):
        """Test all frames have display names"""
        for frame in frame_manager.get_all_frames():
            assert frame.display_name != "", f"Frame '{frame.name}' has no display name"


class TestFrameThickness:
    """Tests for frame default thickness values"""

    @pytest.fixture
    def frame_manager(self):
        return FrameManager()

    def test_simple_line_thickness(self, frame_manager):
        """Test simple_line has thin default thickness"""
        frame = frame_manager.get_frame("simple_line")
        assert frame.default_thickness == 2.0

    def test_vintage_frames_are_thicker(self, frame_manager):
        """Test vintage frames have thicker default"""
        floral = frame_manager.get_frame("floral_corner")
        ornate = frame_manager.get_frame("ornate_corner")

        assert floral.default_thickness >= 8.0
        assert ornate.default_thickness >= 8.0

    def test_all_thicknesses_positive(self, frame_manager):
        """Test all frames have positive thickness"""
        for frame in frame_manager.get_all_frames():
            assert frame.default_thickness > 0
