from __future__ import annotations

from fastapi import APIRouter, Depends, Query, status

from src.core.deps import get_entregas_service, require_api_key
from src.modules.entregas.schemas import (
    CotacaoFreteRequest,
    CotacaoFreteResponse,
    EntregaCreateRequest,
    EntregaOut,
    EntregaUpdate,
)
from src.modules.entregas.service import EntregasService

router = APIRouter(prefix="/api/v1/entregas", tags=["Entregas"])

_ALLOWED_SORT_FIELDS = {
    "status",
    "codigoRastreamento",
    "dataCriacao",
    "dataAtualizacao",
    "$createdAt",
    "$updatedAt",
    "nomeDestinatario",
    "entregadorId",
}


@router.get(
    "",
    summary="Listar entregas",
    description=(
        "Retorna uma lista paginada de entregas com filtros opcionais por status, entregador, "
        "empresa e busca textual. Inclua o header opcional `x-api-key` quando configurado."
    ),
    response_model=dict,
    responses={
        status.HTTP_200_OK: {
            "description": "Lista de entregas retornada com sucesso",
            "content": {
                "application/json": {
                    "example": {
                        "page": 1,
                        "limit": 20,
                        "total": 1,
                        "items": [
                            {
                                "id": "entrega_1",
                                "status": "pendente",
                                "codigoRastreamento": "BR123456789BR",
                                "nomeDestinatario": "Maria Silva",
                                "cidadeEntrega": "Goiânia",
                                "estadoEntrega": "GO",
                                "createdAt": "2025-10-22T08:00:00.000Z",
                                "updatedAt": "2025-10-22T08:00:00.000Z",
                            }
                        ],
                    }
                }
            },
        },
        status.HTTP_400_BAD_REQUEST: {
            "description": "Parâmetros inválidos",
            "content": {"application/json": {"example": {"detail": "Invalid sort field."}}},
        },
    },
)
async def list_entregas(
    page: int = Query(1, ge=1),
    limit: int | None = Query(None, ge=1, le=100),
    q: str | None = Query(None, min_length=1),
    status_filter: str | None = Query(None, alias="status"),
    entregador_id: str | None = Query(None),
    empresa_id: str | None = Query(None),
    sort: str | None = Query(None),
    order: str | None = Query(None, pattern="^(?i)(asc|desc)$"),
    _: None = Depends(require_api_key),
    service: EntregasService = Depends(get_entregas_service),
) -> dict:
    normalized_order = order.lower() if order else None
    normalized_sort = sort if sort in _ALLOWED_SORT_FIELDS else sort
    return await service.list(
        page=page,
        limit=limit,
        q=q,
        status_filter=status_filter,
        entregador_id=entregador_id,
        empresa_id=empresa_id,
        sort=normalized_sort,
        order=normalized_order,
    )


@router.get(
    "/{entrega_id}",
    summary="Detalhar entrega",
    description="Busca uma entrega pelo identificador. Header `x-api-key` opcional.",
    response_model=EntregaOut,
    responses={
        status.HTTP_200_OK: {
            "description": "Entrega localizada",
            "content": {
                "application/json": {
                    "example": {
                        "id": "entrega_1",
                        "status": "entregue",
                        "codigoRastreamento": "BR123456789BR",
                        "nomeDestinatario": "Maria Silva",
                        "cidadeEntrega": "Goiânia",
                        "estadoEntrega": "GO",
                        "createdAt": "2025-10-25T18:30:00.000Z",
                        "updatedAt": "2025-10-25T18:35:00.000Z",
                    }
                }
            },
        },
        status.HTTP_404_NOT_FOUND: {
            "description": "Entrega não encontrada",
            "content": {"application/json": {"example": {"detail": "Entrega not found."}}},
        },
    },
)
async def get_entrega(
    entrega_id: str,
    _: None = Depends(require_api_key),
    service: EntregasService = Depends(get_entregas_service),
) -> EntregaOut:
    return await service.get(entrega_id)


@router.post(
    "",
    summary="Criar entrega",
    description="Cria uma nova entrega no Appwrite. Header `x-api-key` opcional.",
    response_model=EntregaOut,
    status_code=status.HTTP_201_CREATED,
    responses={
        status.HTTP_201_CREATED: {
            "description": "Entrega criada",
            "content": {
                "application/json": {
                    "example": {
                        "id": "entrega_1",
                        "status": "pendente",
                        "codigoRastreamento": "BR123456789BR",
                        "nomeDestinatario": "Maria Silva",
                        "cidadeEntrega": "Goiânia",
                        "estadoEntrega": "GO",
                        "createdAt": "2025-10-22T08:00:00.000Z",
                        "updatedAt": "2025-10-22T08:00:00.000Z",
                    }
                }
            },
        },
        status.HTTP_409_CONFLICT: {
            "description": "Entrega já existente",
            "content": {"application/json": {"example": {"detail": "Entrega already exists."}}},
        },
    },
)
async def create_entrega(
    payload: EntregaCreateRequest,
    _: None = Depends(require_api_key),
    service: EntregasService = Depends(get_entregas_service),
) -> EntregaOut:
    return await service.create(payload)


@router.post(
    "/cotacao",
    summary="Calcular cotacao de frete",
    description="Calcula valor e distancia do frete usando configuracao da empresa e Mapbox.",
    response_model=CotacaoFreteResponse,
    status_code=status.HTTP_200_OK,
)
async def cotar_frete(
    payload: CotacaoFreteRequest,
    _: None = Depends(require_api_key),
    service: EntregasService = Depends(get_entregas_service),
) -> CotacaoFreteResponse:
    return await service.cotar_frete(payload)


@router.patch(
    "/{entrega_id}",
    summary="Atualizar entrega",
    description="Atualiza campos de uma entrega existente. Header `x-api-key` opcional.",
    response_model=EntregaOut,
    responses={
        status.HTTP_200_OK: {
            "description": "Entrega atualizada",
            "content": {
                "application/json": {
                    "example": {
                        "id": "entrega_1",
                        "status": "em_rota",
                        "codigoRastreamento": "BR123456789BR",
                        "nomeDestinatario": "Maria Silva",
                        "cidadeEntrega": "Goiânia",
                        "estadoEntrega": "GO",
                        "createdAt": "2025-10-22T08:00:00.000Z",
                        "updatedAt": "2025-10-22T10:00:00.000Z",
                    }
                }
            },
        },
        status.HTTP_404_NOT_FOUND: {
            "description": "Entrega não encontrada",
            "content": {"application/json": {"example": {"detail": "Entrega not found."}}},
        },
    },
)
async def update_entrega(
    entrega_id: str,
    payload: EntregaUpdate,
    _: None = Depends(require_api_key),
    service: EntregasService = Depends(get_entregas_service),
) -> EntregaOut:
    return await service.update(entrega_id, payload)


@router.delete(
    "/{entrega_id}",
    summary="Remover entrega",
    description="Remove uma entrega existente. Header `x-api-key` opcional.",
    status_code=status.HTTP_204_NO_CONTENT,
    responses={
        status.HTTP_204_NO_CONTENT: {"description": "Entrega removida"},
        status.HTTP_404_NOT_FOUND: {
            "description": "Entrega não encontrada",
            "content": {"application/json": {"example": {"detail": "Entrega not found."}}},
        },
    },
)
async def delete_entrega(
    entrega_id: str,
    _: None = Depends(require_api_key),
    service: EntregasService = Depends(get_entregas_service),
) -> None:
    await service.delete(entrega_id)
