"""Scheduler for automatic episode checking and downloading"""
import asyncio
import logging
from datetime import datetime
from typing import Optional

from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.interval import IntervalTrigger

from app.watchlist import watchlist_manager, WatchlistManager
from app.episode_checker import EpisodeChecker, episode_checker
from app.providers_manager import providers_manager

logger = logging.getLogger(__name__)


class AutoDownloadScheduler:
    """Manages automatic episode checking and downloading on a schedule"""

    def __init__(
        self,
        wlm: Optional[WatchlistManager] = None,
        checker: Optional[EpisodeChecker] = None
    ):
        self.wlm = wlm or watchlist_manager
        self.checker = checker or episode_checker
        self.providers_mgr = providers_manager
        self.scheduler: Optional[AsyncIOScheduler] = None
        self._running = False

    async def _check_job(self):
        """Job function that runs periodically to check for new episodes"""
        try:
            logger.info("Running scheduled episode check...")
            results = await self.checker.check_all_due()

            # Log summary
            for result in results:
                if result.new_episodes_found > 0:
                    logger.info(
                        f"✓ {result.anime_title}: "
                        f"{result.new_episodes_found} new, "
                        f"{len(result.episodes_downloaded)} downloaded"
                    )

            logger.info(f"Scheduled check complete: processed {len(results)} items")

        except Exception as e:
            logger.error(f"Error in scheduled check job: {e}", exc_info=True)

    async def _health_check_job(self):
        """Job function that runs periodically to check provider health"""
        try:
            logger.info("Running scheduled provider health check...")
            await self.providers_mgr.check_all_health()
        except Exception as e:
            logger.error(f"Error in health check job: {e}")

    def start(self):
        """Start the scheduler"""
        if self._running:
            logger.warning("Scheduler already running")
            return

        try:
            self.scheduler = AsyncIOScheduler()

            # Get initial check interval from settings
            settings = self.wlm.settings
            interval_hours = settings.check_interval_hours

            # Add the job for episode checking
            self.scheduler.add_job(
                self._check_job,
                trigger=IntervalTrigger(hours=interval_hours),
                id='episode_check',
                name='Check for new episodes',
                replace_existing=True
            )

            # Add the job for provider health check (every 6 hours)
            self.scheduler.add_job(
                self._health_check_job,
                trigger=IntervalTrigger(hours=6),
                id='provider_health',
                name='Check provider health',
                replace_existing=True
            )

            # Start the scheduler
            self.scheduler.start()
            self._running = True

            logger.info(
                f"Auto-download scheduler started (checking every {interval_hours}h)"
            )

        except Exception as e:
            logger.error(f"Error starting scheduler: {e}", exc_info=True)
            raise

    def stop(self):
        """Stop the scheduler"""
        if not self._running:
            logger.warning("Scheduler not running")
            return

        try:
            if self.scheduler:
                self.scheduler.shutdown(wait=False)
                self.scheduler = None

            self._running = False
            logger.info("Auto-download scheduler stopped")

        except Exception as e:
            logger.error(f"Error stopping scheduler: {e}", exc_info=True)

    def restart(self):
        """Restart the scheduler with updated settings"""
        logger.info("Restarting scheduler with new settings...")
        self.stop()
        self.start()

    def update_interval(self, hours: int):
        """Update the check interval"""
        if not self._running:
            logger.warning("Scheduler not running, interval will be applied on start")
            return

        try:
            settings = self.wlm.get_settings()
            settings.check_interval_hours = hours
            self.wlm.update_settings(settings)

            # Restart to apply new interval
            self.restart()

            logger.info(f"Updated check interval to {hours}h")

        except Exception as e:
            logger.error(f"Error updating interval: {e}", exc_info=True)

    def get_next_run_time(self) -> Optional[datetime]:
        """Get the next scheduled run time"""
        if not self._running or not self.scheduler:
            return None

        try:
            job = self.scheduler.get_job('episode_check')
            if job:
                return job.next_run_time
        except Exception as e:
            logger.error(f"Error getting next run time: {e}")

        return None

    def is_running(self) -> bool:
        """Check if scheduler is running"""
        return self._running

    async def trigger_check_now(self):
        """Manually trigger an episode check now"""
        logger.info("Manually triggering episode check...")
        try:
            await self._check_job()
        except Exception as e:
            logger.error(f"Error in manual check: {e}", exc_info=True)
            raise

    async def trigger_health_check_now(self):
        """Manually trigger a health check now"""
        logger.info("Manually triggering provider health check...")
        try:
            await self._health_check_job()
        except Exception as e:
            logger.error(f"Error in manual health check: {e}")
            raise


# Global scheduler instance
auto_download_scheduler = AutoDownloadScheduler()
