"""Tests for Attachments API."""

import pytest
from pytest_httpx import HTTPXMock

from concentriq import ConcentriqClient
from concentriq.auth import ApiKeyAuth
from concentriq.exceptions import AuthenticationError, NotFoundError, ValidationError


class TestAttachmentsList:
    """Tests for Attachments.list() behavior."""

    def test_list_returns_list_of_attachments_with_signed_urls(
        self, httpx_mock: HTTPXMock
    ):
        """List should return attachments with signed URLs for download."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/attachments",
            json={
                "meta": {"status": 200},
                "data": {
                    "attachments": [
                        {
                            "id": 123,
                            "name": "report.pdf",
                            "resourceType": "imageSets",
                            "resourceId": 456,
                            "storageKey": "attachments/imageSets/456/123_report.pdf",
                            "uploaderId": 789,
                            "signedURL": "https://s3.amazonaws.com/signed-url-123",
                        },
                        {
                            "id": 124,
                            "name": "data.xlsx",
                            "resourceType": "folders",
                            "resourceId": 789,
                            "storageKey": "attachments/folders/789/124_data.xlsx",
                            "uploaderId": 789,
                            "signedURL": "https://s3.amazonaws.com/signed-url-124",
                        },
                    ]
                },
            },
        )

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

        assert isinstance(result, list)
        assert len(result) == 2
        assert result[0]["id"] == 123
        assert result[0]["name"] == "report.pdf"
        assert result[0]["resourceType"] == "imageSets"
        assert result[0]["signedURL"] == "https://s3.amazonaws.com/signed-url-123"
        assert result[1]["id"] == 124
        assert result[1]["resourceType"] == "folders"

    def test_list_with_folder_id_filter(self, httpx_mock: HTTPXMock):
        """List should accept folder_id filter."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/attachments?filters=%7B%22folderId%22%3A+%5B123%5D%7D",
            json={
                "meta": {"status": 200},
                "data": {
                    "attachments": [
                        {
                            "id": 456,
                            "name": "folder_doc.pdf",
                            "resourceType": "folders",
                            "resourceId": 123,
                            "storageKey": "attachments/folders/123/456_folder_doc.pdf",
                            "uploaderId": 789,
                            "signedURL": "https://s3.amazonaws.com/signed-url",
                        }
                    ]
                },
            },
        )

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

        assert len(result) == 1
        assert result[0]["resourceId"] == 123

    def test_list_with_image_set_id_filter(self, httpx_mock: HTTPXMock):
        """List should accept image_set_id filter."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/attachments?filters=%7B%22imageSetId%22%3A+%5B456%5D%7D",
            json={
                "meta": {"status": 200},
                "data": {
                    "attachments": [
                        {
                            "id": 789,
                            "name": "imageset_doc.pdf",
                            "resourceType": "imageSets",
                            "resourceId": 456,
                            "storageKey": "attachments/imageSets/456/789_imageset_doc.pdf",
                            "uploaderId": 111,
                            "signedURL": "https://s3.amazonaws.com/signed-url",
                        }
                    ]
                },
            },
        )

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

        assert len(result) == 1
        assert result[0]["resourceId"] == 456

    def test_list_with_attachment_id_filter(self, httpx_mock: HTTPXMock):
        """List should accept attachment_id filter."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/attachments?filters=%7B%22attachmentId%22%3A+%5B999%5D%7D",
            json={
                "meta": {"status": 200},
                "data": {
                    "attachments": [
                        {
                            "id": 999,
                            "name": "specific_doc.pdf",
                            "resourceType": "imageSets",
                            "resourceId": 123,
                            "storageKey": "attachments/imageSets/123/999_specific_doc.pdf",
                            "uploaderId": 111,
                            "signedURL": "https://s3.amazonaws.com/signed-url",
                        }
                    ]
                },
            },
        )

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

        assert len(result) == 1
        assert result[0]["id"] == 999

    def test_list_with_storage_key_filter(self, httpx_mock: HTTPXMock):
        """List should accept storage_key filter."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/attachments?filters=%7B%22storageKey%22%3A+%5B%22key123%22%5D%7D",
            json={
                "meta": {"status": 200},
                "data": {
                    "attachments": [
                        {
                            "id": 888,
                            "name": "key_doc.pdf",
                            "resourceType": "folders",
                            "resourceId": 456,
                            "storageKey": "key123",
                            "uploaderId": 111,
                            "signedURL": "https://s3.amazonaws.com/signed-url",
                        }
                    ]
                },
            },
        )

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

        assert len(result) == 1
        assert result[0]["storageKey"] == "key123"

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

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

        assert result == []

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

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

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


class TestAttachmentsCreate:
    """Tests for Attachments.create() behavior."""

    def test_create_returns_attachment_id_and_storage_key(
        self, httpx_mock: HTTPXMock
    ):
        """Create should return attachmentId and storageKey for S3 upload."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/attachments",
            method="POST",
            status_code=201,
            json={
                "meta": {"status": 201},
                "data": {
                    "attachmentId": 123,
                    "storageKey": "attachments/imageSets/456/1234567890_report.pdf",
                },
            },
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )
        result = client.v1.attachments.create(
            {
                "name": "report.pdf",
                "resourceType": "imageSets",
                "resourceId": 456,
            }
        )

        assert result["attachmentId"] == 123
        assert result["storageKey"] == "attachments/imageSets/456/1234567890_report.pdf"

    def test_create_raises_validation_error_on_invalid_resource_type(
        self, httpx_mock: HTTPXMock
    ):
        """Create should raise ValidationError for invalid resource type."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/attachments",
            method="POST",
            status_code=400,
            json={"error": "invalid_resourceType"},
        )

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

        with pytest.raises(ValidationError):
            client.v1.attachments.create(
                {
                    "name": "file.pdf",
                    "resourceType": "invalidType",
                    "resourceId": 123,
                }
            )

    def test_create_raises_validation_error_on_invalid_file_extension(
        self, httpx_mock: HTTPXMock
    ):
        """Create should raise ValidationError for invalid file extension."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/attachments",
            method="POST",
            status_code=400,
            json={"error": "invalid_file_extension"},
        )

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

        with pytest.raises(ValidationError):
            client.v1.attachments.create(
                {
                    "name": "file.exe",
                    "resourceType": "imageSets",
                    "resourceId": 456,
                }
            )

    def test_create_raises_not_found_for_invalid_resource(
        self, httpx_mock: HTTPXMock
    ):
        """Create should raise NotFoundError when resource doesn't exist."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/attachments",
            method="POST",
            status_code=404,
            json={"error": "Resource not found"},
        )

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

        with pytest.raises(NotFoundError):
            client.v1.attachments.create(
                {
                    "name": "file.pdf",
                    "resourceType": "imageSets",
                    "resourceId": 999999,
                }
            )


class TestAttachmentsDelete:
    """Tests for Attachments.delete() behavior."""

    def test_delete_returns_success(self, httpx_mock: HTTPXMock):
        """Delete should complete successfully and return success message."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/attachments/123",
            method="DELETE",
            json={
                "meta": {"status": 200},
                "data": {"success": "attachment: 123 successfully deleted."},
            },
        )

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

        assert result["success"] == "attachment: 123 successfully deleted."

    def test_delete_raises_not_found_for_invalid_id(self, httpx_mock: HTTPXMock):
        """Delete should raise NotFoundError for non-existent attachment."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/attachments/999999",
            method="DELETE",
            status_code=404,
            json={"error": "Attachment not found"},
        )

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

        with pytest.raises(NotFoundError):
            client.v1.attachments.delete(id=999999)

    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/attachments/123",
            method="DELETE",
            status_code=401,
            json={"error": "Unauthorized"},
        )

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

        with pytest.raises(AuthenticationError):
            client.v1.attachments.delete(id=123)
