"""
Phase 1: 历史招投标相似度分析

对比新招标文件与各历史招标文件的相似度，
决定每组历史数据对最终投标文件的影响权重。

用法:
    from phase1_parsing.analyze_similarity import calculate_similarity
    results = calculate_similarity(new_tender_text, historical_groups)
"""

import sys
import os
import json
import re

sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from llm.llm_utils import LLM


def extract_tender_features(text: str) -> dict:
    """从招标文本中提取关键特征用于相似度比较"""
    features = {}

    # 项目类型判断
    type_keywords = {
        "物业管理": ["物业", "保洁", "保安", "绿化", "维修", "会务", "客服"],
        "工程装修": ["装修", "改造", "修缮", "施工", "工程"],
        "IT服务": ["软件", "系统", "信息化", "开发", "运维", "网络安全"],
        "物资采购": ["采购", "设备", "货物", "供应", "物资"],
        "咨询服务": ["咨询", "评估", "审计", "监理", "设计"],
        "餐饮服务": ["餐饮", "食堂", "供餐", "配餐"],
    }
    matched_types = []
    for ttype, kws in type_keywords.items():
        if any(kw in text[:8000] for kw in kws):
            matched_types.append(ttype)
    features["project_types"] = matched_types

    # 采购人（同一采购人很可能项目相似）
    m = re.search(r"采购人[：:]\s*(.{2,30})", text[:5000])
    if m:
        features["buyer"] = m.group(1).strip()

    # 预算规模
    m = re.search(r"预算[^\n]{0,10}[：:]\s*([\d,.]+\s*万)", text[:10000])
    if m:
        budget_str = m.group(1).strip().replace(",", "")
        try:
            budget_val = float(budget_str.replace("万", ""))
            features["budget"] = budget_val
            if budget_val > 1000:
                features["budget_level"] = "大型"
            elif budget_val > 200:
                features["budget_level"] = "中型"
            else:
                features["budget_level"] = "小型"
        except ValueError:
            pass

    # 服务期限
    m = re.search(r"服务期限[：:](.{0,40})", text[:5000])
    if m:
        features["service_period"] = m.group(1).strip()

    # 地域
    m = re.search(r"([一-鿿]{2,8}(?:区|市|县))", text[:3000])
    if m:
        features["region"] = m.group(1).strip()

    # 关键需求关键词密度
    demand_kw = ["服务方案", "质量标准", "人员配置", "管理制度", "应急预案",
                 "考核", "培训", "设备", "安全", "合同"]
    found_kw = [kw for kw in demand_kw if kw in text]
    features["demand_keywords"] = found_kw

    return features


def calculate_similarity(
    new_tender_text: str,
    historical_groups: list,
    use_llm: bool = True,
) -> list:
    """
    计算新招标文件与每组历史招标文件的相似度。

    Args:
        new_tender_text: 新招标文件全文
        historical_groups: [
            {
                "group_id": "project_A",
                "name": "项目名称",
                "tender_text": "历史招标文本",
                "bid_text": "对应投标文本",
                "tender_file": "原始PDF路径",
                "bid_file": "原始PDF路径",
            },
            ...
        ]
        use_llm: 是否用 LLM 做语义级评分（否则只用关键词匹配）

    Returns:
        [
            {
                "group_id": "project_A",
                "name": "项目名称",
                "similarity_score": 0.85,    # 0~1
                "similarity_level": "高",     # 高/中/低
                "similarity_reason": "同为政府机关物业管理...",
                "new_tender_features": {...},
                "history_tender_features": {...},
                "bid_structure": {...},       # 对应投标的目录结构
                "weight": 0.6,                # 归一化后的权重
            },
            ...
        ]
    """
    new_features = extract_tender_features(new_tender_text)
    results = []

    for group in historical_groups:
        hist_features = extract_tender_features(group.get("tender_text", ""))

        if use_llm:
            score, reason = _llm_similarity_score(
                new_tender_text[:8000],
                group.get("tender_text", "")[:8000],
            )
        else:
            score, reason = _keyword_similarity(new_features, hist_features)

        # 提取投标目录
        from phase1_parsing.extract_bid_toc import extract_toc
        bid_toc = extract_toc(group.get("bid_text", ""))

        # 判断相似等级
        if score >= 0.7:
            level = "高"
        elif score >= 0.4:
            level = "中"
        else:
            level = "低"

        results.append({
            "group_id": group["group_id"],
            "name": group.get("name", group["group_id"]),
            "similarity_score": round(score, 4),
            "similarity_level": level,
            "similarity_reason": reason,
            "new_tender_features": new_features,
            "history_tender_features": hist_features,
            "bid_toc": bid_toc,
            "bid_text_len": len(group.get("bid_text", "")),
            "tender_text_len": len(group.get("tender_text", "")),
        })

    # 归一化权重：相似度越高权重越大
    scores = [r["similarity_score"] for r in results]
    total = sum(scores) or 1
    for r in results:
        r["weight"] = round(r["similarity_score"] / total, 4)

    results.sort(key=lambda x: x["similarity_score"], reverse=True)
    return results


def _keyword_similarity(new_feat: dict, hist_feat: dict) -> tuple:
    """基于关键词匹配的相似度计算（快速但粗糙）"""
    score = 0.0
    reasons = []

    # 项目类型匹配
    new_types = set(new_feat.get("project_types", []))
    hist_types = set(hist_feat.get("project_types", []))
    if new_types and hist_types:
        overlap = new_types & hist_types
        if overlap:
            score += 0.3
            reasons.append(f"类型匹配: {overlap}")

    # 采购人匹配
    if (new_feat.get("buyer") and hist_feat.get("buyer")
            and new_feat["buyer"] == hist_feat["buyer"]):
        score += 0.25
        reasons.append("同一采购人")

    # 预算规模匹配
    if new_feat.get("budget_level") and hist_feat.get("budget_level"):
        if new_feat["budget_level"] == hist_feat["budget_level"]:
            score += 0.15
            reasons.append(f"预算规模相当({new_feat['budget_level']})")

    # 需求关键词重叠
    new_kw = set(new_feat.get("demand_keywords", []))
    hist_kw = set(hist_feat.get("demand_keywords", []))
    if new_kw and hist_kw:
        overlap = new_kw & hist_kw
        if overlap:
            kw_score = len(overlap) / max(len(new_kw), 1) * 0.2
            score += kw_score
            reasons.append(f"需求关键词重叠: {overlap}")

    # 地域匹配
    if (new_feat.get("region") and hist_feat.get("region")
            and new_feat["region"] == hist_feat["region"]):
        score += 0.1
        reasons.append("同区域")

    score = min(score, 1.0)
    reason = "；".join(reasons) if reasons else "无明显相似特征"
    return score, reason


def _llm_similarity_score(new_excerpt: str, hist_excerpt: str) -> tuple:
    """用 LLM 评估两个招标文件的相似度（语义级）"""
    try:
        llm = LLM()
        system = (
            "你是一个招标文件比对专家。比较两份招标文件，输出相似度评分(0~1)和理由。\n"
            "输出 JSON: {\"score\": 0.85, \"reason\": \"同类型项目，服务内容重叠度高\"}"
        )
        user = (
            "请比较以下两份招标文件的相似度，考虑项目类型、服务内容、预算规模、采购人等因素：\n\n"
            f"【新招标文件】\n{new_excerpt[:4000]}\n\n"
            f"【历史招标文件】\n{hist_excerpt[:4000]}"
        )
        result = llm._call(system, user, max_tokens=1024, temperature=0.2,
                           response_format={"type": "json_object"})
        parsed = json.loads(result)
        return float(parsed.get("score", 0.5)), parsed.get("reason", "")
    except Exception as e:
        return 0.5, f"LLM评分异常: {e}"


if __name__ == "__main__":
    import sys
    sys.stdout.reconfigure(encoding="utf-8")

    # 简单测试
    text1 = "项目名称：松江区机关事务管理局物业管理服务 预算金额：1739.51万元 服务内容：保洁、保安、绿化、会务"
    text2 = "项目名称：嘉定区机关事务管理局物业管理服务 预算金额：1200万元 服务内容：保洁、保安、绿化"

    groups = [{
        "group_id": "test",
        "name": "测试项目",
        "tender_text": text2,
        "bid_text": "第一章 投标人资格...",
    }]

    results = calculate_similarity(text1, groups, use_llm=False)
    for r in results:
        print(f"{r['name']}: 相似度 {r['similarity_score']} ({r['similarity_level']})")
        print(f"  理由: {r['similarity_reason']}")
        print(f"  权重: {r['weight']}")
