# Copyright (c) 2025 Airbyte, Inc., all rights reserved.
"""Tests for Slack thread posting utilities and feedback follow-up tool.

Tests cover:
- URL parsing (valid permalinks, wrong workspace, malformed URLs)
- Follow-up message wrapping (header + footer disclaimer)
- Feedback follow-up tool error handling
"""

from __future__ import annotations

from unittest.mock import MagicMock, patch

import pytest

from airbyte_ops_mcp.slack_api import SlackURLParseError
from airbyte_ops_mcp.slack_posting import parse_slack_thread_url

# ---------------------------------------------------------------------------
# parse_slack_thread_url tests
# ---------------------------------------------------------------------------


@pytest.mark.unit
@pytest.mark.parametrize(
    "url,expected_channel,expected_ts",
    [
        pytest.param(
            "https://airbytehq-team.slack.com/archives/C0ACUHRP6B1/p1773062711122019",
            "C0ACUHRP6B1",
            "1773062711.122019",
            id="basic_permalink",
        ),
        pytest.param(
            "https://airbytehq-team.slack.com/archives/C0AEN317Z7T/p1774646306048449",
            "C0AEN317Z7T",
            "1774646306.048449",
            id="test_channel_permalink",
        ),
        pytest.param(
            "https://airbytehq-team.slack.com/archives/C0ACUHRP6B1/p1773062711122019"
            "?thread_ts=1773062700.000001&cid=C0ACUHRP6B1",
            "C0ACUHRP6B1",
            "1773062711.122019",
            id="permalink_with_query_params",
        ),
        pytest.param(
            "https://airbytehq-team.slack.com/archives/C0ACUHRP6B1/p1773062711",
            "C0ACUHRP6B1",
            "1773062711",
            id="short_timestamp_10_digits",
        ),
    ],
)
def test_parse_slack_thread_url_valid(
    url: str, expected_channel: str, expected_ts: str
) -> None:
    channel_id, thread_ts = parse_slack_thread_url(url)
    assert channel_id == expected_channel
    assert thread_ts == expected_ts


@pytest.mark.unit
@pytest.mark.parametrize(
    "url,expected_error",
    [
        pytest.param(
            "https://example.com/not-a-slack-url",
            "Invalid Slack thread URL",
            id="not_slack_url",
        ),
        pytest.param(
            "https://other-workspace.slack.com/archives/C0ACUHRP6B1/p1773062711122019",
            "Unexpected Slack workspace",
            id="wrong_workspace",
        ),
        pytest.param(
            "not-even-a-url",
            "Invalid Slack thread URL",
            id="garbage_input",
        ),
        pytest.param(
            "https://airbytehq-team.slack.com/archives/C0ACUHRP6B1",
            "Invalid Slack thread URL",
            id="missing_timestamp",
        ),
    ],
)
def test_parse_slack_thread_url_invalid(url: str, expected_error: str) -> None:
    with pytest.raises(SlackURLParseError, match=expected_error):
        parse_slack_thread_url(url)


# ---------------------------------------------------------------------------
# _wrap_followup_message tests
# ---------------------------------------------------------------------------


@pytest.mark.unit
def test_wrap_followup_message_structure() -> None:
    """Wrapped message has header, body, and non-interactive footer."""
    from airbyte_ops_mcp.mcp.session_feedback import (
        _FOLLOWUP_HEADER,
        _wrap_followup_message,
    )

    body = "Here are my triage findings."
    session_url = "https://app.devin.ai/sessions/test123"
    result = _wrap_followup_message(body, agent_session_url=session_url)

    assert result.startswith(_FOLLOWUP_HEADER)
    assert body in result
    # Verify structure: header \n\n body \n\n footer (with hyperlinked session)
    assert f"<{session_url}|linked session>" in result
    assert "not monitored by Devin" in result
    assert result.endswith("or create a new task._")


# ---------------------------------------------------------------------------
# devin_session_feedback_followup tool tests
# ---------------------------------------------------------------------------


@pytest.mark.unit
def test_followup_tool_invalid_url() -> None:
    """Follow-up tool returns success=False for invalid thread URLs."""
    from airbyte_ops_mcp.mcp.session_feedback import (
        devin_session_feedback_followup,
    )

    result = devin_session_feedback_followup(
        thread_url="https://example.com/not-slack",
        message="Triage report",
        agent_session_url="https://app.devin.ai/sessions/test123",
    )
    assert result.success is False
    assert "Invalid Slack thread URL" in result.message


@pytest.mark.unit
def test_followup_tool_wrong_workspace() -> None:
    """Follow-up tool returns success=False for wrong workspace."""
    from airbyte_ops_mcp.mcp.session_feedback import (
        devin_session_feedback_followup,
    )

    result = devin_session_feedback_followup(
        thread_url="https://evil-workspace.slack.com/archives/C0ACUHRP6B1/p1773062711122019",
        message="Triage report",
        agent_session_url="https://app.devin.ai/sessions/test123",
    )
    assert result.success is False
    assert "Unexpected Slack workspace" in result.message


@pytest.mark.unit
@patch("airbyte_ops_mcp.mcp.session_feedback.post_thread_reply")
def test_followup_tool_success(mock_post: MagicMock) -> None:
    """Follow-up tool returns success=True when post succeeds."""
    from airbyte_ops_mcp.mcp.session_feedback import (
        devin_session_feedback_followup,
    )

    mock_post.return_value = "1774646400.000100"

    result = devin_session_feedback_followup(
        thread_url="https://airbytehq-team.slack.com/archives/C0ACUHRP6B1/p1773062711122019",
        message="Triage report",
        agent_session_url="https://app.devin.ai/sessions/test123",
    )
    assert result.success is True
    assert result.reply_ts == "1774646400.000100"
    assert "C0ACUHRP6B1" in result.message

    # Verify the message was wrapped with disclaimer
    call_kwargs = mock_post.call_args.kwargs
    assert "Automated Triage Update" in call_kwargs["message"]
    assert "not monitored by Devin" in call_kwargs["message"]
