"""Tests for Annotations client."""

import pytest
from pytest_httpx import HTTPXMock

from concentriq import ConcentriqClient
from concentriq.auth import ApiKeyAuth
from concentriq.models.v1.filters import AnnotationFilters


class TestAnnotationsList:
    """Tests for Annotations.list() behavior."""

    def test_list_returns_list_of_annotations(self, httpx_mock: HTTPXMock):
        """List should return a list of annotation data."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/annotations",
            json={
                "meta": {"status": 200},
                "data": {
                    "annotations": [
                        {"id": 1, "text": "ROI 1", "imageId": 100},
                        {"id": 2, "text": "ROI 2", "imageId": 100},
                    ]
                },
            },
        )

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

        assert isinstance(result, list)
        assert len(result) == 2
        assert result[0]["id"] == 1
        assert result[1]["text"] == "ROI 2"

    def test_list_with_pagination_parameters(self, httpx_mock: HTTPXMock):
        """List should send pagination parameters to API."""
        # Match base URL - don't care about exact JSON encoding
        httpx_mock.add_response(
            json={"meta": {"status": 200}, "data": {"annotations": []}}
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )
        result = client.v1.annotations.list(page=2, rows_per_page=50)

        assert isinstance(result, list)

    def test_list_with_filters(self, httpx_mock: HTTPXMock):
        """List should send filter parameters to API."""
        # Match base URL - complex filter encoding handled by backend
        httpx_mock.add_response(
            json={"meta": {"status": 200}, "data": {"annotations": []}}
        )

        filters = AnnotationFilters(imageId=[100], text=["ROI"])

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

        assert isinstance(result, list)

    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/annotations",
            json={"meta": {"status": 200}, "data": {"annotations": []}},
        )

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

        assert result == []

    def test_list_returns_paginated_response_with_meta(self, httpx_mock: HTTPXMock):
        """List should return PaginatedResponse with accessible meta."""
        httpx_mock.add_response(
            json={
                "meta": {
                    "status": 200,
                    "pagination": {"page": 1, "rowsPerPage": 20, "total": 30},
                },
                "data": {
                    "annotations": [
                        {"id": 1, "text": "ROI 1", "imageId": 100},
                    ]
                },
            },
        )

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

        assert len(result) == 1
        assert result.meta["pagination"]["total"] == 30

    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/annotations",
            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.annotations.list()


class TestAnnotationsGet:
    """Tests for Annotations.get() behavior."""

    def test_get_returns_single_annotation(self, httpx_mock: HTTPXMock):
        """Get should return a single annotation by ID."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/annotations/123",
            json={
                "meta": {"status": 200},
                "data": {
                    "id": 123,
                    "text": "Test Annotation",
                    "imageId": 100,
                    "shape": "rect",
                    "color": "#FF0000",
                },
            },
        )

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

        assert result["id"] == 123
        assert result["text"] == "Test Annotation"
        assert result["imageId"] == 100

    def test_get_raises_not_found_for_invalid_id(self, httpx_mock: HTTPXMock):
        """Get should raise NotFoundError for non-existent annotation."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/annotations/99999",
            status_code=404,
            json={"error": "Annotation 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.annotations.get(99999)


class TestAnnotationsCreate:
    """Tests for Annotations.create() behavior."""

    def test_create_returns_created_annotation(self, httpx_mock: HTTPXMock):
        """Create should return the newly created annotation data."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/annotations",
            method="POST",
            json={
                "meta": {"status": 200},
                "data": {
                    "id": 456,
                    "text": "New ROI",
                    "imageId": 100,
                    "shape": "rect",
                },
            },
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )
        result = client.v1.annotations.create(
            {
                "text": "New ROI",
                "imageId": 100,
                "shape": "rect",
                "shapeString": "0,0,100,100",
                "captureBounds": "0,0,1000,1000",
                "isSegmenting": False,
            }
        )

        assert result["id"] == 456
        assert result["text"] == "New ROI"

    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/annotations",
            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.annotations.create({})

    def test_create_raises_authentication_error_when_unauthorized(
        self, httpx_mock: HTTPXMock
    ):
        """Create should raise AuthenticationError when not authenticated."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/annotations",
            method="POST",
            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.annotations.create({"text": "Test"})


class TestAnnotationsUpdate:
    """Tests for Annotations.update() behavior."""

    def test_update_returns_updated_annotation(self, httpx_mock: HTTPXMock):
        """Update should return the updated annotation."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/annotations/123",
            method="PATCH",
            json={
                "meta": {"status": 200},
                "data": {"id": 123, "text": "Updated Text", "imageId": 100},
            },
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )
        result = client.v1.annotations.update(123, {"text": "Updated Text"})

        assert result["id"] == 123
        assert result["text"] == "Updated Text"

    def test_update_raises_not_found_for_invalid_id(self, httpx_mock: HTTPXMock):
        """Update should raise NotFoundError for non-existent annotation."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/annotations/99999",
            method="PATCH",
            status_code=404,
            json={"error": "Annotation 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.annotations.update(99999, {"text": "Updated"})

    def test_update_raises_validation_error_on_invalid_data(
        self, httpx_mock: HTTPXMock
    ):
        """Update should raise ValidationError when data is invalid."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/annotations/123",
            method="PATCH",
            status_code=400,
            json={"error": "Invalid data"},
        )

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

        from concentriq.exceptions import ValidationError

        with pytest.raises(ValidationError):
            client.v1.annotations.update(123, {"invalid": "data"})

    def test_update_raises_authentication_error_when_unauthorized(
        self, httpx_mock: HTTPXMock
    ):
        """Update should raise AuthenticationError when not authenticated."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/annotations/123",
            method="PATCH",
            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.annotations.update(123, {"text": "Updated"})


class TestAnnotationsDelete:
    """Tests for Annotations.delete() behavior."""

    def test_delete_returns_successfully(self, httpx_mock: HTTPXMock):
        """Delete should complete successfully for valid ID."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/annotations/123",
            method="DELETE",
            json={
                "meta": {"status": 200},
                "data": {"success": "Annotation successfully deleted."},
            },
        )

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

        assert result is None

    def test_delete_raises_not_found_for_invalid_id(self, httpx_mock: HTTPXMock):
        """Delete should raise NotFoundError for non-existent annotation."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/annotations/99999",
            method="DELETE",
            status_code=404,
            json={"error": "Annotation 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.annotations.delete(99999)

    def test_delete_raises_authentication_error_when_unauthorized(
        self, httpx_mock: HTTPXMock
    ):
        """Delete should raise AuthenticationError when not authenticated."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/annotations/123",
            method="DELETE",
            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.annotations.delete(123)
