"""Tests for webhook integration."""

from __future__ import annotations

from unittest.mock import MagicMock, patch

import pytest


# ── Payload formatting ─────────────────────────────────────────────────────


class TestFormatPayload:
    """Test webhook payload formatting."""

    def test_slack_format(self):
        from alive.integrations.webhook import _format_payload

        payload = _format_payload("slack", "Hello Slack")
        assert payload == {"text": "Hello Slack"}

    def test_slack_format_with_data(self):
        from alive.integrations.webhook import _format_payload

        payload = _format_payload("slack", "Hello", {"channel": "#general"})
        assert payload["text"] == "Hello"
        assert payload["channel"] == "#general"

    def test_discord_format(self):
        from alive.integrations.webhook import _format_payload

        payload = _format_payload("discord", "Hello Discord")
        assert payload == {"content": "Hello Discord"}

    def test_discord_format_with_data(self):
        from alive.integrations.webhook import _format_payload

        payload = _format_payload("discord", "Hello", {"embed": {}})
        assert payload["content"] == "Hello"
        assert "embed" in payload

    def test_generic_format(self):
        from alive.integrations.webhook import _format_payload

        payload = _format_payload("generic", "Hello Generic", {"key": "val"})
        assert payload["message"] == "Hello Generic"
        assert payload["data"] == {"key": "val"}
        assert payload["source"] == "alive-agent"
        assert "timestamp" in payload

    def test_unknown_type_uses_generic(self):
        from alive.integrations.webhook import _format_payload

        payload = _format_payload("unknown", "Hello")
        assert payload["message"] == "Hello"
        assert payload["source"] == "alive-agent"


# ── send_webhook ───────────────────────────────────────────────────────────


class TestSendWebhook:
    """Test the send_webhook function."""

    @patch("alive.integrations.webhook._get_webhooks", return_value={})
    def test_raises_when_no_webhooks(self, mock_wh):
        from alive.integrations.webhook import send_webhook

        with pytest.raises(ValueError, match="No webhooks configured"):
            send_webhook("Hello")

    @patch("alive.integrations.webhook._get_webhooks", return_value={"slack": {"url": "https://hooks.slack.com/test", "type": "slack"}})
    def test_sends_to_default_webhook(self, mock_wh):
        from alive.integrations.webhook import send_webhook

        mock_resp = MagicMock()
        mock_resp.status_code = 200

        with patch("httpx.post", return_value=mock_resp) as mock_post:
            result = send_webhook("Test message")

        assert result is True
        mock_post.assert_called_once()
        args, kwargs = mock_post.call_args
        assert args[0] == "https://hooks.slack.com/test"
        assert kwargs["json"]["text"] == "Test message"

    @patch("alive.integrations.webhook._get_webhooks", return_value={
        "slack": {"url": "https://hooks.slack.com/test", "type": "slack"},
        "discord": {"url": "https://discord.com/api/webhooks/test", "type": "discord"},
    })
    def test_sends_to_named_webhook(self, mock_wh):
        from alive.integrations.webhook import send_webhook

        mock_resp = MagicMock()
        mock_resp.status_code = 200

        with patch("httpx.post", return_value=mock_resp) as mock_post:
            result = send_webhook("Test", webhook_name="discord")

        assert result is True
        args, kwargs = mock_post.call_args
        assert "discord.com" in args[0]
        assert kwargs["json"]["content"] == "Test"

    @patch("alive.integrations.webhook._get_webhooks", return_value={"slack": {"url": "https://hooks.slack.com/test", "type": "slack"}})
    def test_raises_for_unknown_webhook_name(self, mock_wh):
        from alive.integrations.webhook import send_webhook

        with pytest.raises(ValueError, match="not found"):
            send_webhook("Test", webhook_name="nonexistent")

    @patch("alive.integrations.webhook._get_webhooks", return_value={"slack": {"url": "https://hooks.slack.com/test", "type": "slack"}})
    def test_returns_false_on_server_error(self, mock_wh):
        from alive.integrations.webhook import send_webhook

        mock_resp = MagicMock()
        mock_resp.status_code = 500

        with patch("httpx.post", return_value=mock_resp):
            result = send_webhook("Test")

        assert result is False

    @patch("alive.integrations.webhook._get_webhooks", return_value={"slack": {"url": "https://hooks.slack.com/test", "type": "slack"}})
    def test_includes_extra_data(self, mock_wh):
        from alive.integrations.webhook import send_webhook

        mock_resp = MagicMock()
        mock_resp.status_code = 200

        with patch("httpx.post", return_value=mock_resp) as mock_post:
            send_webhook("Test", data={"extra": "info"})

        payload = mock_post.call_args[1]["json"]
        assert payload["text"] == "Test"
        assert payload["extra"] == "info"


# ── list_webhooks ──────────────────────────────────────────────────────────


class TestListWebhooks:
    """Test list_webhooks function."""

    @patch("alive.integrations.webhook._get_webhooks", return_value={})
    def test_empty_list(self, mock_wh):
        from alive.integrations.webhook import list_webhooks

        assert list_webhooks() == []

    @patch("alive.integrations.webhook._get_webhooks", return_value={
        "slack": {"url": "https://hooks.slack.com/services/xxx/yyy/zzz", "type": "slack"},
    })
    def test_masks_url(self, mock_wh):
        from alive.integrations.webhook import list_webhooks

        result = list_webhooks()
        assert len(result) == 1
        assert result[0]["name"] == "slack"
        assert result[0]["type"] == "slack"
        assert result[0]["url"].endswith("...")

    @patch("alive.integrations.webhook._get_webhooks", return_value={
        "a": {"url": "https://a.com", "type": "slack"},
        "b": {"url": "https://b.com", "type": "discord"},
    })
    def test_multiple_webhooks(self, mock_wh):
        from alive.integrations.webhook import list_webhooks

        result = list_webhooks()
        assert len(result) == 2


# ── Display ────────────────────────────────────────────────────────────────


class TestDisplayWebhooks:
    """Test webhook display."""

    @patch("alive.integrations.webhook.list_webhooks", return_value=[])
    def test_display_empty(self, mock_list):
        from rich.console import Console

        from alive.integrations.webhook import display_webhooks

        con = Console(file=MagicMock(), force_terminal=True)
        display_webhooks(console=con)  # Should not raise

    @patch("alive.integrations.webhook.list_webhooks", return_value=[
        {"name": "slack", "type": "slack", "url": "https://hooks..."},
    ])
    def test_display_with_webhooks(self, mock_list):
        from rich.console import Console

        from alive.integrations.webhook import display_webhooks

        con = Console(file=MagicMock(), force_terminal=True)
        display_webhooks(console=con)  # Should not raise


# ── test_webhook ───────────────────────────────────────────────────────────


class TestTestWebhook:
    """Test the test_webhook function."""

    @patch("alive.integrations.webhook.send_webhook", return_value=True)
    def test_success(self, mock_send):
        from alive.integrations.webhook import test_webhook

        result = test_webhook(console=MagicMock())
        assert result is True

    @patch("alive.integrations.webhook.send_webhook", side_effect=ValueError("Not configured"))
    def test_not_configured(self, mock_send):
        from alive.integrations.webhook import test_webhook

        result = test_webhook(console=MagicMock())
        assert result is False
