"""
API endpoints for sample collection and specimen tracking.
"""

from uuid import UUID

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

from app.core.auth_deps import require_permission
from app.core.dependencies import get_db
from app.core.pagination import PaginationParams
from app.core.permissions import PermissionCode
from app.core.responses import PaginatedResponse, SuccessResponse
from app.models.user import User
from app.schemas.sample import (
    SampleCollectRequest,
    SampleDetailResponse,
    SampleRejectRequest,
)
from app.services.sample_service import SampleService

router = APIRouter(prefix="/samples", tags=["Samples"])
service = SampleService()


@router.get(
    "",
    response_model=PaginatedResponse[SampleDetailResponse],
    summary="List samples with filters",
)
async def list_samples(
    status: str | None = Query(
        None,
        description="Filter by sample lifecycle state (pending, collected, processing, completed, rejected)",
    ),
    sample_type: str | None = Query(None, description="Filter by specimen type"),
    order_id: str | None = Query(None, description="Filter by visit order ID or order number"),
    collected_by: UUID | None = Query(None, description="Filter by phlebotomist ID"),
    pagination: PaginationParams = Depends(),
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_permission(PermissionCode.SAMPLE_READ)),
) -> PaginatedResponse[SampleDetailResponse]:
    """List lab samples with pagination and filters."""
    return await service.list_samples(
        db=db,
        current_user=current_user,
        pagination=pagination,
        status=status,
        sample_type=sample_type,
        order_id=order_id,
        collected_by=collected_by,
    )


@router.get(
    "/barcode/{barcode}",
    response_model=SuccessResponse[SampleDetailResponse],
    summary="Barcode scanner specimen lookup",
)
async def get_by_barcode(
    barcode: str,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_permission(PermissionCode.SAMPLE_READ)),
) -> SuccessResponse[SampleDetailResponse]:
    """Scan and fetch sample, order, and patient details via barcode."""
    res = await service.get_by_barcode(db, barcode=barcode, current_user=current_user)
    return SuccessResponse(data=res)


@router.get(
    "/{id}",
    response_model=SuccessResponse[SampleDetailResponse],
    summary="Retrieve sample details",
)
async def get_sample(
    id: UUID,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_permission(PermissionCode.SAMPLE_READ)),
) -> SuccessResponse[SampleDetailResponse]:
    """Retrieve sample details by ID."""
    res = await service.get_sample(db, sample_id=id, current_user=current_user)
    return SuccessResponse(data=res)


@router.post(
    "/{id}/collect",
    response_model=SuccessResponse[SampleDetailResponse],
    summary="Mark specimen collected by phlebotomist",
)
async def collect_sample(
    id: UUID,
    data: SampleCollectRequest,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_permission(PermissionCode.SAMPLE_WRITE)),
) -> SuccessResponse[SampleDetailResponse]:
    """
    Record specimen collection. Sets collector, timestamp, and transitions status to 'collected'.
    If all order specimens are collected, advances order status to 'sample_collected'.
    """
    res = await service.collect_sample(db, sample_id=id, data=data, current_user=current_user)
    return SuccessResponse(data=res, message="Sample marked as collected successfully")


@router.post(
    "/{id}/receive",
    response_model=SuccessResponse[SampleDetailResponse],
    summary="Receive specimen in testing laboratory",
)
async def receive_sample(
    id: UUID,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_permission(PermissionCode.SAMPLE_WRITE)),
) -> SuccessResponse[SampleDetailResponse]:
    """
    Record specimen reception in the laboratory.
    Transitions sample and parent order to 'processing'.
    """
    res = await service.receive_sample(db, sample_id=id, current_user=current_user)
    return SuccessResponse(data=res, message="Sample received in laboratory successfully")


@router.post(
    "/{id}/complete",
    response_model=SuccessResponse[SampleDetailResponse],
    summary="Mark specimen testing completed",
)
async def complete_sample(
    id: UUID,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_permission(PermissionCode.SAMPLE_WRITE)),
) -> SuccessResponse[SampleDetailResponse]:
    """Mark physical specimen lifecycle as completed."""
    res = await service.complete_sample(db, sample_id=id, current_user=current_user)
    return SuccessResponse(data=res, message="Sample testing marked as completed")


@router.post(
    "/{id}/reject",
    response_model=SuccessResponse[SampleDetailResponse],
    summary="Reject defective specimen",
)
async def reject_sample(
    id: UUID,
    data: SampleRejectRequest,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_permission(PermissionCode.SAMPLE_WRITE)),
) -> SuccessResponse[SampleDetailResponse]:
    """
    Record specimen rejection (e.g. hemolyzed, clotted, insufficient volume).
    Logs mandatory rejection reason and resets specimen for re-collection.
    """
    res = await service.reject_sample(db, sample_id=id, data=data, current_user=current_user)
    return SuccessResponse(data=res, message="Sample rejection documented successfully")
