#!/usr/bin/env python3.12
"""豆包配图「禁人物」辅助模块（2026-09-24 用户指出问题后新增）

背景：
  2026-09-02 用户规则：豆包生成的配图 prompt 不体现人名、不画人物肖像，只聚焦事件与品牌。
  但 `search_list_op.py` 只是在 prompt 末尾追加「画面不出现任何人物姓名与肖像」这类**否定式后缀**，
  **标题里的人名没有剥掉** —— 而标题含人名时（如「OPPO × 李现邀你假期…」），
  模型看到「李现」照样会画出该人物肖像。2026-09-24 用户当场指出 brand_hotspots[1] 出现李现。

修复思路：
  在拼 prompt 之前，把人名从文案里**物理删除**（而非仅用否定句约束），
  再叠加否定式后缀双保险。

用法：
    from person_name_filter import strip_person_names, NO_PERSON_SUFFIX
    prompt = "配图：" + strip_person_names(title) + "，新闻配图风格…" + NO_PERSON_SUFFIX
"""
import re

# 否定式后缀（保留原有措辞，双保险）
NO_PERSON_SUFFIX = '，画面不出现任何人物姓名与肖像，只呈现事件场景和品牌产品元素'

# 中文人名清单：营销/时尚/娱乐新闻里常与品牌联名、代言、合作出现的人物。
# 新增人名请在末尾追加，勿打乱顺序（长名先于短名匹配）。
PERSON_NAMES = [
    # 代言/合作常客
    '李现', '王俊凯', '王一博', '肖战', '易烊千玺', '王嘉尔', '蔡徐坤', '朱一龙',
    '迪丽热巴', '杨幂', '赵丽颖', '刘亦菲', '唐嫣', '倪妮', '周迅', '宋佳',
    '杨紫', '关晓彤', '欧阳娜娜', '刘雯', '谷爱凌', '汪苏泷', '陈哲远', '王虹',
    '李凤刚', '朱松纯', '黄健翔', '文淇', '王彦桐', '王俊凯', '王源', '华晨宇',
    '周杰伦', '林俊杰', '陈奕迅', '张学友', '刘德华', '郭富城', '黎明',
    '沈腾', '贾玲', '雷军', '罗永浩', '董明珠', '余承东', '李斌', '李想', '何小鹏',
    '郑义宣', '张骏', '邬江兴',
    # 2026-10-03 补充：体育代言人（「金典听劝签下小孩姐陈妤颉」实测漏删，
    # 该名字未在名单内、且兜底句式「签下<2-4字>」也匹配不到 → 只能加名单）
    '陈妤颉',
]

# 外籍人物：中文译名同样要剥掉（肖像风险一致）
FOREIGN_NAMES_CN = ['马斯克', '扎克伯格', '库克', '奥特曼', '黄仁勋', '陶哲轩']

_ALL_NAMES = sorted(set(PERSON_NAMES + FOREIGN_NAMES_CN), key=len, reverse=True)

# 拉丁人名（标题里直接写英文名的场景）
LATIN_NAMES = [
    'Ewan McGregor', 'Elon Musk', 'Mark Zuckerberg', 'Tim Cook', 'Sam Altman',
    'Jensen Huang', 'Terence Tao',
]


def strip_person_names(text: str) -> str:
    """删除文案中的人名，并清理因此产生的悬空标点/空格。

    例：
      'OPPO × 李现邀你假期「原相机」出行'  → 'OPPO ×邀你假期「原相机」出行' → 'OPPO 假期「原相机」出行'
      '每日新品 | 蜂花请了王俊凯，但…'    → '每日新品 | 蜂花请了，但…' → '每日新品 | 蜂花，但…'
    """
    if not text:
        return text
    out = text
    for n in _ALL_NAMES:
        out = out.replace(n, '')
    for n in LATIN_NAMES:
        out = re.sub(re.escape(n), '', out, flags=re.IGNORECASE)

    # 清理悬空标点/连接符/动词残留：'×'、'请了'、'与'、'邀' 后面紧跟标点或空白的情况
    out = re.sub(r'[×xX]\s*(?=[，,、。；;：:\s]|$)', '', out)
    out = re.sub(r'请了(?=[，,、。；;：:\s]|$)', '', out)
    # 删除外籍人名后残留的「与/和/、」连接词（如 'Canada Goose 与 合作帆船纪录片'）
    out = re.sub(r'\s*[与和]\s*(?=(?:合作|联手|携手|共同|一起))', ' ', out)
    out = re.sub(r'\s+', ' ', out)
    out = re.sub(r'[，,、]\s*(?=[，,、。；;])', '', out)
    out = out.strip('，,、 ')
    return out


def auto_strip_collab_names(text: str) -> str:
    """兜底：清单未收录的人名，按常见合作句式删掉。

    只处理高度确定的句式，避免误删品牌名：
      - '× <2-4汉字>' 后紧跟 邀/为/代/合/携/出 等动词
      - '请了 <2-4汉字>' 后紧跟标点
    """
    if not text:
        return text
    out = re.sub(r'[×xX]\s*[\u4e00-\u9fff]{2,4}(?=[邀为代合携出])', '×', text)
    out = re.sub(r'请了[\u4e00-\u9fff]{2,4}(?=[，,、。；;])', '请了', out)
    out = re.sub(r'\s+', ' ', out).strip()
    return out


def sanitize(text: str) -> str:
    """供配图 prompt 使用的最终清洗：先删清单人名，再兜底删未收录人名。"""
    return auto_strip_collab_names(strip_person_names(text))


if __name__ == '__main__':
    samples = [
        'OPPO × 李现邀你假期「原相机」出行',
        '每日新品 | 蜂花请了王俊凯，但一瓶3块钱的护发素已经卖到100块了',
        'edition × 文淇城市漫步「拥抱好心情」',
        'Canada Goose 与 Ewan McGregor 合作帆船纪录片',
        '魏牌高山 8/9 智慧版 MPV 上市，30.98 万 / 38.58 万元',
    ]
    for s in samples:
        print(f'  前: {s}')
        print(f'  后: {sanitize(s)}')
        print()
