import os
import tempfile
from unittest.mock import patch, MagicMock

import pytest

from app import db as db_module
from app import keyword_extractor


@pytest.fixture
def tmp_db(monkeypatch):
    fd, path = tempfile.mkstemp(suffix=".db")
    os.close(fd)
    monkeypatch.setattr(db_module, "DB_PATH", path)
    db_module.init_db()
    yield path
    # Windows-safe cleanup: close handles + remove sidecars
    import gc
    gc.collect()
    for ext in ("", "-wal", "-shm"):
        try:
            os.remove(path + ext)
        except OSError:
            pass


def test_count_nouns_extracts_korean_nouns():
    text = "기준금리 인상으로 환율 급등. 기준금리 추가 인상 가능성"
    counts = keyword_extractor._count_nouns(text)
    assert counts["기준금리"] == 2
    assert counts["환율"] == 1


def test_top_candidates_filters_stopwords():
    counts = {"기준금리": 5, "있다": 7, "환율": 3, "그리고": 4}
    top = keyword_extractor._top_candidates(counts, n=10)
    keywords = [k for k, _ in top]
    assert "있다" not in keywords
    assert "그리고" not in keywords
    assert "기준금리" in keywords


def test_extract_for_category_persists(tmp_db):
    # seed articles
    for i in range(3):
        db_module.add_news_article({
            "category": "economy",
            "title": f"기준금리 인상 {i}",
            "link": f"https://example.com/{i}",
            "summary": "환율도 영향",
        })

    # mock LLM refinement
    fake_refined = [
        {"keyword": "기준금리", "score": 0.92, "reason": "핵심 금융 이슈"},
        {"keyword": "환율", "score": 0.71, "reason": "시장 영향"},
    ]
    with patch.object(keyword_extractor, "_refine_with_llm", return_value=fake_refined):
        kws = keyword_extractor.extract_for_category("economy", limit=2)

    assert len(kws) == 2
    assert kws[0]["keyword"] == "기준금리"
    persisted = db_module.list_trending_keywords(category="economy")
    assert {p["keyword"] for p in persisted} == {"기준금리", "환율"}
