"""Watchlist management system for automatic episode tracking and downloading with SQLModel support"""
import json
import os
import uuid
import logging
from datetime import datetime, timedelta
from typing import List, Optional, Dict
from pathlib import Path

from sqlmodel import Session, select
from app.database import engine
from app.models.watchlist import (
    WatchlistItem,
    WatchlistItemTable,
    WatchlistItemCreate,
    WatchlistItemUpdate,
    WatchlistStatus,
    WatchlistSettings,
    WatchlistSettingsTable,
    NewEpisodeInfo,
    AutoDownloadResult
)

logger = logging.getLogger(__name__)

class WatchlistManager:
    """Manages user watchlist for automatic episode downloads using SQL database"""

    def __init__(self):
        self.settings: Optional[WatchlistSettings] = None
        self._load_settings()

    def _load_settings(self):
        """Load watchlist settings from database"""
        try:
            with Session(engine) as session:
                statement = select(WatchlistSettingsTable).where(WatchlistSettingsTable.user_id == "default")
                db_settings = session.exec(statement).first()
                if db_settings:
                    self.settings = WatchlistSettings(
                        check_interval_hours=db_settings.check_interval_hours,
                        auto_download_enabled=db_settings.auto_download_enabled,
                        max_concurrent_auto_downloads=db_settings.max_concurrent_auto_downloads,
                        notify_on_new_episodes=db_settings.notify_on_new_episodes,
                        include_completed_anime=db_settings.include_completed_anime
                    )
                    logger.info(f"Loaded watchlist settings from database")
                else:
                    self.settings = WatchlistSettings()
                    self._save_settings()
                    logger.info("Settings not found in database, created defaults")
        except Exception as e:
            logger.error(f"Error loading settings from database: {e}")
            self.settings = WatchlistSettings()

    def _save_settings(self):
        try:
            with Session(engine) as session:
                statement = select(WatchlistSettingsTable).where(WatchlistSettingsTable.user_id == "default")
                db_settings = session.exec(statement).first()
                
                if db_settings:
                    db_settings.check_interval_hours = self.settings.check_interval_hours
                    db_settings.auto_download_enabled = self.settings.auto_download_enabled
                    db_settings.max_concurrent_auto_downloads = self.settings.max_concurrent_auto_downloads
                    db_settings.notify_on_new_episodes = self.settings.notify_on_new_episodes
                    db_settings.include_completed_anime = self.settings.include_completed_anime
                else:
                    db_settings = WatchlistSettingsTable(
                        user_id="default",
                        check_interval_hours=self.settings.check_interval_hours,
                        auto_download_enabled=self.settings.auto_download_enabled,
                        max_concurrent_auto_downloads=self.settings.max_concurrent_auto_downloads,
                        notify_on_new_episodes=self.settings.notify_on_new_episodes,
                        include_completed_anime=self.settings.include_completed_anime
                    )
                    session.add(db_settings)
                    
                session.commit()
            logger.debug("Saved watchlist settings to database")
        except Exception as e:
            logger.error(f"Error saving settings to database: {e}")

    def _to_api_model(self, db_item: WatchlistItemTable) -> WatchlistItem:
        """Convert database table model to API response model"""
        data = db_item.model_dump()
        data["genres"] = db_item.genres
        return WatchlistItem(**data)

    def get_all(self, user_id: Optional[str] = None, status: Optional[WatchlistStatus] = None) -> List[WatchlistItem]:
        """Get all watchlist items, optionally filtered by user and status"""
        with Session(engine) as session:
            statement = select(WatchlistItemTable)
            if user_id:
                statement = statement.where(WatchlistItemTable.user_id == user_id)
            if status:
                statement = statement.where(WatchlistItemTable.status == status)
            
            # Sort by added_at descending
            statement = statement.order_by(WatchlistItemTable.added_at.desc())
            
            db_items = session.exec(statement).all()
            return [self._to_api_model(item) for item in db_items]

    def get_by_id(self, item_id: str) -> Optional[WatchlistItem]:
        """Get a specific watchlist item by ID"""
        with Session(engine) as session:
            db_item = session.get(WatchlistItemTable, item_id)
            if db_item:
                return self._to_api_model(db_item)
            return None

    def get_by_anime_url(self, anime_url: str, user_id: str) -> Optional[WatchlistItem]:
        """Get a watchlist item by anime URL and user ID"""
        with Session(engine) as session:
            statement = select(WatchlistItemTable).where(
                WatchlistItemTable.anime_url == anime_url,
                WatchlistItemTable.user_id == user_id
            )
            db_item = session.exec(statement).first()
            if db_item:
                return self._to_api_model(db_item)
            return None

    def add(self, user_id: str, item_create: WatchlistItemCreate) -> WatchlistItem:
        """Add a new anime to the watchlist"""
        # Check if already in watchlist for this user
        existing = self.get_by_anime_url(item_create.anime_url, user_id)
        if existing:
            return existing

        with Session(engine) as session:
            # Create new item
            db_item = WatchlistItemTable(
                user_id=user_id,
                anime_title=item_create.anime_title,
                anime_url=item_create.anime_url,
                provider_id=item_create.provider_id,
                lang=item_create.lang,
                auto_download=item_create.auto_download,
                quality_preference=item_create.quality_preference,
                poster_image=item_create.poster_image,
                cover_image=item_create.cover_image,
                synopsis=item_create.synopsis,
                status=WatchlistStatus.ACTIVE,
                added_at=datetime.now(),
                updated_at=datetime.now(),
                last_episode_downloaded=0
            )
            db_item.genres = item_create.genres

            session.add(db_item)
            session.commit()
            session.refresh(db_item)
            
            logger.info(f"Added {db_item.anime_title} to watchlist for user {user_id}")
            return self._to_api_model(db_item)

    # Alias for backward compatibility if needed
    add_item = add

    def update(self, item_id: str, update_data) -> Optional[WatchlistItem]:
        """Update a watchlist item"""
        with Session(engine) as session:
            db_item = session.get(WatchlistItemTable, item_id)
            if not db_item:
                return None

            # Handle both dict and WatchlistItemUpdate
            if isinstance(update_data, dict):
                update_dict = update_data
            else:
                update_dict = update_data.model_dump(exclude_unset=True)

            for key, value in update_dict.items():
                if hasattr(db_item, key):
                    setattr(db_item, key, value)
            
            db_item.updated_at = datetime.now()
            
            session.add(db_item)
            session.commit()
            session.refresh(db_item)
            
            logger.info(f"Updated watchlist item: {item_id}")
            return self._to_api_model(db_item)

    # Alias for backward compatibility
    update_item = update

    def delete(self, item_id: str) -> bool:
        """Remove an item from the watchlist"""
        with Session(engine) as session:
            db_item = session.get(WatchlistItemTable, item_id)
            if not db_item:
                return False
            
            session.delete(db_item)
            session.commit()
            
            logger.info(f"Deleted item {item_id} from watchlist")
            return True

    def update_last_checked(self, item_id: str, last_episode: Optional[int] = None):
        """Update the last_checked timestamp and optionally last episode for an item"""
        with Session(engine) as session:
            db_item = session.get(WatchlistItemTable, item_id)
            if db_item:
                db_item.last_checked = datetime.now()
                if last_episode is not None:
                    db_item.last_episode_downloaded = last_episode
                session.add(db_item)
                session.commit()

    # Alias for backward compatibility
    update_check_time = update_last_checked

    def get_due_items(self) -> List[WatchlistItem]:
        """Get all items that are due for a check based on settings"""
        interval = timedelta(hours=self.settings.check_interval_hours)
        now = datetime.now()
        
        with Session(engine) as session:
            statement = select(WatchlistItemTable).where(
                (WatchlistItemTable.status == WatchlistStatus.ACTIVE)
            )
            
            db_items = session.exec(statement).all()
            
            due_items = []
            for item in db_items:
                if not item.last_checked or (item.last_checked + interval) < now:
                    due_items.append(self._to_api_model(item))
            
            return due_items

    def update_settings(self, settings: WatchlistSettings) -> WatchlistSettings:
        """Update global watchlist settings"""
        self.settings = settings
        self._save_settings()
        logger.info("Updated watchlist settings")
        return self.settings

    def get_stats(self, user_id: str) -> Dict:
        """Get statistics for a user's watchlist"""
        items = self.get_all(user_id=user_id)
        stats = {
            "total_items": len(items),
            "active_items": len([i for i in items if i.status == WatchlistStatus.ACTIVE]),
            "paused_items": len([i for i in items if i.status == WatchlistStatus.PAUSED]),
            "completed_items": len([i for i in items if i.status == WatchlistStatus.COMPLETED]),
            "total_episodes_downloaded": sum(i.last_episode_downloaded for i in items),
            "providers": {}
        }
        
        # Count by provider
        for item in items:
            provider = item.provider_id
            stats["providers"][provider] = stats["providers"].get(provider, 0) + 1
            
        return stats


# Global watchlist manager instance
watchlist_manager = WatchlistManager()
