"""
Visit order management endpoints.

Handles lab visit orders, line items, status progression, and cancellation.
"""

from datetime import datetime
from typing import Annotated
from uuid import UUID

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

from app.core.auth_deps import get_current_user, require_permission
from app.core.dependencies import get_db
from app.core.exceptions import ForbiddenException
from app.core.pagination import PaginationParams
from app.core.permissions import PermissionCode
from app.core.responses import PaginatedResponse, SuccessResponse
from app.models.order import OrderStatus
from app.models.user import User
from app.repositories.lab_repository import LabRepository
from app.schemas.order import (
    OrderAttachPackages,
    OrderAttachTests,
    OrderCreate,
    OrderUpdate,
    VisitOrderDetailResponse,
    VisitOrderResponse,
)
from app.schemas.sample import SampleCreate, SampleDetailResponse
from app.services.order_service import OrderService
from app.services.sample_service import SampleService

router = APIRouter(prefix="/orders", tags=["Orders"])
_service = OrderService()
_sample_service = SampleService()


async def _resolve_lab_id(db: AsyncSession, user: User, requested_lab_id: UUID | None) -> UUID:
    """Resolve staff work to the assigned branch and reject cross-branch requests."""
    if user.is_superadmin:
        if requested_lab_id:
            return requested_lab_id
        if user.lab_id:
            return user.lab_id
        return await LabRepository().get_default_lab_id(db)
    if not user.lab_id:
        return await LabRepository().get_default_lab_id(db)
    if requested_lab_id and requested_lab_id != user.lab_id:
        raise ForbiddenException("Access denied to another lab branch.")
    return user.lab_id


@router.get(
    "",
    response_model=PaginatedResponse[VisitOrderResponse],
    status_code=status.HTTP_200_OK,
    summary="List orders",
    description="Retrieve paginated list of visit orders.",
    dependencies=[Depends(require_permission(PermissionCode.ORDER_READ))],
)
async def list_orders(
    db: Annotated[AsyncSession, Depends(get_db)],
    current_user: Annotated[User, Depends(get_current_user)],
    pagination: Annotated[PaginationParams, Depends()],
    lab_id: UUID | None = Query(None, description="Filter by lab branch ID"),
    order_status: OrderStatus | None = Query(None, alias="status", description="Filter by status"),
    patient_id: UUID | None = Query(None, description="Filter by patient ID"),
    is_abroad: bool | None = Query(None, description="Filter by abroad patient flag"),
    destination_country: str | None = Query(None, description="Filter by destination country"),
    q: str | None = Query(None, description="Search query across order number or referral"),
    created_from: datetime | None = Query(None, description="Created at or after (inclusive, ISO datetime)"),
    created_to: datetime | None = Query(None, description="Created before (exclusive, ISO datetime)"),
) -> PaginatedResponse[VisitOrderResponse]:
    target_lab_id = await _resolve_lab_id(db, current_user, lab_id)
    return await _service.list_orders(
        db,
        pagination,
        lab_id=target_lab_id,
        status=order_status,
        patient_id=patient_id,
        is_abroad=is_abroad,
        destination_country=destination_country,
        q=q,
        created_from=created_from,
        created_to=created_to,
    )


@router.post(
    "",
    response_model=SuccessResponse[VisitOrderDetailResponse],
    status_code=status.HTTP_201_CREATED,
    summary="Create order",
    description="Create a new visit order with tests/packages for a patient.",
    dependencies=[Depends(require_permission(PermissionCode.ORDER_WRITE))],
)
async def create_order(
    data: OrderCreate,
    db: Annotated[AsyncSession, Depends(get_db)],
    current_user: Annotated[User, Depends(get_current_user)],
) -> SuccessResponse[VisitOrderDetailResponse]:
    target_lab_id = await _resolve_lab_id(db, current_user, data.lab_id)
    order = await _service.create_order(db, data.model_copy(update={"lab_id": target_lab_id}))
    return SuccessResponse(data=order, message="Visit order created successfully.")


@router.get(
    "/{order_id}",
    response_model=SuccessResponse[VisitOrderDetailResponse],
    status_code=status.HTTP_200_OK,
    summary="Get order details",
    description="Retrieve full details for an order including items and payment summary.",
    dependencies=[Depends(require_permission(PermissionCode.ORDER_READ))],
)
async def get_order(
    order_id: UUID,
    db: Annotated[AsyncSession, Depends(get_db)],
    current_user: Annotated[User, Depends(get_current_user)],
) -> SuccessResponse[VisitOrderDetailResponse]:
    target_lab_id = await _resolve_lab_id(db, current_user, None)
    order = await _service.get_order(db, order_id, lab_id=target_lab_id)
    return SuccessResponse(data=order)


@router.patch(
    "/{order_id}",
    response_model=SuccessResponse[VisitOrderDetailResponse],
    status_code=status.HTTP_200_OK,
    summary="Update order",
    description="Update order metadata or clinical notes.",
    dependencies=[Depends(require_permission(PermissionCode.ORDER_WRITE))],
)
async def update_order(
    order_id: UUID,
    data: OrderUpdate,
    db: Annotated[AsyncSession, Depends(get_db)],
    current_user: Annotated[User, Depends(get_current_user)],
) -> SuccessResponse[VisitOrderDetailResponse]:
    target_lab_id = await _resolve_lab_id(db, current_user, None)
    order = await _service.update_order(db, order_id, data, lab_id=target_lab_id)
    return SuccessResponse(data=order, message="Order updated successfully.")


@router.post(
    "/{order_id}/cancel",
    response_model=SuccessResponse[VisitOrderDetailResponse],
    status_code=status.HTTP_200_OK,
    summary="Cancel order",
    description="Cancel a visit order.",
    dependencies=[Depends(require_permission(PermissionCode.ORDER_WRITE))],
)
async def cancel_order(
    order_id: UUID,
    db: Annotated[AsyncSession, Depends(get_db)],
    current_user: Annotated[User, Depends(get_current_user)],
) -> SuccessResponse[VisitOrderDetailResponse]:
    target_lab_id = await _resolve_lab_id(db, current_user, None)
    order = await _service.cancel_order(db, order_id, lab_id=target_lab_id)
    return SuccessResponse(data=order, message="Order cancelled successfully.")


@router.post(
    "/{order_id}/tests",
    response_model=SuccessResponse[VisitOrderDetailResponse],
    status_code=status.HTTP_200_OK,
    summary="Attach tests to order",
    description=(
        "Add panels to an existing order (e.g. legacy test-less orders)."
        " Blocked once the report is verified/released. Already-attached tests are skipped."
    ),
    dependencies=[Depends(require_permission(PermissionCode.ORDER_WRITE))],
)
async def attach_order_tests(
    order_id: UUID,
    data: OrderAttachTests,
    db: Annotated[AsyncSession, Depends(get_db)],
    current_user: Annotated[User, Depends(get_current_user)],
) -> SuccessResponse[VisitOrderDetailResponse]:
    target_lab_id = await _resolve_lab_id(db, current_user, None)
    order = await _service.attach_tests(db, order_id, data.test_ids, lab_id=target_lab_id)
    return SuccessResponse(data=order, message="Tests attached to order successfully.")


@router.post(
    "/{order_id}/packages",
    response_model=SuccessResponse[VisitOrderDetailResponse],
    status_code=status.HTTP_200_OK,
    summary="Attach packages to order",
    description="Add health packages to an existing order. Blocked once the report is verified/released.",
    dependencies=[Depends(require_permission(PermissionCode.ORDER_WRITE))],
)
async def attach_order_packages(
    order_id: UUID,
    data: OrderAttachPackages,
    db: Annotated[AsyncSession, Depends(get_db)],
    current_user: Annotated[User, Depends(get_current_user)],
) -> SuccessResponse[VisitOrderDetailResponse]:
    target_lab_id = await _resolve_lab_id(db, current_user, None)
    order = await _service.attach_packages(db, order_id, data.package_ids, lab_id=target_lab_id)
    return SuccessResponse(data=order, message="Packages attached to order successfully.")


@router.post(
    "/{order_id}/samples",
    response_model=SuccessResponse[SampleDetailResponse],
    status_code=status.HTTP_201_CREATED,
    summary="Create specimen record for order",
    dependencies=[Depends(require_permission(PermissionCode.SAMPLE_WRITE))],
)
async def create_order_sample(
    order_id: UUID,
    data: SampleCreate,
    db: Annotated[AsyncSession, Depends(get_db)],
    current_user: Annotated[User, Depends(get_current_user)],
) -> SuccessResponse[SampleDetailResponse]:
    target_lab_id = await _resolve_lab_id(db, current_user, None)
    await _service.get_order(db, order_id, lab_id=target_lab_id)
    sample = await _sample_service.create_sample_for_order(
        db, order_id=order_id, data=data, current_user=current_user
    )
    return SuccessResponse(data=sample, message="Sample created successfully.")
