import httpx
import pytest
import respx

from anyfast import AnyFast


@pytest.fixture
def client():
    return AnyFast(api_key="test-key")


class TestSeedance:
    @respx.mock
    def test_generate_async(self, client):
        route = respx.post("https://www.anyfast.ai/v1/video/generations").mock(
            return_value=httpx.Response(200, json={"task_id": "vid-001"})
        )

        response = client.video.generate_async(
            model="seedance",
            content=[{"type": "text", "text": "ocean waves"}],
        )

        assert route.called
        assert response.task_id == "vid-001"

    @respx.mock
    def test_generate_async_seedance_fast(self, client):
        respx.post("https://www.anyfast.ai/v1/video/generations").mock(
            return_value=httpx.Response(200, json={"task_id": "vid-002"})
        )

        response = client.video.generate_async(
            model="seedance-fast",
            content=[{"type": "text", "text": "a cat"}],
            resolution="720p",
        )

        assert response.task_id == "vid-002"

    @respx.mock
    def test_query_task(self, client):
        respx.get("https://www.anyfast.ai/v1/video/generations/vid-001").mock(
            return_value=httpx.Response(200, json={
                "id": "vid-001",
                "status": "PROCESSING",
                "progress": "60%",
            })
        )

        status = client.video.query_task("vid-001")

        assert status.is_processing()
        assert status.progress_percent == 60

    @respx.mock
    def test_run(self, client):
        respx.post("https://www.anyfast.ai/v1/video/generations").mock(
            return_value=httpx.Response(200, json={"task_id": "vid-run-001"})
        )
        respx.get("https://www.anyfast.ai/v1/video/generations/vid-run-001").mock(
            side_effect=[
                httpx.Response(200, json={"id": "vid-run-001", "status": "QUEUED"}),
                httpx.Response(200, json={
                    "id": "vid-run-001",
                    "status": "SUCCESS",
                    "result": {"url": "https://cdn.example.com/video.mp4"},
                }),
            ]
        )

        status = client.video.run(
            {"model": "seedance", "content": [{"type": "text", "text": "sunset"}]},
            poll_interval=0.01,
        )

        assert status.is_completed()
        assert status.result["url"] == "https://cdn.example.com/video.mp4"

    @respx.mock
    def test_run_failed(self, client):
        respx.post("https://www.anyfast.ai/v1/video/generations").mock(
            return_value=httpx.Response(200, json={"task_id": "vid-fail-001"})
        )
        respx.get("https://www.anyfast.ai/v1/video/generations/vid-fail-001").mock(
            return_value=httpx.Response(200, json={
                "id": "vid-fail-001",
                "status": "FAILURE",
                "fail_reason": "Content policy violation",
            })
        )

        status = client.video.run(
            {"model": "seedance", "content": [{"type": "text", "text": "test"}]},
            poll_interval=0.01,
        )

        assert status.is_failed()
        assert status.fail_reason == "Content policy violation"


class TestKling:
    @respx.mock
    def test_kling_text2video(self, client):
        route = respx.post("https://www.anyfast.ai/kling/v1/videos/text2video").mock(
            return_value=httpx.Response(200, json={"task_id": "kling-001"})
        )

        response = client.video.kling_text2video(
            model_name="kling-v2-master",
            prompt="A sunset over the ocean",
            mode="pro",
            duration="10",
            aspect_ratio="16:9",
        )

        assert route.called
        assert response.task_id == "kling-001"

    @respx.mock
    def test_kling_image2video(self, client):
        route = respx.post("https://www.anyfast.ai/kling/v1/videos/image2video").mock(
            return_value=httpx.Response(200, json={"task_id": "kling-002"})
        )

        response = client.video.kling_image2video(
            model_name="kling-v2-master",
            image="https://example.com/frame.jpg",
            prompt="Make it move",
        )

        assert route.called
        assert response.task_id == "kling-002"

    @respx.mock
    def test_kling_multi_image2video(self, client):
        route = respx.post("https://www.anyfast.ai/kling/v1/videos/multi-image2video").mock(
            return_value=httpx.Response(200, json={"task_id": "kling-003"})
        )

        response = client.video.kling_multi_image2video(
            model_name="kling-v1-6",
            image_list=[
                {"image": "https://example.com/1.jpg"},
                {"image": "https://example.com/2.jpg"},
            ],
            prompt="Transition between scenes",
        )

        assert route.called
        assert response.task_id == "kling-003"

    @respx.mock
    def test_kling_query_task(self, client):
        respx.get("https://www.anyfast.ai/kling/v1/videos/text2video/kling-001").mock(
            return_value=httpx.Response(200, json={
                "id": "kling-001",
                "status": "SUCCESS",
                "progress": "100%",
            })
        )

        status = client.video.kling_query_task("text2video", "kling-001")

        assert status.is_completed()

    @respx.mock
    def test_run_kling_text2video(self, client):
        respx.post("https://www.anyfast.ai/kling/v1/videos/text2video").mock(
            return_value=httpx.Response(200, json={"task_id": "kling-run-001"})
        )
        respx.get("https://www.anyfast.ai/kling/v1/videos/text2video/kling-run-001").mock(
            side_effect=[
                httpx.Response(200, json={"id": "kling-run-001", "status": "PROCESSING"}),
                httpx.Response(200, json={
                    "id": "kling-run-001",
                    "status": "SUCCESS",
                    "result": {"videos": [{"url": "https://cdn.example.com/done.mp4"}]},
                }),
            ]
        )

        status = client.video.run_kling_text2video(
            {"model_name": "kling-v2-master", "prompt": "A cat playing"},
            poll_interval=0.01,
        )

        assert status.is_completed()

    @respx.mock
    def test_run_kling_image2video(self, client):
        respx.post("https://www.anyfast.ai/kling/v1/videos/image2video").mock(
            return_value=httpx.Response(200, json={"task_id": "kling-i2v-001"})
        )
        respx.get("https://www.anyfast.ai/kling/v1/videos/image2video/kling-i2v-001").mock(
            return_value=httpx.Response(200, json={
                "id": "kling-i2v-001",
                "status": "SUCCESS",
            })
        )

        status = client.video.run_kling_image2video(
            {"model_name": "kling-v2-master", "image": "https://example.com/img.jpg"},
            poll_interval=0.01,
        )

        assert status.is_completed()
