from calendar import monthrange
from datetime import UTC, date, datetime

from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.database import get_db
from app.models.goal import Goal
from app.models.reminder import Reminder
from app.models.task import Task, TaskPriority
from app.models.todo import DailyTodo
from app.models.user import User
from app.routers.auth import get_current_user
from app.schemas.schedule_center import (
    ScheduleCenterDateOut,
    ScheduleCenterDaySummary,
    ScheduleCenterMonthOut,
)

router = APIRouter(prefix="/api/schedule-center", tags=["调度中心"])


def _build_summary(
    target_date: str,
    todos: list[DailyTodo],
    tasks: list[Task],
    reminders: list[Reminder],
    goals: list[Goal],
) -> ScheduleCenterDaySummary:
    return ScheduleCenterDaySummary(
        date=target_date,
        todo_total=len(todos),
        todo_completed=sum(1 for item in todos if item.is_completed),
        task_due_total=len(tasks),
        high_priority_total=sum(1 for item in tasks if item.priority in {TaskPriority.HIGH, TaskPriority.URGENT}),
        reminder_total=len(reminders),
        goal_total=len(goals),
    )


@router.get("/month", response_model=ScheduleCenterMonthOut)
async def get_month_schedule(
    year: int = Query(..., ge=2000, le=2100),
    month: int = Query(..., ge=1, le=12),
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    month_start = date(year, month, 1)
    days_in_month = monthrange(month_start.year, month_start.month)[1]
    start_key = month_start.isoformat()
    end_key = month_start.replace(day=days_in_month).isoformat()
    start_dt = datetime.combine(month_start, datetime.min.time())
    end_dt = datetime.combine(month_start.replace(day=days_in_month), datetime.max.time())

    todos = (await db.execute(
        select(DailyTodo).where(DailyTodo.user_id == current_user.id, DailyTodo.todo_date >= start_key, DailyTodo.todo_date <= end_key)
    )).scalars().all()
    tasks = (await db.execute(
        select(Task).where(
            Task.user_id == current_user.id,
            Task.due_date.is_not(None),
            Task.due_date >= start_dt,
            Task.due_date <= end_dt,
        )
    )).scalars().all()
    reminders = (await db.execute(
        select(Reminder).where(
            Reminder.user_id == current_user.id,
            Reminder.reminder_at >= start_dt,
            Reminder.reminder_at <= end_dt,
        )
    )).scalars().all()
    goals = (await db.execute(
        select(Goal).where(Goal.user_id == current_user.id, Goal.goal_date >= start_key, Goal.goal_date <= end_key)
    )).scalars().all()

    todo_map: dict[str, list[DailyTodo]] = {}
    for item in todos:
        todo_map.setdefault(item.todo_date, []).append(item)

    task_map: dict[str, list[Task]] = {}
    for item in tasks:
        key = item.due_date.date().isoformat()
        task_map.setdefault(key, []).append(item)

    reminder_map: dict[str, list[Reminder]] = {}
    for item in reminders:
        key = item.reminder_at.date().isoformat()
        reminder_map.setdefault(key, []).append(item)

    goal_map: dict[str, list[Goal]] = {}
    for item in goals:
        goal_map.setdefault(item.goal_date, []).append(item)

    days = []
    for day in range(1, days_in_month + 1):
        date_key = month_start.replace(day=day).isoformat()
        days.append(_build_summary(
            date_key,
            todo_map.get(date_key, []),
            task_map.get(date_key, []),
            reminder_map.get(date_key, []),
            goal_map.get(date_key, []),
        ))

    return ScheduleCenterMonthOut(month=f"{year:04d}-{month:02d}", days=days)


@router.get("/date", response_model=ScheduleCenterDateOut)
async def get_date_schedule(
    date_str: date = Query(...),
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    target_date = date_str
    start_dt = datetime.combine(target_date, datetime.min.time())
    end_dt = datetime.combine(target_date, datetime.max.time())
    date_key = target_date.isoformat()

    todos = (await db.execute(
        select(DailyTodo)
        .where(DailyTodo.user_id == current_user.id, DailyTodo.todo_date == date_key)
        .order_by(DailyTodo.created_at.desc())
    )).scalars().all()
    tasks = (await db.execute(
        select(Task)
        .where(
            Task.user_id == current_user.id,
            Task.due_date.is_not(None),
            Task.due_date >= start_dt,
            Task.due_date <= end_dt,
        )
        .order_by(Task.created_at.desc())
    )).scalars().all()
    reminders = (await db.execute(
        select(Reminder)
        .where(
            Reminder.user_id == current_user.id,
            Reminder.reminder_at >= start_dt,
            Reminder.reminder_at <= end_dt,
        )
        .order_by(Reminder.reminder_at.asc(), Reminder.created_at.asc())
    )).scalars().all()
    goals = (await db.execute(
        select(Goal)
        .where(Goal.user_id == current_user.id, Goal.goal_date == date_key)
        .order_by(Goal.created_at.desc())
    )).scalars().all()

    summary = _build_summary(date_key, todos, tasks, reminders, goals)
    return ScheduleCenterDateOut(
        date=date_key,
        todos=todos,
        tasks=tasks,
        reminders=reminders,
        goals=goals,
        summary=summary,
        generated_at=datetime.now(UTC),
    )
