import uuid

from fastapi import APIRouter, Depends, Request
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.actors import ActorType
from app.core.dependencies import (
    GESTIONNAIRE_PLUS,
    get_current_actor,
    get_current_guest_actor,
    get_current_user,
    require_role,
)
from app.core.limiter import limiter
from app.core.responses import api_response, normalize_page_param, page_response
from app.db.database import get_async_session
from app.schemas.signalement import NoteInterneCreate, SignalementAssign, SignalementCreate, SignalementUpdateStatut
from app.services.signalement_service import SignalementService

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


@router.post("/", status_code=201)
@limiter.limit("5/minute")
async def creer_signalement(
    request: Request,
    body: SignalementCreate,
    db: AsyncSession = Depends(get_async_session),
    actor=Depends(get_current_actor),
):
    service = SignalementService(db)
    actor_name = None
    if actor.actor_type == ActorType.AUTH_USER.value and actor.user is not None:
        actor_name = f"{actor.user.prenom} {actor.user.nom}".strip()
    else:
        actor_name = "Invité"
    data = await service.creer(actor.actor_type, actor.actor_id, body, actor_name=actor_name)
    return api_response(data, message="Signalement créé", status_code=201)


@router.get("/me")
async def mes_signalements(
    page: int = 0,
    size: int = 20,
    db: AsyncSession = Depends(get_async_session),
    current_user=Depends(get_current_user),
):
    resolved_page = normalize_page_param(page)
    service = SignalementService(db)
    items, total = await service.get_mes_signalements(current_user.id, page=resolved_page, size=size)
    return page_response(items, total=total, page=resolved_page, size=size)


@router.get("/guest/me")
async def mes_signalements_guest(
    page: int = 0,
    size: int = 20,
    db: AsyncSession = Depends(get_async_session),
    actor=Depends(get_current_guest_actor),
):
    resolved_page = normalize_page_param(page)
    service = SignalementService(db)
    items, total = await service.get_guest_signalements(actor.actor_id, page=resolved_page, size=size)
    return page_response(items, total=total, page=resolved_page, size=size)


@router.get("/non-traites")
async def non_traites(
    page: int = 0,
    size: int = 20,
    db: AsyncSession = Depends(get_async_session),
    _current_user=Depends(require_role(*GESTIONNAIRE_PLUS)),
):
    resolved_page = normalize_page_param(page)
    service = SignalementService(db)
    items, total = await service.get_non_traites(page=resolved_page, size=size)
    return page_response(items, total=total, page=resolved_page, size=size)


@router.get("/{signalement_id}")
async def get_signalement(
    signalement_id: uuid.UUID,
    db: AsyncSession = Depends(get_async_session),
    actor=Depends(get_current_actor),
):
    service = SignalementService(db)
    data = await service.get_by_id_for_actor(
        str(signalement_id),
        actor_type=actor.actor_type,
        actor_id=actor.actor_id,
        current_user=actor.user,
    )
    return api_response(data, message="Signalement récupéré")


@router.put("/{signalement_id}/statut")
async def update_statut(
    signalement_id: uuid.UUID,
    body: SignalementUpdateStatut,
    db: AsyncSession = Depends(get_async_session),
    current_user=Depends(require_role(*GESTIONNAIRE_PLUS)),
):
    service = SignalementService(db)
    data = await service.update_statut(str(signalement_id), body.statut, current_user)
    return api_response(data, message="Statut mis à jour")


@router.put("/{signalement_id}/assigner")
async def assigner(
    signalement_id: uuid.UUID,
    body: SignalementAssign,
    db: AsyncSession = Depends(get_async_session),
    current_user=Depends(require_role(*GESTIONNAIRE_PLUS)),
):
    service = SignalementService(db)
    data = await service.assigner(str(signalement_id), body.gestionnaireId, current_user)
    return api_response(data, message="Signalement assigné")


@router.post("/{signalement_id}/notes")
async def ajouter_note(
    signalement_id: uuid.UUID,
    body: NoteInterneCreate,
    db: AsyncSession = Depends(get_async_session),
    current_user=Depends(require_role(*GESTIONNAIRE_PLUS)),
):
    service = SignalementService(db)
    data = await service.ajouter_note(str(signalement_id), body, current_user)
    return api_response(data, message="Note ajoutée", status_code=201)


@router.get("/{signalement_id}/timeline")
async def get_timeline(
    signalement_id: uuid.UUID,
    db: AsyncSession = Depends(get_async_session),
    actor=Depends(get_current_actor),
):
    service = SignalementService(db)
    data = await service.get_timeline_for_actor(
        str(signalement_id),
        actor_type=actor.actor_type,
        actor_id=actor.actor_id,
        current_user=actor.user,
    )
    return api_response(data, message="Timeline récupérée")
