"""Recording transport for fixture-driven Caliper tests."""

from __future__ import annotations

from typing import Any

from test_support.transport_base import BaseRecordingTransport
from test_support.transport_helpers import dump_model
from timeback_common import CaliperPaths

from ..types.api import JobStatus, SendEventsResult, StoredEvent, ValidationResult


def create_recording_transport(
    fail_request: dict[str, Any] | None = None,
    transport_config: dict[str, Any] | None = None,
) -> BaseRecordingTransport:
    """Create a transport-like object that records calls and returns stub responses."""
    return _CaliperRecordingTransport(fail_request=fail_request, transport_config=transport_config)


class _CaliperRecordingTransport(BaseRecordingTransport):
    """Caliper-specific recording transport with caliper paths and stubs."""

    def __init__(self, **kwargs: Any) -> None:
        super().__init__(**kwargs)
        self.paths = self._build_paths()

    def _default_get_stub(self, path: str) -> dict[str, Any]:
        if "/jobs/" in path and path.endswith("/status"):
            return {"job": dump_model(_stub_job_status())}
        if path.startswith("/caliper/events/") and path != "/caliper/events":
            return {"event": dump_model(_stub_event())}
        if path == "/caliper/events" or path.startswith("/caliper/events?"):
            return {
                "events": [dump_model(_stub_event())],
                "pagination": {"total": 1, "totalPages": 1, "currentPage": 1, "limit": 10},
            }
        return {}

    def _default_post_stub(self, path: str) -> dict[str, Any]:
        if path == self.paths.validate:
            return dump_model(_stub_validation_result())
        return dump_model(_stub_send_result())

    def _build_paths(self) -> CaliperPaths:
        defaults: dict[str, str | None] = {
            "send": "/caliper/event",
            "validate": "/caliper/event/validate",
            "list": "/caliper/events",
            "get": "/caliper/events/{id}",
            "job_status": "/jobs/{id}/status",
        }

        exclude_map = {
            "send": "send",
            "validate": "validate",
            "list": "list",
            "get": "get",
            "jobStatus": "job_status",
            "job_status": "job_status",
        }

        self.apply_exclude_paths(
            defaults, exclude_map, self._transport_config.get("excludePaths", [])
        )

        return CaliperPaths(
            send=defaults["send"] or "",
            validate=defaults["validate"],
            list=defaults["list"],
            get=defaults["get"],
            job_status=defaults["job_status"],
        )


def _stub_event() -> StoredEvent:
    return StoredEvent(
        id=1,
        externalId="urn:uuid:stub-event-001",
        sensor="https://sensor.test/1",
        type="Event",
        profile="GeneralProfile",
        action="Completed",
        eventTime="2025-01-01T00:00:00Z",
        sendTime="2025-01-01T00:00:00Z",
        created_at="2025-01-01T00:00:00Z",
    )


def _stub_send_result() -> SendEventsResult:
    return SendEventsResult(jobId="stub-job-001")


def _stub_validation_result() -> ValidationResult:
    return ValidationResult(status="success")


def _stub_job_status() -> JobStatus:
    return JobStatus(id="stub-job-001", state="completed")
