import os
import sys
import tempfile

_fd, _TMP = tempfile.mkstemp(suffix=".db")
os.close(_fd)
os.unlink(_TMP)
os.environ["AGENT_OFFICE_DB_PATH"] = _TMP

sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

import pytest
from unittest.mock import AsyncMock, patch


@pytest.fixture(autouse=True)
def _init_db(monkeypatch):
    import gc
    gc.collect()
    # config.DB_PATH는 첫 import 시 1회 고정되므로, 다른 테스트 파일과 조합 실행 시
    # db가 이 파일의 _TMP가 아닌 다른 경로를 쓸 수 있다. db.DB_PATH를 이 파일 전용으로
    # 강제해 영속 테이블의 테스트 간 누수를 결정적으로 차단.
    import app.db as _db
    monkeypatch.setattr(_db, "DB_PATH", _TMP)
    for suffix in ("", "-wal", "-shm"):
        p = _TMP + suffix
        if os.path.exists(p):
            os.remove(p)
    _db.init_db()
    yield
    gc.collect()


@pytest.mark.asyncio
async def test_watch_command_calls_add():
    from app.telegram import webhook
    msg = {"chat": {"id": 1}, "text": "/watch 005930"}
    with patch("app.telegram.webhook.service_proxy.watchlist_add",
               new=AsyncMock(return_value={"ok": True})) as m, \
         patch("app.telegram.webhook.api_call", new=AsyncMock(return_value={"ok": True})):
        handled = await webhook.handle_watch_command(msg)
    assert handled is True
    m.assert_awaited_once_with("005930")


@pytest.mark.asyncio
async def test_non_watch_text_ignored():
    from app.telegram import webhook
    msg = {"chat": {"id": 1}, "text": "안녕"}
    assert await webhook.handle_watch_command(msg) is False


@pytest.mark.asyncio
async def test_unwatch_command_calls_remove():
    from app.telegram import webhook
    msg = {"chat": {"id": 1}, "text": "/unwatch 005930"}
    with patch("app.telegram.webhook.service_proxy.watchlist_remove",
               new=AsyncMock(return_value={"ok": True})) as m, \
         patch("app.telegram.webhook.api_call", new=AsyncMock(return_value={"ok": True})) as sent:
        handled = await webhook.handle_watch_command(msg)
    assert handled is True
    m.assert_awaited_once_with("005930")
    sent.assert_awaited_once()


@pytest.mark.asyncio
async def test_watchlist_command_calls_list_and_formats_items():
    from app.telegram import webhook
    msg = {"chat": {"id": 1}, "text": "/watchlist"}
    items = {"watchlist": [{"ticker": "005930", "name": "삼성전자"}]}
    with patch("app.telegram.webhook.service_proxy.watchlist_list",
               new=AsyncMock(return_value=items)) as m, \
         patch("app.telegram.webhook.api_call", new=AsyncMock(return_value={"ok": True})) as sent:
        handled = await webhook.handle_watch_command(msg)
    assert handled is True
    m.assert_awaited_once_with()
    text = sent.await_args.args[1]["text"]
    assert "005930" in text and "삼성전자" in text


@pytest.mark.asyncio
async def test_watch_command_reaches_handle_webhook_before_slash_dispatch():
    """handle_webhook이 /watch 를 agent_dispatcher 호출 전에 가로채야 한다."""
    from app.telegram import webhook
    data = {"message": {"chat": {"id": 1}, "text": "/watch 005930"}}
    dispatcher = AsyncMock(side_effect=AssertionError("agent_dispatcher가 호출되면 안 됨"))
    with patch("app.telegram.webhook.service_proxy.watchlist_add",
               new=AsyncMock(return_value={"ok": True})) as m, \
         patch("app.telegram.webhook.api_call", new=AsyncMock(return_value={"ok": True})):
        result = await webhook.handle_webhook(data, agent_dispatcher=dispatcher)
    assert result is None
    m.assert_awaited_once_with("005930")
    dispatcher.assert_not_awaited()
