"""Tests for V2 UserGroups API."""

import json

import pytest
from pytest_httpx import HTTPXMock

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


class TestUserGroupsList:
    """Tests for UserGroups.list() behavior."""

    def test_list_returns_paginated_user_groups(self, httpx_mock: HTTPXMock):
        """List should return results and total from V2 response format."""
        httpx_mock.add_response(
            json={
                "results": [
                    {
                        "id": 1,
                        "organizationId": 10,
                        "name": "Pathology Team",
                        "description": "Main pathology group",
                    },
                    {
                        "id": 2,
                        "organizationId": 10,
                        "name": "Research Team",
                        "description": "Research group",
                    },
                ],
                "total": 2,
            },
        )

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

        assert isinstance(result, dict)
        assert "results" in result
        assert len(result["results"]) == 2
        assert result["results"][0]["name"] == "Pathology Team"
        assert result["total"] == 2

        # Verify correct pagination params sent
        request = httpx_mock.get_request()
        pagination_param = request.url.params.get("pagination")
        parsed = json.loads(pagination_param)
        assert parsed["page"] == 0
        assert parsed["pageSize"] == 20
        assert parsed["orderBy"] == "id"
        assert parsed["orderDirection"] == "asc"

    def test_list_with_pagination_parameters(self, httpx_mock: HTTPXMock):
        """List should accept V2 pagination parameters."""
        httpx_mock.add_response(
            json={
                "results": [{"id": 3, "organizationId": 10, "name": "Group 3", "description": ""}],
                "total": 50,
            },
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )
        client.v2.user_groups.list(
            page=2, page_size=10, order_by="name", order_direction="desc"
        )

        request = httpx_mock.get_request()
        pagination_param = request.url.params.get("pagination")
        parsed = json.loads(pagination_param)
        assert parsed["page"] == 2
        assert parsed["pageSize"] == 10
        assert parsed["orderBy"] == "name"
        assert parsed["orderDirection"] == "desc"

    def test_list_with_filters(self, httpx_mock: HTTPXMock):
        """List should accept filter parameters."""
        httpx_mock.add_response(
            json={
                "results": [{"id": 1, "organizationId": 10, "name": "Org 10 Group", "description": ""}],
                "total": 1,
            },
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )
        result = client.v2.user_groups.list(filters={"organizationId": 10})

        assert len(result["results"]) == 1
        assert result["results"][0]["organizationId"] == 10

        request = httpx_mock.get_request()
        pagination_param = request.url.params.get("pagination")
        parsed = json.loads(pagination_param)
        assert parsed["filter"] == {"organizationId": 10}


class TestUserGroupsGet:
    """Tests for UserGroups.get() behavior."""

    def test_get_returns_single_user_group(self, httpx_mock: HTTPXMock):
        """Get should use plural path and return flat resource object."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/v2/userGroups/123",
            json={
                "id": 123,
                "organizationId": 10,
                "name": "Test Group",
                "description": "A test group",
            },
        )

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

        assert result["id"] == 123
        assert result["name"] == "Test Group"

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

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

        with pytest.raises(NotFoundError):
            client.v2.user_groups.get(id=999999)


class TestUserGroupsCreate:
    """Tests for UserGroups.create() behavior."""

    def test_create_returns_created_user_group(self, httpx_mock: HTTPXMock):
        """Create should return the newly created user group."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/v2/userGroups",
            method="POST",
            status_code=201,
            json={
                "id": 456,
                "organizationId": 10,
                "name": "New Group",
                "description": "New test group",
            },
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )
        result = client.v2.user_groups.create(
            {
                "organizationId": 10,
                "name": "New Group",
                "description": "New test group",
            }
        )

        assert result["id"] == 456
        assert result["name"] == "New Group"

    def test_create_raises_validation_error_on_missing_required_fields(
        self, httpx_mock: HTTPXMock
    ):
        """Create should raise ValidationError when required fields are missing."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/v2/userGroups",
            method="POST",
            status_code=400,
            json={"error": "organizationId and name are required"},
        )

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

        with pytest.raises(ValidationError):
            client.v2.user_groups.create({"name": "Group without org"})


class TestUserGroupsUpdate:
    """Tests for UserGroups.update() behavior."""

    def test_update_returns_updated_user_group(self, httpx_mock: HTTPXMock):
        """Update should use plural path and return the updated user group."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/v2/userGroups/123",
            method="PATCH",
            json={
                "id": 123,
                "organizationId": 10,
                "name": "Updated Group Name",
                "description": "Updated description",
            },
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )
        result = client.v2.user_groups.update(
            id=123, data={"name": "Updated Group Name", "description": "Updated description"}
        )

        assert result["id"] == 123
        assert result["name"] == "Updated Group Name"

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

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

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


class TestUserGroupsDelete:
    """Tests for UserGroups.delete() behavior."""

    def test_delete_returns_success(self, httpx_mock: HTTPXMock):
        """Delete should use plural path and complete successfully."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/v2/userGroups/123",
            method="DELETE",
            status_code=204,
        )

        client = ConcentriqClient(
            base_url="https://test.concentriq.com", auth=ApiKeyAuth("test-key")
        )
        result = client.v2.user_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 group."""
        httpx_mock.add_response(
            url="https://test.concentriq.com/api/v2/userGroups/999999",
            method="DELETE",
            status_code=404,
            json={"error": "User group not found"},
        )

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

        with pytest.raises(NotFoundError):
            client.v2.user_groups.delete(id=999999)
