"""Tests for trigger event resolver."""

from unittest.mock import MagicMock

import pytest

from preloop.services.prompt_resolvers.base import ResolverContext
from preloop.services.prompt_resolvers.trigger_event import TriggerEventResolver


class TestTriggerEventResolver:
    """Test TriggerEventResolver class."""

    def test_prefix(self):
        """Test that prefix returns correct value."""
        resolver = TriggerEventResolver()
        assert resolver.prefix == "trigger_event"

    @pytest.mark.asyncio
    async def test_resolve_simple_field(self):
        """Test resolving a simple field from trigger event."""
        resolver = TriggerEventResolver()

        mock_db = MagicMock()
        context = ResolverContext(
            db=mock_db,
            trigger_event_data={"source": "github", "action": "created"},
            flow_id="flow-1",
            execution_id="exec-1",
        )

        result = await resolver.resolve("source", context)
        assert result == "github"

        result = await resolver.resolve("action", context)
        assert result == "created"

    @pytest.mark.asyncio
    async def test_resolve_nested_field(self):
        """Test resolving a nested field from trigger event."""
        resolver = TriggerEventResolver()

        mock_db = MagicMock()
        context = ResolverContext(
            db=mock_db,
            trigger_event_data={
                "payload": {
                    "issue": {"title": "Test Issue", "number": 123},
                    "commit": {"sha": "abc123"},
                }
            },
            flow_id="flow-1",
            execution_id="exec-1",
        )

        result = await resolver.resolve("payload.issue.title", context)
        assert result == "Test Issue"

        result = await resolver.resolve("payload.commit.sha", context)
        assert result == "abc123"

    @pytest.mark.asyncio
    async def test_resolve_no_trigger_event_data(self):
        """Test resolving when no trigger event data is available."""
        resolver = TriggerEventResolver()

        mock_db = MagicMock()
        context = ResolverContext(
            db=mock_db,
            trigger_event_data=None,
            flow_id="flow-1",
            execution_id="exec-1",
        )

        result = await resolver.resolve("source", context)
        assert result is None

    @pytest.mark.asyncio
    async def test_resolve_nonexistent_field(self):
        """Test resolving a field that doesn't exist."""
        resolver = TriggerEventResolver()

        mock_db = MagicMock()
        context = ResolverContext(
            db=mock_db,
            trigger_event_data={"source": "github"},
            flow_id="flow-1",
            execution_id="exec-1",
        )

        result = await resolver.resolve("nonexistent.field", context)
        assert result is None

    @pytest.mark.asyncio
    async def test_resolve_empty_trigger_event_data(self):
        """Test resolving when trigger event data is empty."""
        resolver = TriggerEventResolver()

        mock_db = MagicMock()
        context = ResolverContext(
            db=mock_db,
            trigger_event_data={},
            flow_id="flow-1",
            execution_id="exec-1",
        )

        result = await resolver.resolve("source", context)
        assert result is None

    @pytest.mark.asyncio
    async def test_resolve_entire_event(self):
        """Test resolving the entire trigger event as JSON when no path is provided.

        Note: The resolver normalizes GitHub events by adding object_attributes
        for cross-platform compatibility with GitLab.
        """
        import json

        resolver = TriggerEventResolver()

        mock_db = MagicMock()
        trigger_data = {
            "source": "github",
            "action": "opened",
            "payload": {
                "issue": {"title": "Test Issue", "number": 123},
                "repository": {"name": "test-repo"},
            },
        }
        context = ResolverContext(
            db=mock_db,
            trigger_event_data=trigger_data,
            flow_id="flow-1",
            execution_id="exec-1",
        )

        # Test with empty string path
        result = await resolver.resolve("", context)
        assert result is not None
        parsed = json.loads(result)

        # The resolver normalizes GitHub events by adding object_attributes
        assert parsed["source"] == "github"
        assert parsed["action"] == "opened"
        assert parsed["payload"]["issue"] == {"title": "Test Issue", "number": 123}
        assert parsed["payload"]["repository"] == {"name": "test-repo"}
        # Normalized object_attributes should be present for GitHub issue events
        assert "object_attributes" in parsed["payload"]
        assert parsed["payload"]["object_attributes"]["title"] == "Test Issue"
        assert parsed["payload"]["object_attributes"]["number"] == 123

        # Test with whitespace-only path
        result = await resolver.resolve("  ", context)
        assert result is not None
        parsed = json.loads(result)
        assert parsed["source"] == "github"
        assert "object_attributes" in parsed["payload"]

    @pytest.mark.asyncio
    async def test_resolve_entire_event_complex_structure(self):
        """Test resolving entire event with complex nested structure."""
        import json

        resolver = TriggerEventResolver()

        mock_db = MagicMock()
        trigger_data = {
            "tracker_type": "gitlab",
            "event_type": "merge_request",
            "timestamp": "2025-11-05T12:00:00Z",
            "payload": {
                "object_attributes": {
                    "id": 999,
                    "title": "Add new feature",
                    "state": "opened",
                    "source_branch": "feature/new",
                    "target_branch": "main",
                },
                "user": {"name": "John Doe", "email": "john@example.com"},
                "labels": [
                    {"name": "enhancement", "color": "#00FF00"},
                    {"name": "priority:high", "color": "#FF0000"},
                ],
            },
        }
        context = ResolverContext(
            db=mock_db,
            trigger_event_data=trigger_data,
            flow_id="flow-1",
            execution_id="exec-1",
        )

        result = await resolver.resolve("", context)
        assert result is not None
        parsed = json.loads(result)
        assert parsed == trigger_data
        # Verify nested structures are preserved
        assert parsed["payload"]["object_attributes"]["title"] == "Add new feature"
        assert len(parsed["payload"]["labels"]) == 2
