"""Tests for campaigns 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 CampaignFactory


@pytest.mark.django_db
class TestCampaignsQuery:
    """Tests for campaigns query."""

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

        CampaignFactory.create_batch(3, workspace=workspace)

        client = GraphQLTestClient(user=user)
        result = client.execute(
            """
            query Campaigns($workspaceId: ID!) {
                campaigns(workspaceId: $workspaceId) {
                    id
                    name
                    status
                    channel
                }
            }
            """,
            variables={"workspaceId": str(workspace.id)},
        )

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

    def test_campaigns_filters_by_status(self):
        """Test that campaigns can be filtered by status."""
        user = UserFactory()
        workspace = WorkspaceFactory()
        WorkspaceMembershipFactory(user=user, workspace=workspace)

        CampaignFactory(workspace=workspace, status="draft")
        CampaignFactory(workspace=workspace, status="draft")
        CampaignFactory(workspace=workspace, status="sent")

        client = GraphQLTestClient(user=user)
        result = client.execute(
            """
            query Campaigns($workspaceId: ID!, $status: CampaignStatus) {
                campaigns(workspaceId: $workspaceId, status: $status) {
                    id
                    status
                }
            }
            """,
            variables={"workspaceId": str(workspace.id), "status": "DRAFT"},
        )

        assert result.errors is None
        assert len(result.data["campaigns"]) == 2
        assert all(c["status"] == "DRAFT" for c in result.data["campaigns"])

    def test_campaigns_returns_empty_for_unauthenticated(self):
        """Test that campaigns query returns empty for unauthenticated users."""
        workspace = WorkspaceFactory()
        CampaignFactory.create_batch(3, workspace=workspace)

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

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


@pytest.mark.django_db
class TestCampaignQuery:
    """Tests for campaign query."""

    def test_campaign_returns_single_campaign(self):
        """Test that campaign query returns a specific campaign."""
        user = UserFactory()
        workspace = WorkspaceFactory()
        WorkspaceMembershipFactory(user=user, workspace=workspace)
        campaign = CampaignFactory(workspace=workspace, name="Summer Sale")

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

        assert result.errors is None
        assert result.data["campaign"]["name"] == "Summer Sale"

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

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

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


@pytest.mark.django_db
class TestCreateCampaignMutation:
    """Tests for createCampaign mutation."""

    def test_create_campaign_success(self):
        """Test creating a campaign successfully."""
        user = UserFactory()
        workspace = WorkspaceFactory()
        WorkspaceMembershipFactory(user=user, workspace=workspace, role="member")

        client = GraphQLTestClient(user=user)
        result = client.execute(
            """
            mutation CreateCampaign($input: CreateCampaignInput!) {
                createCampaign(input: $input) {
                    id
                    name
                    status
                    channel
                }
            }
            """,
            variables={
                "input": {
                    "workspaceId": str(workspace.id),
                    "name": "New Campaign",
                }
            },
        )

        assert result.errors is None
        assert result.data["createCampaign"]["name"] == "New Campaign"
        assert result.data["createCampaign"]["status"] == "DRAFT"
        assert result.data["createCampaign"]["channel"] == "ANNOUNCEMENT"

    def test_create_campaign_requires_auth(self):
        """Test that creating a campaign requires authentication."""
        workspace = WorkspaceFactory()

        client = GraphQLTestClient()
        result = client.execute(
            """
            mutation CreateCampaign($input: CreateCampaignInput!) {
                createCampaign(input: $input) {
                    id
                }
            }
            """,
            variables={
                "input": {
                    "workspaceId": str(workspace.id),
                    "name": "New Campaign",
                }
            },
        )

        assert result.errors is not None
        assert "Authentication required" in str(result.errors)


@pytest.mark.django_db
class TestUpdateCampaignMutation:
    """Tests for updateCampaign mutation."""

    def test_update_campaign_success(self):
        """Test updating a campaign successfully."""
        user = UserFactory()
        workspace = WorkspaceFactory()
        WorkspaceMembershipFactory(user=user, workspace=workspace, role="member")
        campaign = CampaignFactory(workspace=workspace, name="Old Name")

        client = GraphQLTestClient(user=user)
        result = client.execute(
            """
            mutation UpdateCampaign($id: ID!, $input: UpdateCampaignInput!) {
                updateCampaign(id: $id, input: $input) {
                    id
                    name
                }
            }
            """,
            variables={"id": str(campaign.id), "input": {"name": "New Name"}},
        )

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

    def test_update_campaign_status(self):
        """Test updating a campaign status."""
        user = UserFactory()
        workspace = WorkspaceFactory()
        WorkspaceMembershipFactory(user=user, workspace=workspace, role="member")
        campaign = CampaignFactory(workspace=workspace, status="draft")

        client = GraphQLTestClient(user=user)
        result = client.execute(
            """
            mutation UpdateCampaign($id: ID!, $input: UpdateCampaignInput!) {
                updateCampaign(id: $id, input: $input) {
                    id
                    status
                }
            }
            """,
            variables={"id": str(campaign.id), "input": {"status": "SCHEDULED"}},
        )

        assert result.errors is None
        assert result.data["updateCampaign"]["status"] == "SCHEDULED"


@pytest.mark.django_db
class TestDeleteCampaignMutation:
    """Tests for deleteCampaign mutation."""

    def test_delete_campaign_success(self):
        """Test deleting a campaign successfully."""
        user = UserFactory()
        workspace = WorkspaceFactory()
        WorkspaceMembershipFactory(user=user, workspace=workspace, role="admin")
        campaign = CampaignFactory(workspace=workspace)

        client = GraphQLTestClient(user=user)
        result = client.execute(
            """
            mutation DeleteCampaign($id: ID!) {
                deleteCampaign(id: $id)
            }
            """,
            variables={"id": str(campaign.id)},
        )

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

    def test_delete_campaign_requires_admin(self):
        """Test that deleting requires admin access."""
        user = UserFactory()
        workspace = WorkspaceFactory()
        WorkspaceMembershipFactory(user=user, workspace=workspace, role="member")
        campaign = CampaignFactory(workspace=workspace)

        client = GraphQLTestClient(user=user)
        result = client.execute(
            """
            mutation DeleteCampaign($id: ID!) {
                deleteCampaign(id: $id)
            }
            """,
            variables={"id": str(campaign.id)},
        )

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