"""YouTube video repository for database operations."""

import logging
from typing import Any, Dict, List, Optional, Protocol, runtime_checkable
from uuid import UUID

from ..database.models import YouTubeVideo
from ..database.connection import get_db_session

logger = logging.getLogger(__name__)


@runtime_checkable
class YouTubeRepositoryProtocol(Protocol):
    """Protocol for YouTube repository operations."""

    async def create(self, video_data: Dict[str, Any]) -> YouTubeVideo:
        """Create a new YouTube video record."""
        ...

    async def get_by_id(self, video_id: UUID) -> Optional[YouTubeVideo]:
        """Get video by ID."""
        ...

    async def get_by_youtube_id(self, youtube_id: str) -> Optional[YouTubeVideo]:
        """Get video by YouTube ID."""
        ...

    async def update(self, video_id: UUID, video_data: Dict[str, Any]) -> Optional[YouTubeVideo]:
        """Update video record."""
        ...

    async def delete(self, video_id: UUID) -> bool:
        """Delete video record."""
        ...

    async def list_all(self, limit: int = 100, offset: int = 0) -> List[YouTubeVideo]:
        """List all videos with pagination."""
        ...

    async def search_by_title(self, title: str, limit: int = 50) -> List[YouTubeVideo]:
        """Search videos by title."""
        ...

    async def get_by_channel(self, channel: str, limit: int = 50) -> List[YouTubeVideo]:
        """Get videos by channel."""
        ...


class YouTubeRepository:
    """YouTube video repository implementation."""

    def __init__(self):
        pass

    async def create(self, video_data: Dict[str, Any]) -> YouTubeVideo:
        """Create a new YouTube video record."""
        try:
            with get_db_session() as session:
                video = YouTubeVideo(**video_data)
                session.add(video)
                session.commit()
                session.refresh(video)
                logger.info(f"Created YouTube video: {video.youtube_id}")
                return video
        except Exception as e:
            logger.error(f"Error creating YouTube video: {e}")
            raise

    async def get_by_youtube_id(self, youtube_id: str) -> Optional[YouTubeVideo]:
        """Get video by YouTube ID."""
        try:
            with get_db_session() as session:
                video = session.query(YouTubeVideo).filter(
                    YouTubeVideo.youtube_id == youtube_id
                ).first()
                return video
        except Exception as e:
            logger.error(f"Error getting video by YouTube ID: {e}")
            return None

    async def update(self, video_id: UUID, video_data: Dict[str, Any]) -> Optional[YouTubeVideo]:
        """Update video record."""
        try:
            with get_db_session() as session:
                video = session.query(YouTubeVideo).filter(YouTubeVideo.id == video_id).first()
                if not video:
                    return None
                
                for key, value in video_data.items():
                    if hasattr(video, key):
                        setattr(video, key, value)
                
                session.commit()
                session.refresh(video)
                logger.info(f"Updated YouTube video: {video.youtube_id}")
                return video
        except Exception as e:
            logger.error(f"Error updating YouTube video: {e}")
            raise

    async def delete(self, video_id: UUID) -> bool:
        """Delete video record."""
        try:
            with get_db_session() as session:
                video = session.query(YouTubeVideo).filter(YouTubeVideo.id == video_id).first()
                if not video:
                    return False
                
                session.delete(video)
                session.commit()
                logger.info(f"Deleted YouTube video: {video.youtube_id}")
                return True
        except Exception as e:
            logger.error(f"Error deleting YouTube video: {e}")
            return False

    async def list_all(self, limit: int = 100, offset: int = 0) -> List[YouTubeVideo]:
        """List all videos with pagination."""
        try:
            with get_db_session() as session:
                videos = session.query(YouTubeVideo).order_by(
                    YouTubeVideo.created_at.desc()
                ).limit(limit).offset(offset).all()
                return videos
        except Exception as e:
            logger.error(f"Error listing YouTube videos: {e}")
            return []

    async def search_by_title(self, title: str, limit: int = 50) -> List[YouTubeVideo]:
        """Search videos by title."""
        try:
            with get_db_session() as session:
                videos = session.query(YouTubeVideo).filter(
                    YouTubeVideo.title.ilike(f"%{title}%")
                ).order_by(YouTubeVideo.created_at.desc()).limit(limit).all()
                return videos
        except Exception as e:
            logger.error(f"Error searching YouTube videos by title: {e}")
            return []

    async def get_by_channel(self, channel: str, limit: int = 50) -> List[YouTubeVideo]:
        """Get videos by channel."""
        try:
            with get_db_session() as session:
                videos = session.query(YouTubeVideo).filter(
                    YouTubeVideo.channel.ilike(f"%{channel}%")
                ).order_by(YouTubeVideo.created_at.desc()).limit(limit).all()
                return videos
        except Exception as e:
            logger.error(f"Error getting YouTube videos by channel: {e}")
            return []

    async def get_recent_videos(self, days: int = 7, limit: int = 50) -> List[YouTubeVideo]:
        """Get recently added videos."""
        try:
            from datetime import datetime, timedelta, timezone
            
            with get_db_session() as session:
                cutoff_date = datetime.now(timezone.utc) - timedelta(days=days)
                videos = session.query(YouTubeVideo).filter(
                    YouTubeVideo.created_at >= cutoff_date
                ).order_by(YouTubeVideo.created_at.desc()).limit(limit).all()
                return videos
        except Exception as e:
            logger.error(f"Error getting recent YouTube videos: {e}")
            return []

    async def get_statistics(self) -> Dict[str, Any]:
        """Get YouTube video statistics."""
        try:
            from sqlalchemy import func
            
            with get_db_session() as session:
                # Total videos
                total_videos = session.query(func.count(YouTubeVideo.id)).scalar()
                
                # Total duration
                total_duration = session.query(func.sum(YouTubeVideo.duration_seconds)).scalar() or 0
                
                # Top channels
                top_channels_result = session.query(
                    YouTubeVideo.channel,
                    func.count(YouTubeVideo.id).label('count')
                ).group_by(YouTubeVideo.channel).order_by(
                    func.count(YouTubeVideo.id).desc()
                ).limit(10).all()
                
                top_channels = [
                    {"channel": row.channel, "count": row.count} 
                    for row in top_channels_result
                ]
                
                return {
                    "total_videos": total_videos,
                    "total_duration_seconds": total_duration,
                    "total_duration_hours": total_duration / 3600,
                    "top_channels": top_channels
                }
        except Exception as e:
            logger.error(f"Error getting YouTube statistics: {e}")
            return {
                "total_videos": 0,
                "total_duration_seconds": 0,
                "total_duration_hours": 0,
                "top_channels": []
            }
