from unittest.mock import AsyncMock, patch

import pytest
from fastapi.testclient import TestClient

from app.main import app

client = TestClient(app)


@pytest.fixture
def mock_postgres():
    with patch("app.modules.zalo_crm.presentation.router.PostgresClient") as mock:
        instance = mock.return_value
        instance.upsert_contact.return_value = {"id": "test"}
        instance.upsert_zalo_account.return_value = {"id": "test"}
        instance.upsert_conversation.return_value = {"id": "test"}
        instance.insert_message.return_value = {"id": "test"}
        yield instance


@pytest.fixture
def mock_telegram_bridge():
    with patch("app.modules.zalo_crm.presentation.router.TelegramBridge") as mock:
        instance = mock.return_value
        instance.create_topic = AsyncMock(return_value="123")
        instance.forward_inbound_message = AsyncMock()
        instance.process_webhook = AsyncMock()
        instance.forward_inbound_message = AsyncMock()
        instance.process_webhook = AsyncMock()
        yield instance


def test_webhook_external_contact(mock_postgres, mock_telegram_bridge):
    payload = {
        "event_name": "message",
        "sender_id": "ext_123",
        "sender_name": "Nguyễn Văn A - Đối tác",
        "message": "Xin chào",
        "timestamp": 1690000000000,
    }
    response = client.post("/crm/webhook", json=payload)
    assert response.status_code == 200
    data = response.json()
    assert data["status"] == "success"

    # Check DB calls
    mock_postgres.upsert_contact.assert_called_once()
    contact_data = mock_postgres.upsert_contact.call_args[0][0]
    assert contact_data["is_internal"] is False

    # create_topic should be called as background task
    mock_telegram_bridge.create_topic.assert_called_once()


def test_webhook_internal_contact(mock_postgres, mock_telegram_bridge):
    payload = {
        "event_name": "message",
        "sender_id": "int_456",
        "sender_name": "Son - Giám Đốc",
        "message": "Kiểm tra hệ thống",
        "timestamp": 1690000000000,
    }
    response = client.post("/crm/webhook", json=payload)
    assert response.status_code == 200

    # Check DB calls
    mock_postgres.upsert_contact.assert_called_once()
    contact_data = mock_postgres.upsert_contact.call_args[0][0]
    assert contact_data["is_internal"] is True

    # create_topic should NOT be called for internal
    mock_telegram_bridge.create_topic.assert_not_called()


def test_telegram_webhook(mock_telegram_bridge):
    payload = {
        "update_id": 12345,
        "callback_query": {
            "id": "cb_1",
            "data": "approve_ext_123",
            "message": {"text": "AI DRAFT:\nXin chào, tôi có thể giúp gì?"},
        },
    }
    response = client.post("/crm/telegram_webhook", json=payload)
    assert response.status_code == 200
    assert response.json() == {"status": "ok"}
    mock_telegram_bridge.process_webhook.assert_called_once_with(payload)
