"""Deterministic mock fal adapter for tests.

Mirrors FalAdapter'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 MockFalAdapter:
    provider_id = "fal"
    supported_models = ["seeddance-2.0"]
    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": True, "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, "tier": tier},
        )

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

    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 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 {}
        return PollResult(status="COMPLETED", video_url=v.get("url"), audio_url=None, observed_cost=None, raw=resp)

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


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