"""WESP-shaped reports API for copied static UI (/api/reports)."""

from __future__ import annotations

import json
from datetime import UTC, datetime, timedelta
from typing import Any

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

from app.core.database import session_scope
from app.modules.sync.tenant import TenantContext, require_enterprise_zootech
from app.modules.zootech.report_models import ZootechLoadingReport, ZootechUnloadingReport
from sqlalchemy import select

router = APIRouter()


def _require_ent(enterprise_id: str, tenant: TenantContext) -> None:
    if tenant.enterprise_id != enterprise_id:
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="ENTERPRISE_FORBIDDEN")


def _parse_payload(row: ZootechLoadingReport | ZootechUnloadingReport) -> dict[str, Any]:
    if not row.payload_json:
        return {}
    try:
        data = json.loads(row.payload_json)
    except json.JSONDecodeError:
        return {}
    return data if isinstance(data, dict) else {}


def _parse_date_range(
    date_from: str | None, date_to: str | None
) -> tuple[datetime, datetime] | None:
    if not date_from or not date_to:
        end = datetime.now(UTC)
        return end - timedelta(hours=24), end + timedelta(seconds=1)
    try:
        start = datetime.strptime(date_from.strip(), "%Y-%m-%d").replace(tzinfo=UTC)
        end = datetime.strptime(date_to.strip(), "%Y-%m-%d").replace(tzinfo=UTC) + timedelta(days=1)
        return start, end
    except ValueError as exc:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail={"error": True, "message": "Некорректный формат date_from/date_to (YYYY-MM-DD)"},
        ) from exc


def _parse_report_time(value: Any) -> datetime | None:
    if value is None:
        return None
    if isinstance(value, datetime):
        return value if value.tzinfo else value.replace(tzinfo=UTC)
    text = str(value).strip()
    if not text:
        return None
    try:
        parsed = datetime.fromisoformat(text.replace("Z", "+00:00"))
    except ValueError:
        return None
    return parsed if parsed.tzinfo else parsed.replace(tzinfo=UTC)


def _in_range(start_time: datetime | None, window: tuple[datetime, datetime]) -> bool:
    if start_time is None:
        return False
    start, end = window
    return start <= start_time < end


def _serialize_unloading_id(unloading_id: str, payload: dict[str, Any]) -> dict[str, Any]:
    groups = payload.get("unloading_groups")
    if not isinstance(groups, list):
        groups = payload.get("groups") if isinstance(payload.get("groups"), list) else []
    return {
        "id": unloading_id,
        "start_time": payload.get("start_time"),
        "end_time": payload.get("end_time"),
        "total_weight": payload.get("total_weight"),
        "total_unloaded_weight": payload.get("total_unloaded_weight"),
        "remaining_weight": payload.get("remaining_weight"),
        "unloading_groups": groups,
    }


def _serialize_unloading(row: ZootechUnloadingReport, payload: dict[str, Any]) -> dict[str, Any]:
    return _serialize_unloading_id(row.id, payload)


@router.get("/reports")
def list_reports_wesp(
    enterprise_id: str = Query(...),
    date_from: str | None = Query(None),
    date_to: str | None = Query(None),
    limit: int = Query(500, ge=1, le=2000),
    offset: int = Query(0, ge=0),
    tenant: TenantContext = Depends(require_enterprise_zootech),
):
    """Legacy-compatible aggregated loading reports for reports.html."""
    _require_ent(enterprise_id, tenant)
    window = _parse_date_range(date_from, date_to)

    with session_scope() as db:
        loading_rows = list(
            db.scalars(
                select(ZootechLoadingReport).where(
                    ZootechLoadingReport.enterprise_id == enterprise_id,
                    ZootechLoadingReport.is_deleted.is_(False),
                )
            )
        )
        unloading_rows = list(
            db.scalars(
                select(ZootechUnloadingReport).where(
                    ZootechUnloadingReport.enterprise_id == enterprise_id,
                    ZootechUnloadingReport.is_deleted.is_(False),
                )
            )
        )
        loading_data = [(row.id, _parse_payload(row)) for row in loading_rows]
        unloading_data: list[tuple[str, str, dict[str, Any]]] = []
        for row in unloading_rows:
            payload = _parse_payload(row)
            loading_id = str(payload.get("loading_report_id") or "").strip()
            if loading_id:
                unloading_data.append((loading_id, row.id, payload))

    unloading_by_loading: dict[str, tuple[str, dict[str, Any]]] = {
        loading_id: (unloading_id, payload) for loading_id, unloading_id, payload in unloading_data
    }

    payload: list[dict[str, Any]] = []
    for row_id, data in loading_data:
        start_time = _parse_report_time(data.get("start_time"))
        if window and not _in_range(start_time, window):
            continue
        unloading = unloading_by_loading.get(row_id)
        unloading_payload = (
            _serialize_unloading_id(unloading[0], unloading[1]) if unloading else None
        )
        payload.append(
            {
                "id": row_id,
                "recipe_id": data.get("recipe_id"),
                "recipe_name": data.get("recipe_name"),
                "start_time": data.get("start_time"),
                "end_time": data.get("end_time"),
                "target_mixing_time": data.get("target_mixing_time"),
                "actual_mixing_time": data.get("actual_mixing_time"),
                "total_weight": data.get("total_weight"),
                "dispenser_type": data.get("dispenser_type") or "dispenser",
                "components": data.get("components") if isinstance(data.get("components"), list) else [],
                "component_loading_times": (
                    data.get("component_loading_times")
                    if isinstance(data.get("component_loading_times"), list)
                    else []
                ),
                "unloading_data": unloading_payload,
            }
        )

    payload.sort(key=lambda item: str(item.get("start_time") or ""), reverse=True)
    result = payload[offset : offset + limit]

    # #region agent log
    try:
        import pathlib
        _log_path = pathlib.Path("/Users/vlad/Documents/wesp new (1)/.cursor/debug-785e22.log")
        _log_path.parent.mkdir(parents=True, exist_ok=True)
        with _log_path.open("a", encoding="utf-8") as _lf:
            _lf.write(json.dumps({"sessionId":"785e22","hypothesisId":"A,B","location":"wesp_compat_reports.py:list","message":"reports api response","data":{"date_from":date_from,"date_to":date_to,"total_before_filter":len(payload),"returned":len(result),"component_counts":[len(r.get("components") or []) for r in result[:5]]},"timestamp":int(datetime.now(UTC).timestamp()*1000)}, ensure_ascii=False) + "\n")
    except Exception:
        pass
    # #endregion

    return result


@router.get("/reports/ping")
def reports_ping_wesp():
    return {"status": "ok"}
