"""
text_scoring.py — 五维打分接口 + 去重（≤100行）
打分维度逻辑见 _scoring_dims.py
"""
from __future__ import annotations
import re
from difflib import SequenceMatcher
from typing import Any

from .constants import (
    BANNED_WORDS_DEFAULT, BANNED_VISUAL_WORDS,
    SCORE_WEIGHTS, QUALITY_PASS_SCORE,
    DEDUP_TITLE_THRESHOLD, DEDUP_TITLE_CONTENT_TITLE, DEDUP_TITLE_CONTENT_BODY,
)
from ._scoring_dims import (
    _cat_words, score_title, score_emotion, score_selling,
    score_keyword, score_compliance,
)


def score_copy(
    copy: dict[str, Any],
    source: dict[str, Any],
    banned_words: list[str] | None = None,
    weights: dict[str, int] | None = None,
    pass_score: int = QUALITY_PASS_SCORE,
) -> dict[str, Any]:
    """
    五维打分（标题25 / 情绪25 / 买点25 / 关键词20 / 合规5）
    返回：{score, score_detail, passed, banned_words_found}
    """
    w      = weights or SCORE_WEIGHTS
    bwords = list(set((banned_words or []) + BANNED_WORDS_DEFAULT + BANNED_VISUAL_WORDS))

    title   = str(copy.get("title", ""))
    content = str(copy.get("content", ""))
    tags    = " ".join(str(t) for t in copy.get("tags", []))
    full    = f"{title}\n{content}\n{tags}\n{copy.get('imageBrief','')}"

    selling_points = source.get("selling_points", []) or []
    keywords       = source.get("keywords", []) or []
    category       = source.get("category", "通用好物")
    cat_w          = _cat_words(category)

    dim_title      = score_title(title, cat_w, w)
    dim_emotion    = score_emotion(full, w)
    dim_selling    = score_selling(copy, full, selling_points, w)
    dim_keyword    = score_keyword(copy, tags, keywords, w)
    dim_compliance, found_all = score_compliance(full, bwords, w)

    details = [dim_title, dim_emotion, dim_selling, dim_keyword, dim_compliance]
    total   = max(0, min(100, sum(d["score"] for d in details)))
    passed  = (total >= pass_score) and not found_all

    return {"score": total, "score_detail": details, "passed": passed, "banned_words_found": found_all}


def _sim(a: str, b: str) -> float:
    return SequenceMatcher(None, a, b).ratio()


def _copy_signature(copy: dict) -> str:
    content = str(copy.get("content", ""))
    opening = re.sub(r"\s+", "", content[:30])
    return f"{copy.get('title', '')}|{opening}"


def is_similar_copy(a: dict, b: dict) -> bool:
    """同质化判重（标题≥0.82 OR 标题≥0.65且正文≥0.72）"""
    t = _sim(str(a.get("title", "")), str(b.get("title", "")))
    if t >= DEDUP_TITLE_THRESHOLD:
        return True
    if t >= DEDUP_TITLE_CONTENT_TITLE:
        if _sim(str(a.get("content",""))[:200], str(b.get("content",""))[:200]) >= DEDUP_TITLE_CONTENT_BODY:
            return True
    return False


def dedupe_copies(copies: list[dict], previous: list[dict] | None = None) -> list[dict]:
    """本轮内互去重 + 与历史去重 + angle 去重"""
    history = previous or []
    kept: list[dict] = []
    used_angles: set[str] = set()
    for c in copies:
        sig = _copy_signature(c)
        if any(_copy_signature(h) == sig for h in history): continue
        if any(is_similar_copy(c, h) for h in history):    continue
        if any(is_similar_copy(c, k) for k in kept):       continue
        angle = str(c.get("angle", "")).strip()
        if angle and angle in used_angles: continue
        if angle: used_angles.add(angle)
        kept.append(c)
    return kept
