# #region ReportsRouter [C:5] [TYPE Module] [SEMANTICS fastapi, report, api, transform, search, task]
# @BRIEF FastAPI router for unified task report list and detail retrieval endpoints.
# @LAYER API
# @RELATION DEPENDS_ON -> [ReportsService]
# @RELATION DEPENDS_ON -> [get_task_manager]
# @RELATION DEPENDS_ON -> [get_clean_release_repository]
# @RELATION DEPENDS_ON -> [has_permission]
# @INVARIANT  Endpoints are read-only and do not trigger long-running tasks.
# @PRE  Reports service and dependencies are initialized.
# @POST  Router is configured and endpoints are ready for registration.
# @SIDE_EFFECT  None
# @DATA_CONTRACT  [ReportQuery] -> [ReportCollection | ReportDetailView]

from datetime import datetime

from fastapi import APIRouter, Depends, HTTPException, Query, status

from ...core.logger import belief_scope
from ...core.task_manager import TaskManager
from ...dependencies import (
    get_clean_release_repository,
    get_task_manager,
    has_permission,
)
from ...models.report import (
    ReportCollection,
    ReportDetailView,
    ReportQuery,
    ReportStatus,
    TaskType,
)
from ...services.clean_release.repository import CleanReleaseRepository
from ...services.reports.report_service import ReportsService

router = APIRouter(prefix="/api/reports", tags=["Reports"])


# #region _parse_csv_enum_list [C:1] [TYPE Function]
# @BRIEF Parse comma-separated query value into enum list.
# @PRE  raw may be None/empty or comma-separated values.
# @POST  Returns enum list or raises HTTP 400 with deterministic machine-readable payload.
# @RELATION BINDS_TO -> [ReportsRouter]
def _parse_csv_enum_list(raw: str | None, enum_cls, field_name: str) -> list:
    with belief_scope("_parse_csv_enum_list"):
        if raw is None or not raw.strip():
            return []
        values = [item.strip() for item in raw.split(",") if item.strip()]
        parsed = []
        invalid = []
        for value in values:
            try:
                parsed.append(enum_cls(value))
            except ValueError:
                invalid.append(value)
        if invalid:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail={
                    "message": f"Invalid values for '{field_name}'",
                    "field": field_name,
                    "invalid_values": invalid,
                    "allowed_values": [item.value for item in enum_cls],
                },
            )
        return parsed


# #endregion _parse_csv_enum_list


# #region list_reports [C:2] [TYPE Function]
# @BRIEF Return paginated unified reports list.
# @PRE  authenticated/authorized request and validated query params.
# @POST  returns {items,total,page,page_size,has_next,applied_filters}.
# @POST  deterministic error payload for invalid filters.
# @RELATION CALLS -> [_parse_csv_enum_list]
# @RELATION DEPENDS_ON -> [ReportQuery]
# @RELATION DEPENDS_ON -> [ReportsService]
#
# @TEST_CONTRACT  ListReportsApi ->
# {
#   required_fields: {page: int, page_size: int, sort_by: str, sort_order: str},
#   optional_fields: {task_types: str, statuses: str, search: str},
#   invariants: [
#       "Returns ReportCollection on success",
#       "Raises HTTPException 400 for invalid query parameters"
#   ]
# }
# @TEST_FIXTURE  valid_list_request -> {"page": 1, "page_size": 20}
# @TEST_EDGE  invalid_task_type_filter -> raises HTTPException(400)
# @TEST_EDGE  malformed_query -> raises HTTPException(400)
# @TEST_INVARIANT  consistent_list_payload -> verifies: [valid_list_request]
@router.get("", response_model=ReportCollection)
async def list_reports(
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100),
    task_types: str | None = Query(None, description="Comma-separated task types"),
    statuses: str | None = Query(None, description="Comma-separated statuses"),
    time_from: datetime | None = Query(None),
    time_to: datetime | None = Query(None),
    search: str | None = Query(None, max_length=200),
    sort_by: str = Query("updated_at"),
    sort_order: str = Query("desc"),
    task_manager: TaskManager = Depends(get_task_manager),
    clean_release_repository: CleanReleaseRepository = Depends(
        get_clean_release_repository
    ),
    _=Depends(has_permission("tasks", "READ")),
):
    with belief_scope("list_reports"):
        try:
            parsed_task_types = _parse_csv_enum_list(task_types, TaskType, "task_types")
            parsed_statuses = _parse_csv_enum_list(statuses, ReportStatus, "statuses")
            query = ReportQuery(
                page=page,
                page_size=page_size,
                task_types=parsed_task_types,
                statuses=parsed_statuses,
                time_from=time_from,
                time_to=time_to,
                search=search,
                sort_by=sort_by,
                sort_order=sort_order,
            )
        except HTTPException:
            raise
        except Exception as exc:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail={
                    "message": "Invalid query parameters",
                    "code": "INVALID_REPORT_QUERY",
                    "reason": str(exc),
                },
            )

        service = ReportsService(
            task_manager, clean_release_repository=clean_release_repository
        )
        return service.list_reports(query)


# #endregion list_reports


# #region get_report_detail [C:2] [TYPE Function]
# @BRIEF Return one normalized report detail with diagnostics and next actions.
# @PRE  authenticated/authorized request and existing report_id.
# @POST  returns normalized detail envelope or 404 when report is not found.
# @RELATION CALLS -> [ReportsService]
@router.get("/{report_id}", response_model=ReportDetailView)
async def get_report_detail(
    report_id: str,
    task_manager: TaskManager = Depends(get_task_manager),
    clean_release_repository: CleanReleaseRepository = Depends(
        get_clean_release_repository
    ),
    _=Depends(has_permission("tasks", "READ")),
):
    with belief_scope("get_report_detail", f"report_id={report_id}"):
        service = ReportsService(
            task_manager, clean_release_repository=clean_release_repository
        )
        detail = service.get_report_detail(report_id)
        if not detail:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail={"message": "Report not found", "code": "REPORT_NOT_FOUND"},
            )
        return detail


# #endregion get_report_detail

# #endregion ReportsRouter
