"""Deterministic mock Kling adapter for tests.

Mirrors KlingAdapter's Protocol surface. No network calls. Requests point
at mock:// URLs - the test harness intercepts them (see test_provider_adapters.py,
which monkeypatches video_model_client._http).
"""

from __future__ import annotations

from typing import Optional

from recoil.execution.providers.base import (
    PollRequest,
    PollResult,
    ProviderJob,
    SubmitRequest,
    UnifiedVideoPayload,
)


class MockKlingAdapter:
    provider_id = "kling"
    supported_models = ["kling-o3", "kling-v3", "kling-v3-i2v"]
    auth_env_var = "FAL_KEY"
    base_url = "mock://queue.fal.run"
    max_prompt_chars = None
    status = "primary"
    capabilities = {
        "t2v": True,
        "i2v": True,
        "r2v": True,
        "end_frame": True,
        "audio": True,
        "negative_prompt": True,
        "resolution_480p": False,
        "resolution_720p": True,
        "resolution_1080p": False,
    }

    def build_submit(
        self, payload: UnifiedVideoPayload, tier: str
    ) -> SubmitRequest:
        return SubmitRequest(
            method="POST",
            url=f"{self.base_url}/submit/{tier}",
            headers={"Authorization": "Key mock"},
            body={
                "prompt": payload.prompt,
                "model": payload.model_id,
                "duration": str(payload.duration_s),
                "tier": tier,
            },
        )

    def parse_submit(self, resp, payload, tier):
        request_id = resp.get("request_id", "mock-kling-req")
        return ProviderJob(
            provider_id=self.provider_id,
            model_id=payload.model_id,
            native_id=request_id,
            tier=tier,
            duration_s=payload.duration_s,
            resolution=payload.resolution,
            native_state={
                "model_path": "mock/kling",
                "status_url": resp.get("status_url")
                    or f"{self.base_url}/status/{request_id}",
                "response_url": resp.get("response_url")
                    or f"{self.base_url}/result/{request_id}",
            },
        )

    def build_poll(self, job):
        return PollRequest(
            method="GET", url=job.native_state["status_url"], headers={}
        )

    def parse_poll(self, resp, job):
        status = (resp.get("status") or "unknown").upper()
        if status == "COMPLETED":
            return PollResult(status="COMPLETED", raw=resp)
        if status == "FAILED":
            return PollResult(
                status="FAILED",
                error=resp.get("error", "mock kling failed"),
                raw=resp,
            )
        return PollResult(status="IN_PROGRESS", raw=resp)

    def build_result_fetch(self, job) -> Optional[PollRequest]:
        return PollRequest(
            method="GET", url=job.native_state["response_url"], headers={}
        )

    def parse_result(self, resp, job):
        v = resp.get("video") or {}
        a = resp.get("audio") or {}
        return PollResult(
            status="COMPLETED",
            video_url=v.get("url") or "mock://kling/video.mp4",
            audio_url=a.get("url"),
            observed_cost=None,
            raw=resp,
        )

    def compute_cost(
        self, duration_s: float, tier: str, profile: dict
    ) -> float:
        return 0.126 * float(duration_s)


ADAPTER = MockKlingAdapter()
__all__ = ["MockKlingAdapter", "ADAPTER"]
