"""Tests for sources app GraphQL queries and mutations."""

import pytest
from tests.backend.graphql.conftest import GraphQLTestClient

from accounts.tests.factories import UserFactory, WorkspaceFactory, WorkspaceMembershipFactory

from .factories import SourceFactory


@pytest.mark.django_db
class TestSourcesQuery:
    """Tests for sources query."""

    def test_sources_returns_workspace_sources(self):
        """Test that sources query returns all sources in a workspace."""
        user = UserFactory()
        workspace = WorkspaceFactory()
        WorkspaceMembershipFactory(user=user, workspace=workspace)

        SourceFactory.create_batch(3, workspace=workspace)

        client = GraphQLTestClient(user=user)
        result = client.execute(
            """
            query Sources($workspaceId: ID!) {
                sources(workspaceId: $workspaceId) {
                    id
                    name
                    kind
                    externalId
                }
            }
            """,
            variables={"workspaceId": str(workspace.id)},
        )

        assert result.errors is None
        assert len(result.data["sources"]) == 3

    def test_sources_returns_empty_for_unauthenticated(self):
        """Test that sources query returns empty for unauthenticated users."""
        workspace = WorkspaceFactory()
        SourceFactory.create_batch(3, workspace=workspace)

        client = GraphQLTestClient()
        result = client.execute(
            """
            query Sources($workspaceId: ID!) {
                sources(workspaceId: $workspaceId) {
                    id
                }
            }
            """,
            variables={"workspaceId": str(workspace.id)},
        )

        assert result.errors is None
        assert result.data["sources"] == []

    def test_sources_returns_empty_for_non_member(self):
        """Test that sources query returns empty for non-members."""
        user = UserFactory()
        workspace = WorkspaceFactory()
        SourceFactory.create_batch(3, workspace=workspace)

        client = GraphQLTestClient(user=user)
        result = client.execute(
            """
            query Sources($workspaceId: ID!) {
                sources(workspaceId: $workspaceId) {
                    id
                }
            }
            """,
            variables={"workspaceId": str(workspace.id)},
        )

        assert result.errors is None
        assert result.data["sources"] == []


@pytest.mark.django_db
class TestSourceQuery:
    """Tests for source query."""

    def test_source_returns_single_source(self):
        """Test that source query returns a specific source."""
        user = UserFactory()
        workspace = WorkspaceFactory()
        WorkspaceMembershipFactory(user=user, workspace=workspace)
        source = SourceFactory(workspace=workspace, name="My Source", kind="github_repo")

        client = GraphQLTestClient(user=user)
        result = client.execute(
            """
            query Source($id: ID!) {
                source(id: $id) {
                    id
                    name
                    kind
                }
            }
            """,
            variables={"id": str(source.id)},
        )

        assert result.errors is None
        assert result.data["source"]["name"] == "My Source"
        assert result.data["source"]["kind"] == "GITHUB_REPO"

    def test_source_returns_none_for_nonexistent(self):
        """Test that source returns null for nonexistent source."""
        user = UserFactory()

        client = GraphQLTestClient(user=user)
        result = client.execute(
            """
            query Source($id: ID!) {
                source(id: $id) {
                    id
                }
            }
            """,
            variables={"id": "99999"},
        )

        assert result.errors is None
        assert result.data["source"] is None


@pytest.mark.django_db
class TestCreateSourceMutation:
    """Tests for createSource mutation."""

    def test_create_source_success(self):
        """Test creating a source successfully."""
        user = UserFactory()
        workspace = WorkspaceFactory()
        WorkspaceMembershipFactory(user=user, workspace=workspace, role="admin")

        client = GraphQLTestClient(user=user)
        result = client.execute(
            """
            mutation CreateSource($input: CreateSourceInput!) {
                createSource(input: $input) {
                    id
                    name
                    kind
                    externalId
                }
            }
            """,
            variables={
                "input": {
                    "workspaceId": str(workspace.id),
                    "name": "New Source",
                    "kind": "GITHUB_REPO",
                    "externalId": "repo-123",
                }
            },
        )

        assert result.errors is None
        assert result.data["createSource"]["name"] == "New Source"
        assert result.data["createSource"]["kind"] == "GITHUB_REPO"

    def test_create_source_requires_admin(self):
        """Test that creating source requires admin access."""
        user = UserFactory()
        workspace = WorkspaceFactory()
        WorkspaceMembershipFactory(user=user, workspace=workspace, role="member")

        client = GraphQLTestClient(user=user)
        result = client.execute(
            """
            mutation CreateSource($input: CreateSourceInput!) {
                createSource(input: $input) {
                    id
                }
            }
            """,
            variables={
                "input": {
                    "workspaceId": str(workspace.id),
                    "name": "New Source",
                    "kind": "GITHUB_REPO",
                    "externalId": "repo-123",
                }
            },
        )

        assert result.errors is not None
        assert "Permission denied" in str(result.errors)


@pytest.mark.django_db
class TestUpdateSourceMutation:
    """Tests for updateSource mutation."""

    def test_update_source_success(self):
        """Test updating a source successfully."""
        user = UserFactory()
        workspace = WorkspaceFactory()
        WorkspaceMembershipFactory(user=user, workspace=workspace, role="admin")
        source = SourceFactory(workspace=workspace, name="Old Name")

        client = GraphQLTestClient(user=user)
        result = client.execute(
            """
            mutation UpdateSource($id: ID!, $input: UpdateSourceInput!) {
                updateSource(id: $id, input: $input) {
                    id
                    name
                }
            }
            """,
            variables={"id": str(source.id), "input": {"name": "New Name"}},
        )

        assert result.errors is None
        assert result.data["updateSource"]["name"] == "New Name"


@pytest.mark.django_db
class TestDeleteSourceMutation:
    """Tests for deleteSource mutation."""

    def test_delete_source_success(self):
        """Test deleting a source successfully."""
        user = UserFactory()
        workspace = WorkspaceFactory()
        WorkspaceMembershipFactory(user=user, workspace=workspace, role="admin")
        source = SourceFactory(workspace=workspace)

        client = GraphQLTestClient(user=user)
        result = client.execute(
            """
            mutation DeleteSource($id: ID!) {
                deleteSource(id: $id)
            }
            """,
            variables={"id": str(source.id)},
        )

        assert result.errors is None
        assert result.data["deleteSource"] is True
