"""
API endpoints for Diagnostic Reports, Pathologist Verification, Rejections, and Versioned Amendments.
"""

from datetime import datetime
from typing import Literal
from uuid import UUID

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

from app.core.auth_deps import require_any_permission, require_permission
from app.core.dependencies import get_db
from app.core.exceptions import NotFoundException
from app.core.pagination import PaginationParams
from app.core.permissions import PermissionCode
from app.core.responses import PaginatedResponse, SuccessResponse
from app.models.report import ReportStatus
from app.models.user import User, UserRole
from app.schemas.notification import NotificationResponse
from app.schemas.report import (
    ReportAmendRequest,
    ReportDetailResponse,
    ReportRejectRequest,
    ReportReleaseRequest,
    ReportResendRequest,
    ReportResponse,
    ReportSubmitRequest,
    ReportVerifyRequest,
)
from app.schemas.user import UserResponse
from app.services.notification_service import NotificationService
from app.services.report_service import ReportService

router = APIRouter(prefix="/reports", tags=["Reports & Pathologist Verification"])
service = ReportService()


@router.get(
    "/verifiers",
    response_model=SuccessResponse[list[UserResponse]],
    summary="List available medical verifiers/pathologists",
)
async def list_verifiers(
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_permission(PermissionCode.REPORT_WRITE)),
) -> SuccessResponse[list[UserResponse]]:
    """List active pathologists and medical verifiers for clinical sign-off."""
    stmt = select(User).where(
        User.is_active.is_(True),
        User.role.in_([UserRole.PATHOLOGIST, UserRole.DOCTOR]),
    )
    if not current_user.is_superadmin and current_user.lab_id:
        stmt = stmt.where(User.lab_id == current_user.lab_id)
    stmt = stmt.order_by(User.name)
    res = await db.execute(stmt)
    users = list(res.scalars().all())
    data = [UserResponse.model_validate(u) for u in users]
    return SuccessResponse(data=data)


@router.get(
    "",
    response_model=PaginatedResponse[ReportResponse],
    summary="List diagnostic reports with filters",
)
async def list_reports(
    status: ReportStatus | None = Query(None, description="Filter by report verification state"),
    statuses: list[ReportStatus] | None = Query(None, description="Filter by one or more report states"),
    order_id: UUID | None = Query(None, description="Filter by visit order ID"),
    patient_id: UUID | None = Query(None, description="Filter reports for one patient"),
    activity_from: datetime | None = Query(
        None,
        description="Include reports created, verified, or released at/after this time",
    ),
    activity_to: datetime | None = Query(None, description="Exclusive upper bound for report activity time"),
    critical_only: bool = Query(False, description="Only reports with ≥1 abnormal analyte flag"),
    modality: Literal["pathology", "imaging"] | None = Query(
        None,
        description="Discipline filter: pathology (lab), imaging (radiology). Mixed matches both.",
    ),
    pagination: PaginationParams = Depends(),
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_permission(PermissionCode.REPORT_READ)),
) -> PaginatedResponse[ReportResponse]:
    """List lab diagnostic reports with pagination, branch scoping, and lifecycle state filters."""
    return await service.list_reports(
        db=db,
        current_user=current_user,
        pagination=pagination,
        status=status,
        statuses=statuses,
        order_id=order_id,
        patient_id=patient_id,
        activity_from=activity_from,
        activity_to=activity_to,
        critical_only=critical_only,
        modality=modality,
    )


@router.get(
    "/{id}",
    response_model=SuccessResponse[ReportDetailResponse],
    summary="Get report details",
)
async def get_report(
    id: UUID,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_permission(PermissionCode.REPORT_READ)),
) -> SuccessResponse[ReportDetailResponse]:
    """Fetch complete diagnostic report details with observations and verifier signature."""
    res = await service.get_report(db, report_id=id, current_user=current_user)
    return SuccessResponse(data=res)


@router.get(
    "/order/{order_id}/versions",
    response_model=SuccessResponse[list[ReportResponse]],
    summary="Get all report versions for an order",
)
async def get_order_reports(
    order_id: UUID,
    modality: Literal["pathology", "imaging"] | None = Query(
        None, description="Restrict lineage to one discipline side"
    ),
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_permission(PermissionCode.REPORT_READ)),
) -> SuccessResponse[list[ReportResponse]]:
    """Fetch complete version lineage and audit trail for an order's diagnostic reports."""
    res = await service.get_order_reports(db, order_id=order_id, current_user=current_user, modality=modality)
    return SuccessResponse(data=res)


@router.post(
    "/{id}/submit",
    response_model=SuccessResponse[ReportDetailResponse],
    summary="Submit report for pathologist verification",
)
async def submit_for_verification(
    id: UUID,
    payload: ReportSubmitRequest,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_permission(PermissionCode.REPORT_WRITE)),
) -> SuccessResponse[ReportDetailResponse]:
    """Submit a draft report with entered observations for pathologist review."""
    res = await service.submit_for_verification(
        db=db,
        report_id=id,
        data=payload,
        current_user=current_user,
    )
    return SuccessResponse(data=res, message="Report submitted for verification")


@router.post(
    "/{id}/verify",
    response_model=SuccessResponse[ReportDetailResponse],
    summary="Pathologist electronic verification sign-off",
)
async def verify_report(
    id: UUID,
    payload: ReportVerifyRequest,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_permission(PermissionCode.REPORT_VERIFY)),
) -> SuccessResponse[ReportDetailResponse]:
    """
    Authorize and electronically sign off on clinical findings.
    Transitions report to VERIFIED and order to COMPLETED.
    """
    res = await service.verify_report(
        db=db,
        report_id=id,
        data=payload,
        current_user=current_user,
    )
    return SuccessResponse(data=res, message="Report verified and signed successfully")


@router.post(
    "/{id}/reject",
    response_model=SuccessResponse[ReportDetailResponse],
    summary="Reject report draft during medical review",
)
async def reject_report(
    id: UUID,
    payload: ReportRejectRequest,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_permission(PermissionCode.REPORT_VERIFY)),
) -> SuccessResponse[ReportDetailResponse]:
    """
    Reject diagnostic report draft with clinical rationale.
    Requires correction or sample redraw.
    """
    res = await service.reject_report(
        db=db,
        report_id=id,
        data=payload,
        current_user=current_user,
    )
    return SuccessResponse(data=res, message="Report rejected back for re-testing/correction")


@router.post(
    "/{id}/amend",
    response_model=SuccessResponse[ReportDetailResponse],
    summary="Create versioned amendment from verified report",
)
async def amend_report(
    id: UUID,
    payload: ReportAmendRequest,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_permission(PermissionCode.REPORT_VERIFY)),
) -> SuccessResponse[ReportDetailResponse]:
    """
    Create a new versioned report amendment (e.g. version 2) preserving the
    prior version for complete legal and clinical auditability.
    """
    res = await service.amend_report(
        db=db,
        report_id=id,
        data=payload,
        current_user=current_user,
    )
    return SuccessResponse(data=res, message="New report amendment version created")


@router.post(
    "/{id}/release",
    response_model=SuccessResponse[ReportDetailResponse],
    summary="Release verified report to patient",
)
async def release_report(
    id: UUID,
    payload: ReportReleaseRequest,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(
        require_any_permission(
            PermissionCode.REPORT_VERIFY,
            PermissionCode.REPORT_READ,
            PermissionCode.NOTIFICATION_WRITE,
        )
    ),
) -> SuccessResponse[ReportDetailResponse]:
    """Mark verified report as officially released to the patient / ordering physician."""
    res = await service.release_report(
        db=db,
        report_id=id,
        data=payload,
        current_user=current_user,
    )
    return SuccessResponse(data=res, message="Report officially released")


@router.post(
    "/{id}/resend",
    response_model=SuccessResponse[NotificationResponse],
    summary="Re-dispatch released report email",
)
async def resend_report_email(
    id: UUID,
    payload: ReportResendRequest,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_permission(PermissionCode.NOTIFICATION_WRITE)),
) -> SuccessResponse[NotificationResponse]:
    """Re-send a released report to a (possibly corrected) patient email address."""
    report = await service.report_repo.get_by_id(db, id)
    if report is None:
        raise NotFoundException(message=f"Report {id} not found")
    notif = await NotificationService().resend_report_email(
        db,
        report=report,
        email=payload.email,
        current_user=current_user,
    )
    return SuccessResponse(data=NotificationResponse.model_validate(notif), message="Report re-dispatched")


@router.get(
    "/{id}/pdf",
    summary="Download or stream dynamic diagnostic report PDF",
    responses={
        200: {
            "content": {"application/pdf": {}},
            "description": "Returns generated diagnostic report as binary PDF",
        }
    },
)
async def get_report_pdf(
    id: UUID,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_permission(PermissionCode.REPORT_READ)),
) -> Response:
    """
    Render and stream dynamic medical diagnostic report PDF on-the-fly.
    No static file storage on disk is required.
    """
    pdf_bytes, filename = await service.render_report_pdf(
        db=db,
        report_id=id,
        current_user=current_user,
    )
    return Response(
        content=pdf_bytes,
        media_type="application/pdf",
        headers={
            "Content-Disposition": f'inline; filename="{filename}"',
            "Cache-Control": "private, no-cache, no-store, must-revalidate",
        },
    )


@router.get(
    "/{id}/preview",
    summary="Preview diagnostic report HTML",
    responses={
        200: {
            "content": {"text/html": {}},
            "description": "Returns HTML representation of report for browser preview",
        }
    },
)
async def get_report_preview(
    id: UUID,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_permission(PermissionCode.REPORT_READ)),
) -> Response:
    """Preview report HTML directly in browser."""
    html_content = await service.render_report_html(
        db=db,
        report_id=id,
        current_user=current_user,
    )
    return Response(
        content=html_content,
        media_type="text/html",
        headers={"Cache-Control": "private, no-cache, no-store, must-revalidate"},
    )
