import pytest

from app.workers.citation_engine import BrandMatcher, CompetitorDetector


def test_brand_matcher_exact():
    matcher = BrandMatcher(target_brand="华为", brand_aliases=["Huawei"])
    result = matcher.match("华为是一家伟大的科技公司")
    assert result["cited"] is True
    assert result["match_type"] == "exact"
    assert result["confidence"] == 1.0


def test_brand_matcher_alias():
    matcher = BrandMatcher(target_brand="华为", brand_aliases=["Huawei"])
    result = matcher.match("Huawei makes great phones")
    assert result["cited"] is True
    assert result["match_type"] == "alias"
    assert result["confidence"] == 0.9


def test_brand_matcher_fuzzy():
    matcher = BrandMatcher(target_brand="华为")
    # "华伟" is a fuzzy match to "华为"
    result = matcher.match("华伟 是一家科技公司")
    assert result["cited"] is True
    assert result["match_type"] == "fuzzy"
    assert result["confidence"] > 0.4


def test_brand_matcher_no_match():
    matcher = BrandMatcher(target_brand="华为")
    result = matcher.match("这是一段完全不相关的文本，没有任何品牌信息")
    assert result["cited"] is False
    assert result["match_type"] is None
    assert result["confidence"] == 0.0


def test_competitor_detector():
    detector = CompetitorDetector()
    text = "中国平安和中国人寿都是大型保险公司"
    competitors = detector.detect(text, target_brand="中国平安")
    assert "中国人寿" in competitors
    assert "中国平安" not in competitors


def test_citation_position():
    matcher = BrandMatcher(target_brand="华为")
    text = "第一段介绍市场情况\n第二段提到华为的产品\n第三段是总结"
    result = matcher.match(text)
    assert result["cited"] is True
    assert result["position"] == 2
    assert result["citation_text"] is not None


# ---------------------------------------------------------------------------
# 补充测试
# ---------------------------------------------------------------------------
def test_brand_matcher_multiple_aliases():
    """多个别名时，应能匹配任意一个别名。"""
    matcher = BrandMatcher(target_brand="华为", brand_aliases=["Huawei", "HW", "Honor"])
    # 匹配第二个别名
    result = matcher.match("HW released a new chip")
    assert result["cited"] is True
    assert result["match_type"] == "alias"
    assert result["confidence"] == 0.9
    # 匹配第三个别名
    result2 = matcher.match("Honor phones are popular")
    assert result2["cited"] is True
    assert result2["match_type"] == "alias"


def test_brand_matcher_fuzzy_threshold_boundary():
    """模糊匹配阈值边界：ratio 恰好在 0.4 附近的情况。"""
    matcher = BrandMatcher(target_brand="华为")
    # "华伟" 与 "华为" 的 ratio 约为 0.5，应大于 0.4
    result = matcher.match("华伟 是一家科技公司")
    assert result["cited"] is True
    assert result["match_type"] == "fuzzy"
    assert result["confidence"] > 0.4

    # "苹果" vs "华为" ratio 很低，不应超过 0.4
    result2 = matcher.match("苹果科技公司")
    assert result2["cited"] is False
    assert result2["match_type"] is None


def test_brand_matcher_empty_text():
    """空字符串输入不应崩溃，应返回 cited=False。"""
    matcher = BrandMatcher(target_brand="华为", brand_aliases=["Huawei"])
    result = matcher.match("")
    assert result["cited"] is False
    assert result["confidence"] == 0.0
    assert result["match_type"] is None
    assert result["position"] is None


def test_competitor_detector_multi_industry():
    """竞品检测应能跨行业识别品牌。"""
    detector = CompetitorDetector()
    text = "华为和小米是科技公司，工商银行和招商银行是银行"
    competitors_tech = detector.detect(text, target_brand="华为")
    assert "小米" in competitors_tech
    assert "腾讯" not in competitors_tech  # 未在文本中出现
    assert "华为" not in competitors_tech

    competitors_finance = detector.detect(text, target_brand="工商银行")
    assert "招商银行" in competitors_finance
    assert "建设银行" not in competitors_finance  # 未在文本中出现


def test_citation_position_multiple_paragraphs():
    """品牌在不同段落位置出现时的 position 检测。"""
    matcher = BrandMatcher(target_brand="华为")

    text_first = "华为位于第一段\n第二段没有\n第三段也没有"
    result = matcher.match(text_first)
    assert result["position"] == 1

    text_third = "第一段没有\n第二段没有\n华为在第三段"
    result = matcher.match(text_third)
    assert result["position"] == 3

    text_last = "第一段\n第二段\n第三段\n最后一段提到华为"
    result = matcher.match(text_last)
    assert result["position"] == 4
