"""Tests for Telegram Forum Topic management."""

import json
from unittest.mock import AsyncMock, MagicMock, patch

import pytest

from fliiq.runtime.telegram.topics import (
    TOPICS_FILE,
    _load_topic_map,
    _save_topic_map,
    get_topic_thread_id,
    resolve_or_create_topic,
)


@pytest.fixture(autouse=True)
def _isolate_topics_file(tmp_path, monkeypatch):
    """Redirect TOPICS_FILE to tmp_path so tests don't touch real config."""
    test_file = tmp_path / "telegram_topics.json"
    monkeypatch.setattr("fliiq.runtime.telegram.topics.TOPICS_FILE", test_file)
    return test_file


def test_load_topic_map_empty(tmp_path):
    """Returns empty dict when file doesn't exist."""
    assert _load_topic_map() == {}


def test_save_and_load_roundtrip(tmp_path):
    """Save then load returns the same data."""
    data = {"123:Tennis Coach": 42, "123:GTM Strategy": 99}
    _save_topic_map(data)
    assert _load_topic_map() == data


def test_get_topic_thread_id_cached():
    """Returns cached thread_id when present."""
    _save_topic_map({"123:Tennis Coach": 42})
    assert get_topic_thread_id("123", "Tennis Coach") == 42


def test_get_topic_thread_id_missing():
    """Returns None when topic not in cache."""
    _save_topic_map({"123:Tennis Coach": 42})
    assert get_topic_thread_id("123", "GTM Strategy") is None


async def test_resolve_or_create_topic_returns_cached():
    """Skips API call when topic is already cached."""
    _save_topic_map({"123:Tennis Coach": 42})

    result = await resolve_or_create_topic("123", "Tennis Coach", bot_token="fake")
    assert result == 42


async def test_resolve_or_create_topic_creates_new():
    """Calls createForumTopic API and caches result."""
    mock_response = MagicMock()
    mock_response.status_code = 200
    mock_response.json.return_value = {
        "ok": True,
        "result": {"message_thread_id": 77, "name": "Tennis Coach"},
    }

    with patch("httpx.AsyncClient") as mock_client_cls:
        mock_client = AsyncMock()
        mock_client.post.return_value = mock_response
        mock_client_cls.return_value.__aenter__ = AsyncMock(return_value=mock_client)
        mock_client_cls.return_value.__aexit__ = AsyncMock(return_value=False)

        result = await resolve_or_create_topic("123", "Tennis Coach", bot_token="fake-token")

    assert result == 77
    # Verify cached
    assert get_topic_thread_id("123", "Tennis Coach") == 77
    # Verify API call
    call_args = mock_client.post.call_args
    assert "createForumTopic" in call_args[0][0]
    assert call_args[1]["json"]["name"] == "Tennis Coach"


async def test_resolve_or_create_topic_api_failure():
    """Returns None on API failure and doesn't cache."""
    mock_response = MagicMock()
    mock_response.status_code = 400
    mock_response.json.return_value = {"description": "Bad Request: not enough rights"}
    mock_response.text = "Bad Request: not enough rights"

    with patch("httpx.AsyncClient") as mock_client_cls:
        mock_client = AsyncMock()
        mock_client.post.return_value = mock_response
        mock_client_cls.return_value.__aenter__ = AsyncMock(return_value=mock_client)
        mock_client_cls.return_value.__aexit__ = AsyncMock(return_value=False)

        result = await resolve_or_create_topic("123", "Tennis Coach", bot_token="fake-token")

    assert result is None
    assert get_topic_thread_id("123", "Tennis Coach") is None


async def test_resolve_or_create_topic_no_token(monkeypatch):
    """Returns None when no bot token available."""
    monkeypatch.delenv("TELEGRAM_BOT_TOKEN", raising=False)

    result = await resolve_or_create_topic("123", "Tennis Coach")
    assert result is None


async def test_resolve_or_create_topic_network_error():
    """Returns None on network error."""
    with patch("httpx.AsyncClient") as mock_client_cls:
        mock_client = AsyncMock()
        mock_client.post.side_effect = Exception("Connection refused")
        mock_client_cls.return_value.__aenter__ = AsyncMock(return_value=mock_client)
        mock_client_cls.return_value.__aexit__ = AsyncMock(return_value=False)

        result = await resolve_or_create_topic("123", "Tennis Coach", bot_token="fake-token")

    assert result is None
