# chuk-motion/src/chuk_motion/themes/themes_manager.py
"""
Theme manager for Remotion video compositions.
Central system for managing and applying themes.

The theme system provides:
- Built-in YouTube-optimized themes
- Custom theme creation and registration
- Theme discovery and comparison
- Theme validation
- Export/import for sharing
"""

import json
from typing import TYPE_CHECKING, Any

if TYPE_CHECKING:
    from chuk_virtual_fs import AsyncVirtualFileSystem

from .models import Theme
from .youtube_themes import YOUTUBE_THEMES


class ThemeManager:
    """
    Manages themes for Remotion video compositions.
    Provides theme registration, selection, discovery, and application.
    """

    def __init__(self, vfs: "AsyncVirtualFileSystem"):
        """
        Initialize theme manager with built-in themes.

        Args:
            vfs: Virtual filesystem for file operations
        """
        self.vfs = vfs
        self.themes: dict[str, Theme] = {}
        self.current_theme: str | None = None
        self._register_builtin_themes()

    def _register_builtin_themes(self):
        """Register all built-in YouTube-optimized themes."""
        # YOUTUBE_THEMES is now a ThemeCollection with Pydantic Theme models
        for theme_key, theme in YOUTUBE_THEMES.items():
            self.themes[theme_key] = theme

    def register_theme(self, theme_key: str, theme: Theme) -> None:
        """
        Register a custom theme.

        Args:
            theme_key: Unique identifier for the theme
            theme: Theme object to register
        """
        self.themes[theme_key] = theme

    def list_themes(self) -> list[str]:
        """
        List all registered theme keys.

        Returns:
            List of theme keys
        """
        return list(self.themes.keys())

    def get_theme(self, theme_key: str) -> Theme | None:
        """
        Get a theme by key.

        Args:
            theme_key: Theme identifier

        Returns:
            Theme object or None if not found
        """
        return self.themes.get(theme_key)

    def get_theme_info(self, theme_key: str) -> dict[str, Any] | None:
        """
        Get detailed information about a theme.

        Args:
            theme_key: Theme identifier

        Returns:
            Dictionary with theme information or None
        """
        theme = self.get_theme(theme_key)
        if not theme:
            return None

        # Use model_dump() to convert Pydantic models to dicts
        return theme.model_dump()

    def set_current_theme(self, theme_key: str) -> bool:
        """
        Set the current active theme.

        Args:
            theme_key: Theme identifier

        Returns:
            True if successful, False if theme not found
        """
        if theme_key not in self.themes:
            return False
        self.current_theme = theme_key
        return True

    def get_current_theme(self) -> str | None:
        """
        Get the currently active theme key.

        Returns:
            Current theme key or None
        """
        return self.current_theme

    def compare_themes(self, theme_key1: str, theme_key2: str) -> dict[str, Any]:
        """
        Compare two themes side by side.

        Args:
            theme_key1: First theme identifier
            theme_key2: Second theme identifier

        Returns:
            Dictionary with comparison data
        """
        theme1 = self.get_theme(theme_key1)
        theme2 = self.get_theme(theme_key2)

        if not theme1 or not theme2:
            return {"error": "One or both themes not found"}

        return {
            "themes": [theme_key1, theme_key2],
            "comparison": {
                "names": [theme1.name, theme2.name],
                "descriptions": [theme1.description, theme2.description],
                "primary_colors": [
                    theme1.colors.primary,
                    theme2.colors.primary,
                ],
                "accent_colors": [theme1.colors.accent, theme2.colors.accent],
                "motion_feel": [
                    theme1.motion.default_spring.feel,
                    theme2.motion.default_spring.feel,
                ],
                "use_cases": [theme1.use_cases, theme2.use_cases],
            },
        }

    def search_themes(self, query: str) -> list[str]:
        """
        Search themes by name, description, or use case.

        Args:
            query: Search query string

        Returns:
            List of matching theme keys
        """
        query_lower = query.lower()
        matches = []

        for theme_key, theme in self.themes.items():
            # Search in name
            if query_lower in theme.name.lower():
                matches.append(theme_key)
                continue

            # Search in description
            if query_lower in theme.description.lower():
                matches.append(theme_key)
                continue

            # Search in use cases
            for use_case in theme.use_cases:
                if query_lower in use_case.lower():
                    matches.append(theme_key)
                    break

        return matches

    def get_themes_by_category(self, category: str) -> list[str]:
        """
        Get themes suitable for a content category.

        Args:
            category: Content category (e.g., "gaming", "education", "business")

        Returns:
            List of suitable theme keys
        """
        return self.search_themes(category)

    def validate_theme(self, theme_data: dict[str, Any]) -> dict[str, Any]:
        """
        Validate theme data structure using Pydantic model.

        Args:
            theme_data: Theme dictionary to validate

        Returns:
            Dictionary with validation results
        """
        try:
            # Pydantic will validate the structure
            Theme(**theme_data)
            return {"valid": True, "errors": []}
        except Exception as e:
            return {"valid": False, "errors": [str(e)]}

    async def export_theme(self, theme_key: str, file_path: str | None = None) -> str:
        """
        Export theme to JSON file.

        Args:
            theme_key: Theme identifier
            file_path: Optional output file path (defaults to theme_name.json)

        Returns:
            Path to exported file or error message
        """
        theme = self.get_theme(theme_key)
        if not theme:
            return f"Error: Theme '{theme_key}' not found"

        if not file_path:
            file_path = f"{theme_key}_theme.json"

        try:
            # Use model_dump_json() for direct JSON serialization
            json_content = theme.model_dump_json(indent=2)
            await self.vfs.write_file(file_path, json_content)
            return file_path
        except Exception as e:
            return f"Error exporting theme: {str(e)}"

    async def import_theme(self, file_path: str, theme_key: str | None = None) -> str:
        """
        Import theme from JSON file.

        Args:
            file_path: Path to JSON file
            theme_key: Optional key to register theme under (defaults to name from file)

        Returns:
            Success message or error
        """
        try:
            json_content = await self.vfs.read_text(file_path)
            if not json_content:
                raise ValueError("File is empty or could not be read")
            theme_data = json.loads(json_content)

            # Validate and create theme using Pydantic
            theme = Theme(**theme_data)

            # Register theme
            key = theme_key or theme.name.lower().replace(" ", "_")
            self.register_theme(key, theme)

            return f"Successfully imported theme '{theme.name}' as '{key}'"

        except Exception as e:
            return f"Error importing theme: {str(e)}"

    def create_custom_theme(
        self,
        name: str,
        description: str,
        base_theme: str | None = None,
        color_overrides: dict[str, Any] | None = None,
        typography_overrides: dict[str, Any] | None = None,
        motion_overrides: dict[str, Any] | None = None,
    ) -> str:
        """
        Create a custom theme, optionally based on an existing theme.

        Args:
            name: Custom theme name
            description: Theme description
            base_theme: Optional base theme to start from
            color_overrides: Color tokens to override
            typography_overrides: Typography tokens to override
            motion_overrides: Motion tokens to override

        Returns:
            Theme key of created theme or error message
        """
        try:
            # Start with base theme or use defaults
            if base_theme and base_theme in self.themes:
                base = self.themes[base_theme]
                # Use model_copy for Pydantic models
                theme_dict = base.model_dump()

                # Apply overrides
                if color_overrides:
                    theme_dict["colors"].update(color_overrides)
                if typography_overrides:
                    theme_dict["typography"].update(typography_overrides)
                if motion_overrides:
                    theme_dict["motion"].update(motion_overrides)

                # Update name and description
                theme_dict["name"] = name
                theme_dict["description"] = description

                # Create new theme from modified dict
                theme = Theme(**theme_dict)
            else:
                # Create minimal theme (will fail validation, user must provide all required fields)
                return "Error: Must provide a base_theme or all required token overrides"

            # Register
            theme_key = name.lower().replace(" ", "_")
            self.register_theme(theme_key, theme)

            return theme_key

        except Exception as e:
            return f"Error creating custom theme: {str(e)}"
