"""Tests for SeedDanceClient (fal.ai queue-based HTTP polling).

All network calls are mocked -- no real fal.ai requests.

CP-2 Phase 8 (2026-04-26): SeedDanceClient was migrated to
execution/providers/fal.py + atlas.py. The class no longer exists on
the api_client stub. Provider-level behavior is exercised by
tests/execution/providers/test_fal_*.py and test_atlas_*.py. This
module is skipped at collect time and kept for git history; CP-3 will
delete it.
"""

import pytest

pytest.skip(
    "CP-2 Phase 8 — SeedDanceClient migrated to execution/providers/fal.py "
    "and atlas.py. Provider tests live under tests/execution/providers/.",
    allow_module_level=True,
)

from unittest.mock import patch, MagicMock


def test_seeddance_init_with_api_key():
    """SeedDanceClient accepts api_key param with FAL_KEY env fallback."""
    from recoil.execution.api_client import SeedDanceClient

    # Explicit key
    client = SeedDanceClient(api_key="test-key")
    assert client._api_key == "test-key"

    # Zero-arg construction (for get_client factory compatibility)
    with patch.dict("os.environ", {"FAL_KEY": "env-key"}):
        client2 = SeedDanceClient()
        assert client2._api_key == "env-key"


def test_seeddance_submit_returns_job():
    """Submit delegates to _inner and returns its Job."""
    from recoil.execution.api_client import SeedDanceClient

    client = SeedDanceClient(api_key="test-key")

    fake_job = MagicMock()
    fake_job.job_id = "req_abc123"
    fake_job.status = "submitted"

    with patch.object(client._inner, "submit", return_value=fake_job):
        job = client.submit(
            {"prompt": "Alice walks through warehouse", "duration": "5"}
        )

    assert job.job_id == "req_abc123"
    assert job.status == "submitted"


def test_seeddance_poll_and_download():
    """submit -> wait_for_job delegates to _inner; result has model and success."""
    from recoil.execution.api_client import SeedDanceClient, GenerationResult

    client = SeedDanceClient(api_key="test-key")

    fake_job = MagicMock()
    fake_job.job_id = "req_abc123"
    fake_job.status = "submitted"
    fake_result = GenerationResult(
        success=True,
        model="seeddance-2.0",
        video_url="https://cdn.fal.ai/output/video.mp4",
    )

    with (
        patch.object(client._inner, "submit", return_value=fake_job),
        patch.object(client._inner, "wait_for_job", return_value=fake_result),
    ):
        job = client.submit({"prompt": "test", "duration": "5"})
        result = client.wait_for_job(job, timeout_s=30)

    assert result.success is True
    assert result.model == "seeddance-2.0"


def test_seeddance_timeout_after_10_minutes():
    """Timeout from _inner.wait_for_job propagates through SeedDanceClient."""
    from recoil.execution.api_client import SeedDanceClient, GenerationResult

    client = SeedDanceClient(api_key="test-key")

    fake_job = MagicMock()
    fake_job.job_id = "req_slow"
    fake_job.status = "submitted"
    timeout_result = GenerationResult(
        success=False,
        model="seeddance-2.0",
        error="timed out after 600s",
    )

    with (
        patch.object(client._inner, "submit", return_value=fake_job),
        patch.object(client._inner, "wait_for_job", return_value=timeout_result),
    ):
        job = client.submit({"prompt": "test", "duration": "5"})
        result = client.wait_for_job(job, timeout_s=600)

    assert result.success is False
    assert "timeout" in result.error.lower() or "timed out" in result.error.lower()


def test_seeddance_audio_failure_is_ok():
    """Audio absent in result = still success when video delivered."""
    from recoil.execution.api_client import SeedDanceClient, GenerationResult

    client = SeedDanceClient(api_key="test-key")

    fake_job = MagicMock()
    fake_job.job_id = "req_noaudio"
    # No audio data in result — video is primary deliverable
    ok_result = GenerationResult(
        success=True,
        model="seeddance-2.0",
        video_url="https://cdn.fal.ai/output/video.mp4",
    )

    with (
        patch.object(client._inner, "submit", return_value=fake_job),
        patch.object(client._inner, "wait_for_job", return_value=ok_result),
    ):
        job = client.submit({"prompt": "test", "duration": "5"})
        result = client.wait_for_job(job, timeout_s=30)

    assert result.success is True  # video is primary deliverable


def test_seeddance_is_available():
    """is_available() returns True when FAL_KEY is configured."""
    from recoil.execution.api_client import SeedDanceClient

    client_with_key = SeedDanceClient(api_key="test-key")
    assert client_with_key.is_available() is True

    # Create client without a key (must clear env BEFORE construction)
    with patch.dict("os.environ", {}, clear=True):
        client_no_key = SeedDanceClient(api_key=None)
        assert client_no_key.is_available() is False


def test_seeddance_cost_tracking():
    """GenerationResult.cost propagates from _inner.wait_for_job."""
    from recoil.execution.api_client import SeedDanceClient, GenerationResult

    client = SeedDanceClient(api_key="test-key")

    fake_job = MagicMock()
    fake_job.job_id = "req_cost"
    # cost_per_second for seeddance-2.0 is 0.3034; 5s duration → 1.517
    cost_result = GenerationResult(
        success=True,
        model="seeddance-2.0",
        video_url="https://cdn.fal.ai/output/video.mp4",
        cost=1.517,
    )

    with (
        patch.object(client._inner, "submit", return_value=fake_job),
        patch.object(client._inner, "wait_for_job", return_value=cost_result),
    ):
        job = client.submit({"prompt": "test", "duration": "5"})
        result = client.wait_for_job(job, timeout_s=30)

    assert result.cost > 0
    assert abs(result.cost - 1.517) < 0.05


def test_get_client_returns_seeddance():
    """get_client('seeddance-2.0') returns SeedDanceClient instance."""
    from recoil.execution.api_client import get_client, SeedDanceClient, _CLIENT_CACHE

    # Clear cache to force fresh creation
    _CLIENT_CACHE.pop("fal_ai", None)

    with patch.dict("os.environ", {"FAL_KEY": "test-key"}):
        client = get_client("seeddance-2.0")

    assert isinstance(client, SeedDanceClient)
    # Clean up cache
    _CLIENT_CACHE.pop("fal_ai", None)
