import asyncio
import logging
from datetime import datetime

from apscheduler.schedulers.background import BackgroundScheduler

from app.database import SessionLocal
from app.models.reminder import ReminderSchedule
from app.models.user import User
from app.models.quiz import Quiz
from app.models.attempt import QuizAttempt

logger = logging.getLogger(__name__)

scheduler = BackgroundScheduler()


def check_and_send_reminders():
    """Check for due reminders and send emails."""
    db = SessionLocal()
    try:
        due_reminders = db.query(ReminderSchedule).filter(
            ReminderSchedule.is_active == True,
            ReminderSchedule.next_reminder_at <= datetime.utcnow(),
        ).all()

        if not due_reminders:
            return

        logger.info(f"Found {len(due_reminders)} due reminders")

        for reminder in due_reminders:
            user = db.query(User).filter(User.id == reminder.user_id).first()
            quiz = db.query(Quiz).filter(Quiz.id == reminder.quiz_id).first()

            if not user or not quiz or quiz.deleted_at or quiz.course_id:
                reminder.is_active = False
                continue

            # Deactivate if the user has no completed attempts left for this quiz
            # (e.g., they deleted their attempts — spaced repetition no longer applies).
            has_completed_attempt = db.query(QuizAttempt.id).filter(
                QuizAttempt.user_id == user.id,
                QuizAttempt.quiz_id == quiz.id,
                QuizAttempt.completed_at.isnot(None),
            ).first() is not None
            if not has_completed_attempt:
                reminder.is_active = False
                continue

            # Respect the user's opt-out preference (canonical source: Postgres).
            if user.reminders_disabled:
                continue

            # Send email asynchronously
            try:
                from app.services.email_service import send_reminder_email
                loop = asyncio.new_event_loop()
                loop.run_until_complete(
                    send_reminder_email(
                        email=user.email,
                        user_name=user.name,
                        quiz_title=quiz.title,
                        score=reminder.performance_score,
                        next_date=reminder.next_reminder_at.strftime("%Y-%m-%d"),
                    )
                )
                loop.close()
            except Exception as e:
                logger.error(f"Failed to send reminder {reminder.id}: {e}")

            # Schedule next reminder
            from datetime import timedelta
            reminder.next_reminder_at = datetime.utcnow() + timedelta(days=reminder.interval_days)

        db.commit()
    except Exception as e:
        logger.exception(f"Scheduler error: {e}")
    finally:
        db.close()


def start_scheduler():
    """Start the APScheduler with daily reminder check."""
    scheduler.add_job(
        check_and_send_reminders,
        "interval",
        hours=24,
        id="reminder_check",
        replace_existing=True,
    )
    scheduler.start()
    logger.info("Scheduler started — reminder check runs every 24 hours")


def stop_scheduler():
    if scheduler.running:
        scheduler.shutdown()
