"""PRISMA 流程计算 + SVG 生成"""

from collections import Counter

from app.models.review import ReviewLiterature, SystematicReview


class PrismaFlowData:
    identification_total: int
    duplicates_removed: int
    screened: int
    excluded_screening: int
    full_text_assessed: int
    excluded_eligibility: int
    included_total: int
    excluded_reasons: dict[str, int]


def compute_prisma_flow(review: SystematicReview, literatures: list[ReviewLiterature]) -> dict:
    """从 ReviewLiterature.stage + exclusion_reason 统计 PRISMA 流程计数。"""
    stage_count: dict[str, int] = Counter()
    exclusion_reasons: Counter = Counter()

    duplicates = 0
    for rl in literatures:
        stage_count[rl.stage] += 1
        if rl.stage == "duplicate":
            duplicates += 1
            continue
        if rl.stage == "excluded" and rl.exclusion_reason:
            # 按分号或/分割多条排除原因
            for reason in rl.exclusion_reason.replace("；", ";").split(";"):
                reason = reason.strip()
                if not reason:
                    continue
                # "duplicate" 类排除原因计入去重而非 exclude_reasons
                if "duplicate" in reason.lower() or "重复" in reason or "去重" in reason:
                    duplicates += 1
                else:
                    exclusion_reasons[reason] += 1

    identification = stage_count.get("identification", 0) + stage_count.get("screening", 0) + \
        stage_count.get("eligibility", 0) + stage_count.get("included", 0) + \
        stage_count.get("excluded", 0)

    screened = stage_count.get("screening", 0) + stage_count.get("eligibility", 0) + \
        stage_count.get("included", 0) + stage_count.get("excluded", 0)

    full_text = stage_count.get("eligibility", 0) + stage_count.get("included", 0) + \
        stage_count.get("excluded", 0)

    excluded_screening = screened - stage_count.get("eligibility", 0) - stage_count.get("included", 0) - \
        stage_count.get("excluded", 0)

    excluded_eligibility = stage_count.get("excluded", 0)

    return {
        "identification_total": identification,
        "duplicates_removed": duplicates,
        "screened": screened,
        "excluded_screening": max(0, excluded_screening),
        "full_text_assessed": full_text,
        "excluded_eligibility": excluded_eligibility,
        "included_total": stage_count.get("included", 0),
        "excluded_reasons": dict(exclusion_reasons.most_common(10)),
    }


def generate_prisma_svg(flow: dict, language: str = "zh") -> str:
    """生成 PRISMA 2020 流程图 SVG。"""
    labels = _prisma_labels(language)

    ident_total = flow.get("identification_total", 0)
    screened = flow.get("screened", 0)
    ex_screening = flow.get("excluded_screening", 0)
    full_text = flow.get("full_text_assessed", 0)
    ex_eligibility = flow.get("excluded_eligibility", 0)
    included = flow.get("included_total", 0)
    ex_reasons = flow.get("excluded_reasons", {})

    reasons_text = ""
    if ex_reasons:
        items = [f"<tspan x='490' dy='18'>{_escape_svg(k)} (n={v})</tspan>" for k, v in ex_reasons.items()]
        reasons_text = "\n".join(items[:5])

    return f'''<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 680" font-family="Arial, sans-serif" font-size="13">
  <rect width="800" height="680" fill="white"/>

  <!-- 标题 -->
  <text x="400" y="30" text-anchor="middle" font-size="16" font-weight="bold" fill="#333">{_escape_svg(labels['title'])}</text>

  <!-- 识别 -->
  <rect x="200" y="50" width="400" height="50" rx="6" fill="#e8f4fd" stroke="#1890ff" stroke-width="2"/>
  <text x="400" y="72" text-anchor="middle" font-size="14" font-weight="bold" fill="#1890ff">{labels['identification']}</text>
  <text x="400" y="90" text-anchor="middle" font-size="12" fill="#666">(n = {ident_total})</text>

  <!-- 箭头 1 -->
  <line x1="400" y1="100" x2="400" y2="130" stroke="#ccc" stroke-width="2"/>
  <polygon points="395,128 400,138 405,128" fill="#ccc"/>

  <!-- 初筛 -->
  <rect x="200" y="140" width="400" height="50" rx="6" fill="#e8f8e8" stroke="#52c41a" stroke-width="2"/>
  <text x="400" y="162" text-anchor="middle" font-size="14" font-weight="bold" fill="#52c41a">{labels['screening']}</text>
  <text x="400" y="180" text-anchor="middle" font-size="12" fill="#666">(n = {screened})</text>

  <!-- 右边排除标注 -->
  <rect x="610" y="155" width="170" height="28" rx="4" fill="#fff1f0" stroke="#ff4d4f" stroke-width="1"/>
  <text x="695" y="173" text-anchor="middle" font-size="11" fill="#ff4d4f">{labels['excluded']}: {ex_screening}</text>

  <!-- 箭头 2 -->
  <line x1="400" y1="190" x2="400" y2="220" stroke="#ccc" stroke-width="2"/>
  <polygon points="395,218 400,228 405,218" fill="#ccc"/>

  <!-- 全文评估 -->
  <rect x="200" y="230" width="400" height="50" rx="6" fill="#fffbe6" stroke="#faad14" stroke-width="2"/>
  <text x="400" y="252" text-anchor="middle" font-size="14" font-weight="bold" fill="#faad14">{labels['eligibility']}</text>
  <text x="400" y="270" text-anchor="middle" font-size="12" fill="#666">(n = {full_text})</text>

  <!-- 右边排除标注 -->
  <rect x="610" y="245" width="170" height="28" rx="4" fill="#fff1f0" stroke="#ff4d4f" stroke-width="1"/>
  <text x="695" y="263" text-anchor="middle" font-size="11" fill="#ff4d4f">{labels['excluded']}: {ex_eligibility}</text>

  <!-- 箭头 3 -->
  <line x1="400" y1="280" x2="400" y2="310" stroke="#ccc" stroke-width="2"/>
  <polygon points="395,308 400,318 405,308" fill="#ccc"/>

  <!-- 纳入 -->
  <rect x="200" y="320" width="400" height="50" rx="6" fill="#fff2f0" stroke="#f5222d" stroke-width="2"/>
  <text x="400" y="342" text-anchor="middle" font-size="14" font-weight="bold" fill="#f5222d">{labels['included']}</text>
  <text x="400" y="360" text-anchor="middle" font-size="12" fill="#666">(n = {included})</text>

  <!-- 排除原因列表 -->
  <text x="400" y="410" text-anchor="middle" font-size="12" font-weight="bold" fill="#666">{labels['exclusion_reasons']}</text>
  <text x="400" y="430" text-anchor="middle" font-size="11" fill="#999">
    <tspan>{reasons_text}</tspan>
  </text>
</svg>'''


def _prisma_labels(language: str) -> dict:
    if language == "en":
        return {
            "title": "PRISMA 2020 Flow Diagram",
            "identification": "Identification",
            "screening": "Screening",
            "eligibility": "Eligibility",
            "included": "Included",
            "excluded": "Excluded",
            "exclusion_reasons": "Reasons for exclusion",
        }
    return {
        "title": "PRISMA 2020 文献筛选流程图",
        "identification": "识别",
        "screening": "初筛",
        "eligibility": "全文评估",
        "included": "纳入",
        "excluded": "排除",
        "exclusion_reasons": "排除原因",
    }


def _escape_svg(s: str) -> str:
    return s.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;").replace('"', "&quot;")
