"""Mapper for converting between ProjectDB entity and Project schemas"""
from typing import Optional, List, Dict, Any
from datetime import datetime
import uuid

from src.models.entities import ProjectDB
from src.models.schemas import (
    ProjectData,
    CreateProjectRequest,
    UpdateProjectRequest,
    InitializationProgress,
)


class ProjectMapper:
    """Mapper for Project entity and schemas"""
    
    @staticmethod
    def to_schema(db: ProjectDB, include_relations: bool = False) -> ProjectData:
        """Convert ProjectDB entity to ProjectData schema
        
        Args:
            db: ProjectDB entity from database
            include_relations: Whether to include related entities (assets, episodes, storyboards)
            
        Returns:
            ProjectData schema for API response
        """
        # Parse progress from database
        progress = None
        if db.progress:
            try:
                progress = InitializationProgress(**db.progress)
            except Exception:
                progress = None
        
        # Parse error from database
        error = db.error if db.error else None
        
        # Convert timestamps to datetime
        created_at = datetime.fromtimestamp(db.created_at)
        updated_at = datetime.fromtimestamp(db.updated_at)
        
        # Build base project data
        project_data = ProjectData(
            id=db.id,
            name=db.name,
            description=db.description,
            type=db.type,
            created_at=created_at,
            updated_at=updated_at,
            status=db.status,
            resolution=db.resolution,
            ratio=db.ratio,
            style_id=db.style_id,
            style_params=db.style_params,
            chapters=db.chapters,
            progress=progress,
            error=error,
            assets=[],
            episodes=[],
            storyboards=[],
            general_canvases=[],
            user_id=db.user_id,
        )
        
        # Include relations if requested
        if include_relations:
            from .asset_mapper import AssetMapper
            from .episode_mapper import EpisodeMapper
            from .storyboard_mapper import StoryboardMapper
            
            if db.assets:
                project_data.assets = [AssetMapper.to_schema(asset) for asset in db.assets]
            
            if db.episodes:
                project_data.episodes = [EpisodeMapper.to_schema(episode) for episode in db.episodes]
            
            if db.storyboards:
                project_data.storyboards = [StoryboardMapper.to_schema(storyboard) for storyboard in db.storyboards]
        
        return project_data
    
    @staticmethod
    def to_entity(
        schema: CreateProjectRequest,
        project_id: Optional[str] = None,
        user_id: Optional[str] = None
    ) -> ProjectDB:
        """Convert CreateProjectRequest schema to ProjectDB entity
        
        Args:
            schema: CreateProjectRequest from API
            project_id: Optional project ID (generated if not provided)
            user_id: Optional user ID for tracking
            
        Returns:
            ProjectDB entity for database storage
        """
        now = datetime.now().timestamp()
        
        return ProjectDB(
            id=project_id or str(uuid.uuid4()),
            name=schema.name,
            description=schema.description,
            type=schema.type,
            status="active",
            created_at=now,
            updated_at=now,
            chapters=schema.chapters,
            user_id=user_id,
        )
    
    @staticmethod
    def update_entity(db: ProjectDB, schema: UpdateProjectRequest) -> ProjectDB:
        """Update ProjectDB entity with data from UpdateProjectRequest schema
        
        Args:
            db: Existing ProjectDB entity
            schema: UpdateProjectRequest with new data
            
        Returns:
            Updated ProjectDB entity
        """
        # Update only provided fields
        if schema.name is not None:
            db.name = schema.name
        
        if schema.description is not None:
            db.description = schema.description
        
        if schema.resolution is not None:
            db.resolution = schema.resolution
        
        if schema.ratio is not None:
            db.ratio = schema.ratio
        
        if schema.style_id is not None:
            db.style_id = schema.style_id
        
        if schema.style_params is not None:
            db.style_params = schema.style_params
        
        if schema.chapters is not None:
            db.chapters = schema.chapters
        
        # Update timestamp
        db.updated_at = datetime.now().timestamp()
        
        return db
