"""Tests for V3 ChannelGroups API."""

import pytest
from pytest_httpx import HTTPXMock

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


class TestChannelGroupsList:
    """Tests for ChannelGroups.list() behavior."""

    def test_list_returns_channel_groups(self, httpx_mock: HTTPXMock):
        """List should return all channel groups."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/v3/channelGroups",
            json={
                "items": [
                    {"id": 1, "name": "DAPI", "channels": ["DAPI"]},
                    {"id": 2, "name": "FITC", "channels": ["FITC"]},
                ],
                "total": 2,
            },
        )

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

        assert "items" in result
        assert len(result["items"]) == 2
        assert result["items"][0]["name"] == "DAPI"
        assert result["total"] == 2


class TestChannelGroupsGet:
    """Tests for ChannelGroups.get() behavior."""

    def test_get_returns_single_channel_group(self, httpx_mock: HTTPXMock):
        """Get should return a single channel group by ID."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/v3/channelGroups/123",
            json={"id": 123, "name": "DAPI", "channels": ["DAPI"], "description": "DAPI channel"},
        )

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

        assert result["id"] == 123
        assert result["name"] == "DAPI"

    def test_get_raises_not_found_for_invalid_id(self, httpx_mock: HTTPXMock):
        """Get should raise NotFoundError for non-existent channel group."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/v3/channelGroups/999999",
            status_code=404,
            json={"error": "Channel group not found"},
        )

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

        with pytest.raises(NotFoundError):
            client.v3.channel_groups.get(id=999999)


class TestChannelGroupsCreate:
    """Tests for ChannelGroups.create() behavior."""

    def test_create_returns_created_channel_group(self, httpx_mock: HTTPXMock):
        """Create should return the newly created channel group."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/v3/channelGroups",
            method="POST",
            status_code=201,
            json={"id": 456, "name": "Custom FITC", "channels": ["FITC", "GFP"]},
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )
        result = client.v3.channel_groups.create(
            {"name": "Custom FITC", "channels": ["FITC", "GFP"]}
        )

        assert result["id"] == 456
        assert result["name"] == "Custom FITC"

    def test_create_raises_validation_error_on_missing_name(
        self, httpx_mock: HTTPXMock
    ):
        """Create should raise ValidationError when name is missing."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/v3/channelGroups",
            method="POST",
            status_code=400,
            json={"error": "name is required"},
        )

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

        with pytest.raises(ValidationError):
            client.v3.channel_groups.create({"channels": ["DAPI"]})


class TestChannelGroupsUpdate:
    """Tests for ChannelGroups.update() behavior."""

    def test_update_returns_updated_channel_group(self, httpx_mock: HTTPXMock):
        """Update should return the updated channel group."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/v3/channelGroups/123",
            method="PUT",
            json={"id": 123, "name": "Updated DAPI", "channels": ["DAPI", "Hoechst"]},
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )
        result = client.v3.channel_groups.update(
            id=123, data={"name": "Updated DAPI", "channels": ["DAPI", "Hoechst"]}
        )

        assert result["id"] == 123
        assert result["name"] == "Updated DAPI"

    def test_update_raises_not_found_for_invalid_id(self, httpx_mock: HTTPXMock):
        """Update should raise NotFoundError for non-existent channel group."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/v3/channelGroups/999999",
            method="PUT",
            status_code=404,
            json={"error": "Channel group not found"},
        )

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

        with pytest.raises(NotFoundError):
            client.v3.channel_groups.update(id=999999, data={"name": "New Name"})


class TestChannelGroupsDelete:
    """Tests for ChannelGroups.delete() behavior."""

    def test_delete_returns_success(self, httpx_mock: HTTPXMock):
        """Delete should complete successfully."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/v3/channelGroups/123",
            method="DELETE",
            status_code=204,
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )
        result = client.v3.channel_groups.delete(id=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 channel group."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/v3/channelGroups/999999",
            method="DELETE",
            status_code=404,
            json={"error": "Channel group not found"},
        )

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

        with pytest.raises(NotFoundError):
            client.v3.channel_groups.delete(id=999999)


class TestChannelGroupsAddToRepo:
    """Tests for ChannelGroups.add_to_repo() behavior."""

    def test_add_to_repo_returns_success(self, httpx_mock: HTTPXMock):
        """Add to repo should complete successfully."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/v3/channelGroups/123/repos/456",
            method="POST",
            json={"success": True, "channelGroupId": 123, "repoId": 456},
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )
        result = client.v3.channel_groups.add_to_repo(channel_group_id=123, repo_id=456)

        assert result["success"] is True
        assert result["channelGroupId"] == 123

    def test_add_to_repo_raises_not_found_for_invalid_channel_group(
        self, httpx_mock: HTTPXMock
    ):
        """Add to repo should raise NotFoundError for non-existent channel group."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/v3/channelGroups/999999/repos/456",
            method="POST",
            status_code=404,
            json={"error": "Channel group not found"},
        )

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

        with pytest.raises(NotFoundError):
            client.v3.channel_groups.add_to_repo(channel_group_id=999999, repo_id=456)


class TestChannelGroupsRemoveFromRepo:
    """Tests for ChannelGroups.remove_from_repo() behavior."""

    def test_remove_from_repo_returns_success(self, httpx_mock: HTTPXMock):
        """Remove from repo should complete successfully."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/v3/channelGroups/123/repos/456",
            method="DELETE",
            json={"success": True, "channelGroupId": 123, "repoId": 456},
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )
        result = client.v3.channel_groups.remove_from_repo(
            channel_group_id=123, repo_id=456
        )

        assert result["success"] is True
        assert result["channelGroupId"] == 123

    def test_remove_from_repo_raises_not_found_for_invalid_channel_group(
        self, httpx_mock: HTTPXMock
    ):
        """Remove from repo should raise NotFoundError for non-existent channel group."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/v3/channelGroups/999999/repos/456",
            method="DELETE",
            status_code=404,
            json={"error": "Channel group not found"},
        )

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

        with pytest.raises(NotFoundError):
            client.v3.channel_groups.remove_from_repo(
                channel_group_id=999999, repo_id=456
            )
