"""
ReminderScheduler

Schedules and manages user reminders.
"""

from datetime import UTC, datetime, timedelta
from typing import TYPE_CHECKING

from sqlalchemy import select, and_

from app.models.reminder import Reminder

if TYPE_CHECKING:
    from sqlalchemy.ext.asyncio import AsyncSession


class ReminderScheduler:
    """Schedule and manage user reminders."""

    async def create_reminder(
        self,
        db: "AsyncSession",
        user_id: str,
        content: str,
        trigger_at: datetime,
        trigger_type: str = "time",
        context_memory_id: str | None = None,
    ) -> Reminder:
        """Create a new reminder."""
        reminder = Reminder(
            user_id=user_id,
            content=content,
            trigger_type=trigger_type,
            trigger_at=trigger_at,
            context_memory_id=context_memory_id,
            status="pending",
        )
        db.add(reminder)
        await db.commit()
        await db.refresh(reminder)
        return reminder

    async def get_due_reminders(self, db: "AsyncSession", user_id: str) -> list[Reminder]:
        """Get reminders that are due (status=pending, trigger_at <= now, not snoozed)."""
        now = datetime.now(UTC)
        result = await db.execute(
            select(Reminder)
            .where(
                Reminder.user_id == user_id,
                Reminder.status == "pending",
                Reminder.trigger_at <= now,
                ((Reminder.snoozed_until.is_(None)) | (Reminder.snoozed_until <= now)),
            )
            .order_by(Reminder.trigger_at.asc())
        )
        return list(result.scalars().all())

    async def snooze(
        self,
        db: "AsyncSession",
        reminder_id: int,
        minutes: int,
    ) -> Reminder | None:
        """Snooze reminder for N minutes."""
        result = await db.execute(select(Reminder).where(Reminder.id == reminder_id))
        reminder = result.scalar_one_or_none()
        if not reminder:
            return None

        reminder.status = "snoozed"
        reminder.snoozed_until = datetime.now(UTC) + timedelta(minutes=minutes)
        await db.commit()
        await db.refresh(reminder)
        return reminder

    async def dismiss(self, db: "AsyncSession", reminder_id: int) -> bool:
        """Mark reminder as dismissed."""
        result = await db.execute(select(Reminder).where(Reminder.id == reminder_id))
        reminder = result.scalar_one_or_none()
        if not reminder:
            return False

        reminder.status = "dismissed"
        await db.commit()
        return True

    async def mark_sent(self, db: "AsyncSession", reminder_id: int) -> bool:
        """Mark reminder as sent."""
        result = await db.execute(select(Reminder).where(Reminder.id == reminder_id))
        reminder = result.scalar_one_or_none()
        if not reminder:
            return False

        reminder.status = "sent"
        await db.commit()
        return True

    async def get_pending_reminders(
        self,
        db: "AsyncSession",
        user_id: str,
    ) -> list[Reminder]:
        """Get all pending reminders for a user."""
        result = await db.execute(
            select(Reminder)
            .where(
                Reminder.user_id == user_id,
                Reminder.status.in_(["pending", "snoozed"]),
            )
            .order_by(Reminder.trigger_at.asc())
        )
        return list(result.scalars().all())
