"""Tests for rules 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 RuleFactory


@pytest.mark.django_db
class TestRulesQuery:
    """Tests for rules query."""

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

        RuleFactory.create_batch(3, workspace=workspace)

        client = GraphQLTestClient(user=user)
        result = client.execute(
            """
            query Rules($workspaceId: ID!) {
                rules(workspaceId: $workspaceId) {
                    id
                    name
                    action
                    isEnabled
                }
            }
            """,
            variables={"workspaceId": str(workspace.id)},
        )

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

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

        RuleFactory(workspace=workspace, is_enabled=True)
        RuleFactory(workspace=workspace, is_enabled=True)
        RuleFactory(workspace=workspace, is_enabled=False)

        client = GraphQLTestClient(user=user)
        result = client.execute(
            """
            query Rules($workspaceId: ID!, $isEnabled: Boolean) {
                rules(workspaceId: $workspaceId, isEnabled: $isEnabled) {
                    id
                    isEnabled
                }
            }
            """,
            variables={"workspaceId": str(workspace.id), "isEnabled": True},
        )

        assert result.errors is None
        assert len(result.data["rules"]) == 2
        assert all(r["isEnabled"] for r in result.data["rules"])

    def test_rules_returns_empty_for_unauthenticated(self):
        """Test that rules query returns empty for unauthenticated users."""
        workspace = WorkspaceFactory()
        RuleFactory.create_batch(3, workspace=workspace)

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

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


@pytest.mark.django_db
class TestRuleQuery:
    """Tests for rule query."""

    def test_rule_returns_single_rule(self):
        """Test that rule query returns a specific rule."""
        user = UserFactory()
        workspace = WorkspaceFactory()
        WorkspaceMembershipFactory(user=user, workspace=workspace)
        rule = RuleFactory(workspace=workspace, name="Auto-tag", action="add_tag")

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

        assert result.errors is None
        assert result.data["rule"]["name"] == "Auto-tag"
        assert result.data["rule"]["action"] == "add_tag"


@pytest.mark.django_db
class TestCreateRuleMutation:
    """Tests for createRule mutation."""

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

        client = GraphQLTestClient(user=user)
        result = client.execute(
            """
            mutation CreateRule($input: CreateRuleInput!) {
                createRule(input: $input) {
                    id
                    name
                    action
                    isEnabled
                    priority
                }
            }
            """,
            variables={
                "input": {
                    "workspaceId": str(workspace.id),
                    "name": "New Rule",
                    "action": "add_tag",
                    "priority": 10,
                }
            },
        )

        assert result.errors is None
        assert result.data["createRule"]["name"] == "New Rule"
        assert result.data["createRule"]["action"] == "add_tag"
        assert result.data["createRule"]["priority"] == 10
        assert result.data["createRule"]["isEnabled"] is True

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

        client = GraphQLTestClient(user=user)
        result = client.execute(
            """
            mutation CreateRule($input: CreateRuleInput!) {
                createRule(input: $input) {
                    id
                }
            }
            """,
            variables={
                "input": {
                    "workspaceId": str(workspace.id),
                    "name": "New Rule",
                    "action": "add_tag",
                }
            },
        )

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


@pytest.mark.django_db
class TestUpdateRuleMutation:
    """Tests for updateRule mutation."""

    def test_update_rule_success(self):
        """Test updating a rule successfully."""
        user = UserFactory()
        workspace = WorkspaceFactory()
        WorkspaceMembershipFactory(user=user, workspace=workspace, role="admin")
        rule = RuleFactory(workspace=workspace, name="Old Name", is_enabled=True)

        client = GraphQLTestClient(user=user)
        result = client.execute(
            """
            mutation UpdateRule($id: ID!, $input: UpdateRuleInput!) {
                updateRule(id: $id, input: $input) {
                    id
                    name
                    isEnabled
                }
            }
            """,
            variables={
                "id": str(rule.id),
                "input": {"name": "New Name", "isEnabled": False},
            },
        )

        assert result.errors is None
        assert result.data["updateRule"]["name"] == "New Name"
        assert result.data["updateRule"]["isEnabled"] is False


@pytest.mark.django_db
class TestDeleteRuleMutation:
    """Tests for deleteRule mutation."""

    def test_delete_rule_success(self):
        """Test deleting a rule successfully."""
        user = UserFactory()
        workspace = WorkspaceFactory()
        WorkspaceMembershipFactory(user=user, workspace=workspace, role="admin")
        rule = RuleFactory(workspace=workspace)

        client = GraphQLTestClient(user=user)
        result = client.execute(
            """
            mutation DeleteRule($id: ID!) {
                deleteRule(id: $id)
            }
            """,
            variables={"id": str(rule.id)},
        )

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

    def test_delete_rule_requires_admin(self):
        """Test that deleting rule requires admin access."""
        user = UserFactory()
        workspace = WorkspaceFactory()
        WorkspaceMembershipFactory(user=user, workspace=workspace, role="member")
        rule = RuleFactory(workspace=workspace)

        client = GraphQLTestClient(user=user)
        result = client.execute(
            """
            mutation DeleteRule($id: ID!) {
                deleteRule(id: $id)
            }
            """,
            variables={"id": str(rule.id)},
        )

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