"""Deterministic mock Wan adapter for tests.

Mirrors WanAdapter's Protocol surface. No network calls, no FAL_KEY required.
Used when RECOIL_PROVIDER_MODE=test. Submit URLs are sentinel "fal-sdk://"
strings — the test harness intercepts them via the executor's direct-
subscribe branch, NOT via _http monkeypatching.
"""

from __future__ import annotations

from typing import Optional

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


_SENTINEL_I2V = "fal-sdk://wan-i2v"
_SENTINEL_R2V = "fal-sdk://wan-r2v"


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

    def build_submit(
        self, payload: UnifiedVideoPayload, tier: str
    ) -> SubmitRequest:
        if payload.image is not None:
            return SubmitRequest(
                method="POST",
                url=_SENTINEL_I2V,
                headers={},
                body={
                    "prompt": payload.prompt,
                    "model": payload.model_id,
                    "duration": payload.duration_s,
                    "tier": tier,
                },
            )
        if payload.reference_images or payload.reference_videos:
            return SubmitRequest(
                method="POST",
                url=_SENTINEL_R2V,
                headers={},
                body={
                    "prompt": payload.prompt,
                    "model": payload.model_id,
                    "duration": payload.duration_s,
                    "tier": tier,
                },
            )
        raise ValueError(
            "MockWanAdapter.build_submit: payload missing image and refs"
        )

    def parse_submit(self, resp, payload, tier):
        sub_path = "i2v" if payload.image is not None else "r2v"
        return ProviderJob(
            provider_id=self.provider_id,
            model_id=payload.model_id,
            native_id=resp.get("native_id", "mock-wan-id"),
            tier=tier,
            duration_s=payload.duration_s,
            resolution=payload.resolution,
            native_state={
                "sub_path": sub_path,
                "video_url": resp.get("video_url")
                    or "mock://wan/video.mp4",
                "raw": resp,
            },
        )

    def build_poll(self, job):
        return PollRequest(
            method="GET", url="fal-sdk://wan-noop", headers={}
        )

    def parse_poll(self, resp, job):
        return PollResult(status="COMPLETED", raw=resp or {})

    def build_result_fetch(self, job) -> Optional[PollRequest]:
        return None

    def parse_result(self, resp, job):
        return PollResult(
            status="COMPLETED",
            video_url=job.native_state.get("video_url")
                or "mock://wan/video.mp4",
            raw=resp or {},
        )

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

    # ---- direct-subscribe path (mirrors live adapter) ----

    def direct_subscribe_i2v(self, payload: UnifiedVideoPayload) -> dict:
        return {
            "video_url": "mock://wan/i2v.mp4",
            "raw": {"video": {"url": "mock://wan/i2v.mp4"}},
            "seed": 42,
            "native_id": "mock-wan-i2v",
        }

    def direct_subscribe_r2v(self, payload: UnifiedVideoPayload) -> dict:
        return {
            "video_url": "mock://wan/r2v.mp4",
            "raw": {"video": {"url": "mock://wan/r2v.mp4"}},
            "seed": 42,
            "native_id": "mock-wan-r2v",
        }


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