"""Tests for Orders client."""

import pytest
from pytest_httpx import HTTPXMock

from concentriq import ConcentriqClient
from concentriq.auth import ApiKeyAuth


class TestOrdersListStains:
    """Tests for Orders.list_stains() behavior."""

    def test_list_stains_returns_dict_of_stains(self, httpx_mock: HTTPXMock):
        """List stains should return a dictionary of stain IDs to names."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/stains",
            json={
                "meta": {"status": 200},
                "data": {
                    "stains": {
                        "1": "Ki-67",
                        "2": "HER2",
                        "3": "ER",
                        "4": "PR",
                        "5": "PTEN",
                    }
                },
            },
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )
        result = client.v1.orders.list_stains()

        assert isinstance(result, dict)
        assert len(result) == 5
        assert result["1"] == "Ki-67"
        assert result["2"] == "HER2"
        assert result["5"] == "PTEN"

    def test_list_stains_returns_empty_dict_when_no_stains(self, httpx_mock: HTTPXMock):
        """List stains should return empty dict when no stains available."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/stains",
            json={"meta": {"status": 200}, "data": {"stains": {}}},
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )
        result = client.v1.orders.list_stains()

        assert result == {}

    def test_list_stains_raises_authentication_error_when_unauthorized(
        self, httpx_mock: HTTPXMock
    ):
        """List stains should raise AuthenticationError when API returns 401."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/stains",
            status_code=401,
            json={"error": "Unauthorized"},
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )

        from concentriq.exceptions import AuthenticationError

        with pytest.raises(AuthenticationError):
            client.v1.orders.list_stains()


class TestOrdersList:
    """Tests for Orders.list() behavior."""

    def test_list_returns_list_of_orders_with_stains(self, httpx_mock: HTTPXMock):
        """List should return orders with nested stain data and signed URLs."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/orders",
            json={
                "meta": {"status": 200},
                "data": {
                    "orders": [
                        {
                            "id": 1,
                            "imageId": 100,
                            "created": "2024-01-15T10:30:00Z",
                            "completed": None,
                            "isRecut": False,
                            "layers": None,
                            "comments": "Urgent stain request",
                            "requestingUserId": 50,
                            "stains": [
                                {"id": 1, "name": "Ki-67"},
                                {"id": 2, "name": "HER2"},
                            ],
                            "slideName": "slide-001.svs",
                            "imageName": "H&E Section 1",
                            "slideThumb": "https://signed-url.com/thumb.jpg",
                            "slideMacro": "https://signed-url.com/macro.jpg",
                            "slideLabel": "https://signed-url.com/label.jpg",
                        },
                        {
                            "id": 2,
                            "imageId": 101,
                            "created": "2024-01-16T14:00:00Z",
                            "completed": "2024-01-17T09:00:00Z",
                            "isRecut": True,
                            "layers": 5,
                            "comments": "Recut needed",
                            "requestingUserId": 51,
                            "stains": [],
                            "slideName": "slide-002.svs",
                            "imageName": "H&E Section 2",
                            "slideThumb": "https://signed-url.com/thumb2.jpg",
                        },
                    ]
                },
            },
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )
        result = client.v1.orders.list()

        assert isinstance(result, list)
        assert len(result) == 2
        assert result[0]["id"] == 1
        assert result[0]["isRecut"] is False
        assert len(result[0]["stains"]) == 2
        assert result[0]["stains"][0]["name"] == "Ki-67"
        assert result[0]["slideThumb"] == "https://signed-url.com/thumb.jpg"
        assert result[1]["isRecut"] is True
        assert result[1]["layers"] == 5

    def test_list_with_image_set_id_filter(self, httpx_mock: HTTPXMock):
        """List should support imageSetId query parameter."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/orders?imageSetId=5",
            json={
                "meta": {"status": 200},
                "data": {
                    "orders": [
                        {
                            "id": 1,
                            "imageId": 100,
                            "created": "2024-01-15T10:30:00Z",
                            "completed": None,
                            "isRecut": False,
                            "layers": None,
                            "comments": "",
                            "requestingUserId": 50,
                            "stains": [],
                            "slideName": "slide-001.svs",
                            "imageName": "H&E",
                            "slideThumb": "https://signed-url.com/thumb.jpg",
                        }
                    ]
                },
            },
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )
        result = client.v1.orders.list(image_set_id=5)

        assert isinstance(result, list)
        assert len(result) == 1

    def test_list_with_image_id_filter(self, httpx_mock: HTTPXMock):
        """List should support imageId query parameter."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/orders?imageId=100",
            json={
                "meta": {"status": 200},
                "data": {"orders": []},
            },
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )
        result = client.v1.orders.list(image_id=100)

        assert result == []

    def test_list_with_not_completed_filter(self, httpx_mock: HTTPXMock):
        """List should support notCompleted query parameter."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/orders?notCompleted=true",
            json={
                "meta": {"status": 200},
                "data": {"orders": []},
            },
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )
        result = client.v1.orders.list(not_completed=True)

        assert result == []

    def test_list_returns_empty_list_when_no_results(self, httpx_mock: HTTPXMock):
        """List should return empty list when API returns no data."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/orders",
            json={"meta": {"status": 200}, "data": {"orders": []}},
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )
        result = client.v1.orders.list()

        assert result == []

    def test_list_raises_authentication_error_when_unauthorized(
        self, httpx_mock: HTTPXMock
    ):
        """List should raise AuthenticationError when API returns 401."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/orders",
            status_code=401,
            json={"error": "Unauthorized"},
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )

        from concentriq.exceptions import AuthenticationError

        with pytest.raises(AuthenticationError):
            client.v1.orders.list()


class TestOrdersCreate:
    """Tests for Orders.create() behavior."""

    def test_create_stain_order_returns_created_order(self, httpx_mock: HTTPXMock):
        """Create should return the newly created stain order."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/orders",
            method="POST",
            json={
                "meta": {"status": 201},
                "data": {
                    "orders": {
                        "id": 456,
                        "imageId": 100,
                        "created": "2024-01-20T10:00:00Z",
                        "completed": None,
                        "isRecut": False,
                        "layers": None,
                        "comments": "Urgent request",
                        "requestingUserId": 50,
                    }
                },
            },
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )
        result = client.v1.orders.create({
            "imageId": 100,
            "stains": [1, 2, 3],
            "comments": "Urgent request"
        })

        assert result["id"] == 456
        assert result["imageId"] == 100
        assert result["isRecut"] is False

    def test_create_recut_order_returns_created_order(self, httpx_mock: HTTPXMock):
        """Create should return the newly created recut order."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/orders",
            method="POST",
            json={
                "meta": {"status": 201},
                "data": {
                    "orders": {
                        "id": 789,
                        "imageId": 101,
                        "created": "2024-01-20T11:00:00Z",
                        "completed": None,
                        "isRecut": True,
                        "layers": 5,
                        "comments": "Recut needed",
                        "requestingUserId": 51,
                    }
                },
            },
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )
        result = client.v1.orders.create({
            "imageId": 101,
            "layers": 5,
            "comments": "Recut needed"
        })

        assert result["id"] == 789
        assert result["isRecut"] is True
        assert result["layers"] == 5

    def test_create_raises_validation_error_on_invalid_data(
        self, httpx_mock: HTTPXMock
    ):
        """Create should raise ValidationError when data is invalid."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/orders",
            method="POST",
            status_code=400,
            json={"error": "imageId is required"},
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )

        from concentriq.exceptions import ValidationError

        with pytest.raises(ValidationError):
            client.v1.orders.create({})

    def test_create_raises_not_found_for_invalid_image(self, httpx_mock: HTTPXMock):
        """Create should raise NotFoundError for non-existent image."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/orders",
            method="POST",
            status_code=404,
            json={"error": "Image not found"},
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )

        from concentriq.exceptions import NotFoundError

        with pytest.raises(NotFoundError):
            client.v1.orders.create({"imageId": 99999, "stains": [1]})
