from uuid import UUID

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

from src.apps.crew_members.schemas.requests import (
    CreateCrewMemberRequest,
    UpdateCrewMemberRequest,
)
from src.apps.crew_members.schemas.responses import CrewMemberResponse
from src.apps.crew_members.services.crew_member_service import CrewMemberService
from src.core.constants import UserRole
from src.core.dependencies import require_min_role
from src.core.exceptions import NotFoundError
from src.core.schemas.response import paginated, success
from src.database.session import get_db

router = APIRouter(prefix="/crew-members", tags=["Crew Members"])


def _serialize(member) -> dict:
    return CrewMemberResponse.model_validate(member).model_dump()


@router.get("", response_model=dict)
async def list_crew_members(
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100),
    search: str = Query(None, max_length=200),
    current_user=Depends(require_min_role(UserRole.VIEW_ONLY)),
    db: AsyncSession = Depends(get_db),
):
    skip = (page - 1) * page_size
    service = CrewMemberService(db)
    members, total, available_count = await service.list(
        tenant_id=current_user.tenant_id,
        search=search,
        skip=skip,
        limit=page_size,
    )
    response = paginated(
        items=[_serialize(m) for m in members],
        total=total,
        page=page,
        page_size=page_size,
    )
    response["available_count"] = available_count
    return response


@router.post("", response_model=dict, status_code=201)
async def create_crew_member(
    body: CreateCrewMemberRequest,
    current_user=Depends(require_min_role(UserRole.MANAGER)),
    db: AsyncSession = Depends(get_db),
):
    service = CrewMemberService(db)
    member = await service.create(current_user.tenant_id, body.model_dump())
    return success(data=_serialize(member), message="Crew member created")


@router.get("/{crew_member_id}", response_model=dict)
async def get_crew_member(
    crew_member_id: UUID,
    current_user=Depends(require_min_role(UserRole.VIEW_ONLY)),
    db: AsyncSession = Depends(get_db),
):
    service = CrewMemberService(db)
    member = await service.get_by_id(current_user.tenant_id, crew_member_id)
    if not member:
        raise NotFoundError("Crew member not found")
    return success(data=_serialize(member))


@router.put("/{crew_member_id}", response_model=dict)
async def update_crew_member(
    crew_member_id: UUID,
    body: UpdateCrewMemberRequest,
    current_user=Depends(require_min_role(UserRole.MANAGER)),
    db: AsyncSession = Depends(get_db),
):
    service = CrewMemberService(db)
    member = await service.update(current_user.tenant_id, crew_member_id, body.model_dump())
    return success(data=_serialize(member), message="Crew member updated")


@router.patch("/{crew_member_id}/availability", response_model=dict)
async def toggle_crew_member_availability(
    crew_member_id: UUID,
    current_user=Depends(require_min_role(UserRole.MANAGER)),
    db: AsyncSession = Depends(get_db),
):
    service = CrewMemberService(db)
    member = await service.toggle_availability(current_user.tenant_id, crew_member_id)
    status_label = "available" if member.is_available else "unavailable"
    return success(data=_serialize(member), message=f"Crew member marked {status_label}")


@router.delete("/{crew_member_id}", status_code=204)
async def delete_crew_member(
    crew_member_id: UUID,
    current_user=Depends(require_min_role(UserRole.ADMINISTRATOR)),
    db: AsyncSession = Depends(get_db),
):
    service = CrewMemberService(db)
    await service.delete(current_user.tenant_id, crew_member_id)
