"""Scheduling router — service events."""
from uuid import UUID
from typing import Optional

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

from src.core.dependencies import require_min_role, require_tenant
from src.core.constants import UserRole
from src.core.schemas.response import success, paginated
from src.core.exceptions import NotFoundError
from src.database.session import get_db
from src.apps.auth.models.user import User
from src.apps.scheduling.models.service_event import ServiceEvent
from src.apps.scheduling.schemas.requests import (
    ServiceEventCreateRequest,
    ServiceEventUpdateRequest,
)
from src.apps.scheduling.schemas.responses import ServiceEventResponse

router = APIRouter(prefix="/scheduling", tags=["scheduling"])


async def _get_event(event_id: UUID, tenant_id: str, db: AsyncSession) -> ServiceEvent:
    result = await db.execute(
        select(ServiceEvent).where(
            ServiceEvent.id == event_id, ServiceEvent.tenant_id == tenant_id
        )
    )
    event = result.scalar_one_or_none()
    if not event:
        raise NotFoundError("Service event not found")
    return event


@router.get("/events")
async def list_events(
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100),
    status: Optional[str] = Query(None),
    service_type: Optional[str] = Query(None),
    current_user: User = Depends(require_min_role(UserRole.STAFF)),
    tenant_id: str = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
):
    filters = [ServiceEvent.tenant_id == tenant_id]
    if status:
        filters.append(ServiceEvent.status == status)
    if service_type:
        filters.append(ServiceEvent.service_type == service_type)

    total = (
        await db.execute(select(func.count()).select_from(ServiceEvent).where(*filters))
    ).scalar_one()
    offset = (page - 1) * page_size
    result = await db.execute(
        select(ServiceEvent).where(*filters)
        .order_by(ServiceEvent.service_date.desc())
        .offset(offset).limit(page_size)
    )
    items = [ServiceEventResponse.model_validate(e) for e in result.scalars().all()]
    return paginated(items, total, page, page_size)


@router.get("/events/{event_id}")
async def get_event(
    event_id: UUID,
    current_user: User = Depends(require_min_role(UserRole.STAFF)),
    tenant_id: str = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
):
    event = await _get_event(event_id, tenant_id, db)
    return success(ServiceEventResponse.model_validate(event))


@router.post("/events", status_code=201)
async def create_event(
    body: ServiceEventCreateRequest,
    current_user: User = Depends(require_min_role(UserRole.STAFF)),
    tenant_id: str = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
):
    event = ServiceEvent(
        tenant_id=tenant_id,
        status="scheduled",
        **body.model_dump(),
    )
    db.add(event)
    await db.flush()
    await db.refresh(event)
    return success(ServiceEventResponse.model_validate(event), "Service event created")


@router.patch("/events/{event_id}")
async def update_event(
    event_id: UUID,
    body: ServiceEventUpdateRequest,
    current_user: User = Depends(require_min_role(UserRole.STAFF)),
    tenant_id: str = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
):
    event = await _get_event(event_id, tenant_id, db)
    for field, value in body.model_dump(exclude_unset=True).items():
        setattr(event, field, value)
    await db.flush()
    await db.refresh(event)
    return success(ServiceEventResponse.model_validate(event))


@router.delete("/events/{event_id}", status_code=204)
async def delete_event(
    event_id: UUID,
    current_user: User = Depends(require_min_role(UserRole.MANAGER)),
    tenant_id: str = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
):
    event = await _get_event(event_id, tenant_id, db)
    await db.delete(event)
