#!/usr/bin/env python3
"""Generate the W20 smart-canteen weekly report HTML assets.

The source of truth is the Markdown report plus the extracted Excel records.
This script only renders user-facing HTML wrappers and small summary visuals.
"""

from __future__ import annotations

import csv
import html
import subprocess
from collections import Counter
from pathlib import Path


ROOT = Path(__file__).resolve().parents[3]
OUT_DIR = ROOT / "work/weekly-reports/outputs/2026-W20/smart-canteen-project"

REPORT_MD = OUT_DIR / "smart-canteen-weekly-report.md"
REPORT_HTML = OUT_DIR / "smart-canteen-weekly-report.html"
BRIEF_MD = OUT_DIR / "smart-canteen-weekly-leadership-brief.md"
BRIEF_HTML = OUT_DIR / "smart-canteen-weekly-leadership-brief.html"
EXCEL_EXTRACT = OUT_DIR / "excel-current-week-extract.csv"


TEAM_FOCUS = [
    ("李潇", "项目需求与售前支持", "金斯瑞、江西206、首通智诚、江苏国信、苏州福耀等项目需求确认、客户问题回复、报价和产品材料推进。"),
    ("孙海琴", "监管大屏与页面体验", "教委食安监管大屏、总览大屏、进销存大屏交互动效、Vue 样式转换和页面整合。"),
    ("王朔", "产品设计与市场支撑", "网信办、三全、广东反兴奋剂等项目支持，教委端大屏产品设计和 AI 原型链路推进。"),
    ("兰海军", "标准产品与交付支撑", "售前轻采集系统、金斯瑞标准产品优化、山西焦煤数据处理和产业园食安系统问题处理。"),
    ("尹旭亮", "设备链路与 AI 识别", "金斯瑞 AI 菜品识别、江西206 消费机/称重台、460 设备会话与重量轨迹能力推进。"),
    ("赖清涛", "接口开发与上线保障", "金斯瑞 OA/补贴接口、江西206 售卖柜开发上线、取餐柜方案和 Codex 协作开发。"),
    ("孙倩倩", "小程序、食安与联调", "首通智诚小程序加固、callScreen 叫号联调、食安设备和大屏问题排查、AI 营养师问答。"),
    ("郭东伟", "标准小程序与终端能力", "标准小程序、AI 运动营养师、乐心手环、银行对接流程、Android 460 和终端编程智能体验证。"),
]


PROJECTS = [
    ("金斯瑞", "取餐柜、OA 接口、补贴、麻辣烫小票、AI 菜品识别持续推进"),
    ("江西206", "售卖柜、消费机、称重台、离线消费和升级部署联动优化"),
    ("首通智诚", "缴费需求、原型页面、小程序加固和银行对接流程沉淀"),
    ("江苏国信", "合同需求梳理、个性化需求、报价和部署准备"),
    ("苏州福耀", "食堂场景个性化需求确认，进入售前方案和交付准备"),
    ("三全 / 网信办", "投标方案、等保范围、进销存培训和供应商协同继续推进"),
]


def render_markdown(markdown_text: str) -> str:
    result = subprocess.run(
        ["pandoc", "-f", "gfm", "-t", "html5"],
        input=markdown_text,
        text=True,
        capture_output=True,
        check=True,
    )
    return result.stdout


def read_excel_counts() -> tuple[int, int, list[tuple[str, int]]]:
    people: Counter[str] = Counter()
    rows = 0
    with EXCEL_EXTRACT.open("r", encoding="utf-8-sig", newline="") as f:
        reader = csv.DictReader(f)
        for row in reader:
            rows += 1
            people[row["person"]] += 1
    return len(people), rows, people.most_common()


def team_cards() -> str:
    cards = []
    for name, role, detail in TEAM_FOCUS:
        cards.append(
            f"""
            <article class="person-card">
              <strong>{html.escape(name)}</strong>
              <span>{html.escape(role)}</span>
              <p>{html.escape(detail)}</p>
            </article>
            """
        )
    return "\n".join(cards)


def project_cards() -> str:
    cards = []
    for project, detail in PROJECTS:
        cards.append(
            f"""
            <article class="project-card">
              <strong>{html.escape(project)}</strong>
              <p>{html.escape(detail)}</p>
            </article>
            """
        )
    return "\n".join(cards)


def mini_bars(counts: list[tuple[str, int]]) -> str:
    max_count = max((count for _, count in counts), default=1)
    rows = []
    for name, count in counts:
        width = 18 + int(82 * count / max_count)
        rows.append(
            f"""
            <div class="bar-row">
              <span>{html.escape(name)}</span>
              <div class="bar-track"><i style="width:{width}%"></i></div>
              <b>{count}</b>
            </div>
            """
        )
    return "\n".join(rows)


def page_template(title: str, subtitle: str, body: str, *, is_brief: bool = False) -> str:
    people_count, row_count, people_counts = read_excel_counts()
    brief_class = " brief-mode" if is_brief else ""
    return f"""<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>{html.escape(title)}</title>
  <style>
    :root {{
      --ink: #172033;
      --muted: #617084;
      --line: #d8e0ea;
      --paper: #ffffff;
      --wash: #f4f7fa;
      --blue: #1f6feb;
      --cyan: #0e7490;
      --green: #0f766e;
      --amber: #b86b00;
      --red: #b42318;
      --shadow: 0 20px 60px rgba(23, 32, 51, .11);
    }}
    * {{ box-sizing: border-box; }}
    body {{
      margin: 0;
      color: var(--ink);
      background: var(--wash);
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", Arial, sans-serif;
      line-height: 1.72;
      overflow-wrap: anywhere;
    }}
    .hero {{
      color: #fff;
      background:
        radial-gradient(circle at 82% 16%, rgba(255,255,255,.24), transparent 24%),
        linear-gradient(135deg, #123c69 0%, #0f766e 54%, #9a5b09 100%);
    }}
    .hero-inner {{
      max-width: 1180px;
      margin: 0 auto;
      padding: 42px 24px 70px;
      display: grid;
      grid-template-columns: minmax(0, 1.08fr) minmax(330px, .92fr);
      gap: 28px;
      align-items: center;
    }}
    .eyebrow {{
      display: inline-flex;
      padding: 6px 10px;
      border: 1px solid rgba(255,255,255,.35);
      border-radius: 999px;
      background: rgba(255,255,255,.14);
      font-size: 13px;
    }}
    h1, h2, h3 {{ margin: 0; line-height: 1.22; letter-spacing: 0; }}
    .hero h1 {{
      margin-top: 18px;
      font-size: clamp(32px, 5.8vw, 58px);
      max-width: 850px;
    }}
    .hero p {{
      margin: 18px 0 0;
      max-width: 790px;
      font-size: 18px;
      color: rgba(255,255,255,.9);
    }}
    .hero-tags {{
      display: flex;
      flex-wrap: wrap;
      gap: 8px;
      margin-top: 24px;
    }}
    .hero-tags span {{
      padding: 7px 10px;
      border-radius: 999px;
      background: rgba(255,255,255,.15);
      font-size: 13px;
    }}
    .flow {{
      min-height: 300px;
      border: 1px solid rgba(255,255,255,.32);
      border-radius: 8px;
      background: rgba(255,255,255,.12);
      padding: 20px;
    }}
    .flow svg {{ display: block; width: 100%; height: auto; }}
    main {{
      max-width: 1180px;
      margin: -38px auto 0;
      padding: 0 24px 56px;
    }}
    .metric-grid {{
      display: grid;
      grid-template-columns: repeat(4, minmax(0, 1fr));
      gap: 14px;
      margin-bottom: 22px;
    }}
    .metric {{
      min-height: 132px;
      padding: 18px;
      border: 1px solid rgba(216,224,234,.95);
      border-radius: 8px;
      background: var(--paper);
      box-shadow: var(--shadow);
    }}
    .metric strong {{
      display: block;
      color: var(--blue);
      font-size: 30px;
      line-height: 1;
    }}
    .metric span {{
      display: block;
      margin-top: 12px;
      color: var(--muted);
      font-size: 14px;
    }}
    section.panel {{
      margin-top: 22px;
      padding: 28px;
      border: 1px solid var(--line);
      border-radius: 8px;
      background: var(--paper);
      box-shadow: 0 10px 32px rgba(23, 32, 51, .055);
    }}
    .section-head {{
      display: flex;
      justify-content: space-between;
      align-items: flex-end;
      gap: 22px;
      margin-bottom: 18px;
    }}
    .section-head p {{
      margin: 0;
      max-width: 500px;
      color: var(--muted);
      font-size: 14px;
    }}
    h2 {{
      font-size: clamp(22px, 3vw, 32px);
      color: #12243f;
    }}
    .project-grid {{
      display: grid;
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: 12px;
    }}
    .project-card, .person-card {{
      border: 1px solid var(--line);
      border-radius: 8px;
      background: #fff;
    }}
    .project-card {{
      min-height: 138px;
      padding: 18px;
      border-top: 5px solid var(--green);
    }}
    .project-card:nth-child(2n) {{ border-top-color: var(--blue); }}
    .project-card:nth-child(3n) {{ border-top-color: var(--amber); }}
    .project-card strong, .person-card strong {{
      display: block;
      font-size: 18px;
      color: #12243f;
    }}
    .project-card p, .person-card p {{
      margin: 9px 0 0;
      color: var(--muted);
      font-size: 14px;
    }}
    .people-grid {{
      display: grid;
      grid-template-columns: repeat(4, minmax(0, 1fr));
      gap: 12px;
    }}
    .person-card {{
      min-height: 170px;
      padding: 18px;
    }}
    .person-card span {{
      display: block;
      margin-top: 5px;
      color: var(--green);
      font-size: 13px;
      font-weight: 700;
    }}
    .bar-wrap {{
      display: grid;
      grid-template-columns: minmax(0, 1fr) minmax(280px, .68fr);
      gap: 18px;
      align-items: start;
    }}
    .bar-panel {{
      padding: 18px;
      border: 1px solid var(--line);
      border-radius: 8px;
      background: #fbfcfe;
    }}
    .bar-row {{
      display: grid;
      grid-template-columns: 58px minmax(0, 1fr) 28px;
      gap: 9px;
      align-items: center;
      margin: 10px 0;
      font-size: 13px;
    }}
    .bar-track {{
      height: 9px;
      border-radius: 999px;
      background: #e8eef6;
      overflow: hidden;
    }}
    .bar-track i {{
      display: block;
      height: 100%;
      border-radius: inherit;
      background: linear-gradient(90deg, var(--green), var(--blue));
    }}
    .report-body h1 {{ display: none; }}
    .report-body h2 {{
      margin-top: 30px;
      padding-left: 12px;
      border-left: 5px solid var(--blue);
      font-size: 24px;
    }}
    .report-body h2:first-child {{ margin-top: 0; }}
    .report-body h3 {{
      margin-top: 22px;
      color: #0f4d73;
      font-size: 18px;
    }}
    .report-body p {{ margin: 10px 0; }}
    .report-body ul, .report-body ol {{ padding-left: 22px; }}
    .report-body li {{ margin: 8px 0; }}
    .report-body blockquote {{
      margin: 0 0 18px;
      padding: 12px 16px;
      border-left: 5px solid var(--green);
      background: #f5faf8;
      color: var(--muted);
    }}
    .report-body table {{
      width: 100%;
      border-collapse: collapse;
      margin: 14px 0;
      font-size: 14px;
    }}
    .report-body th, .report-body td {{
      padding: 12px 13px;
      border: 1px solid var(--line);
      vertical-align: top;
      text-align: left;
    }}
    .report-body th {{
      background: #eef4fb;
      color: #12243f;
    }}
    footer {{
      margin-top: 24px;
      color: var(--muted);
      text-align: center;
      font-size: 13px;
    }}
    .brief-mode main {{ max-width: 1080px; }}
    @media (max-width: 980px) {{
      .hero-inner, .bar-wrap {{ grid-template-columns: 1fr; }}
      .metric-grid, .people-grid {{ grid-template-columns: repeat(2, minmax(0, 1fr)); }}
      .project-grid {{ grid-template-columns: repeat(2, minmax(0, 1fr)); }}
      main {{ margin-top: -28px; }}
    }}
    @media (max-width: 680px) {{
      .hero-inner {{ padding: 28px 14px 42px; }}
      main {{ padding: 0 12px 36px; margin-top: 14px; }}
      .metric-grid, .project-grid, .people-grid {{ grid-template-columns: 1fr; }}
      section.panel {{ padding: 20px; }}
      .section-head {{ display: block; }}
      .section-head p {{ margin-top: 8px; }}
      .report-body table {{ display: block; overflow-x: auto; }}
    }}
  </style>
</head>
<body class="{brief_class}">
  <header class="hero">
    <div class="hero-inner">
      <div>
        <span class="eyebrow">2026-W20 · 5月11日-5月17日</span>
        <h1>{html.escape(title)}</h1>
        <p>{html.escape(subtitle)}</p>
        <div class="hero-tags">
          <span>项目交付</span>
          <span>产品标准化</span>
          <span>监管大屏</span>
          <span>设备联调</span>
          <span>AI 提效</span>
        </div>
      </div>
      <div class="flow" aria-label="本周工作主线图">
        <svg viewBox="0 0 520 330" role="img">
          <defs>
            <marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto">
              <path d="M0,0 L0,6 L9,3 z" fill="#fff"></path>
            </marker>
          </defs>
          <rect x="62" y="26" width="396" height="58" rx="8" fill="rgba(255,255,255,.2)" stroke="rgba(255,255,255,.45)"></rect>
          <text x="260" y="61" fill="#fff" text-anchor="middle" font-size="18" font-weight="800">智慧食堂项目周推进</text>
          <path d="M260 88 V118" stroke="#fff" stroke-width="3" marker-end="url(#arrow)"></path>
          <rect x="36" y="130" width="206" height="72" rx="8" fill="rgba(255,255,255,.18)" stroke="rgba(255,255,255,.42)"></rect>
          <text x="139" y="160" fill="#fff" text-anchor="middle" font-size="15" font-weight="800">当前项目需要</text>
          <text x="139" y="184" fill="rgba(255,255,255,.82)" text-anchor="middle" font-size="12">需求、上线、联调、客户问题</text>
          <rect x="278" y="130" width="206" height="72" rx="8" fill="rgba(255,255,255,.18)" stroke="rgba(255,255,255,.42)"></rect>
          <text x="381" y="160" fill="#fff" text-anchor="middle" font-size="15" font-weight="800">产品技术引领</text>
          <text x="381" y="184" fill="rgba(255,255,255,.82)" text-anchor="middle" font-size="12">标准产品、大屏、设备、AI</text>
          <path d="M139 207 V250 H381 V207" stroke="#fff" stroke-width="3" fill="none" marker-end="url(#arrow)"></path>
          <rect x="96" y="260" width="328" height="44" rx="8" fill="rgba(255,255,255,.24)" stroke="rgba(255,255,255,.5)"></rect>
          <text x="260" y="288" fill="#fff" text-anchor="middle" font-size="15" font-weight="800">形成可复制的产品和交付能力</text>
        </svg>
      </div>
    </div>
  </header>
  <main>
    <div class="metric-grid">
      <div class="metric"><strong>{people_count}</strong><span>位同事周输入已归纳，覆盖产品、研发、设计、设备和交付支撑。</span></div>
      <div class="metric"><strong>{row_count}</strong><span>条 Excel 当前周记录进入本版报告，不再只依据项目控制记录。</span></div>
      <div class="metric"><strong>10+</strong><span>个项目被纳入本周进展，包括金斯瑞、江西206、国信、苏州福耀等。</span></div>
      <div class="metric"><strong>4</strong><span>类能力同步沉淀：标准产品、大屏方案、硬件设备链路、AI 工作流。</span></div>
    </div>

    <section class="panel">
      <div class="section-head">
        <div>
          <h2>重点项目推进图</h2>
        </div>
        <p>这部分按项目和客户场景归纳，便于经营层看到交付进度，也便于产品团队识别哪些能力可沉淀为标准产品。</p>
      </div>
      <div class="project-grid">
        {project_cards()}
      </div>
    </section>

    <section class="panel">
      <div class="section-head">
        <div>
          <h2>团队贡献地图</h2>
        </div>
        <p>按 Excel 周报归纳每位同事本周贡献，让报告体现跨项目、跨角色、跨部门协同。</p>
      </div>
      <div class="bar-wrap">
        <div class="people-grid">
          {team_cards()}
        </div>
        <div class="bar-panel">
          <strong>当前周记录分布</strong>
          {mini_bars(people_counts)}
        </div>
      </div>
    </section>

    <section class="panel report-body">
      {body}
    </section>

    <footer>来源：数字技术中心工作周报2025-2026.xlsx · 当前周列 5月11日-5月17日 · 本页由 zhctprompt 周报流程生成</footer>
  </main>
</body>
</html>
"""


def main() -> None:
    report_body = render_markdown(REPORT_MD.read_text(encoding="utf-8"))
    REPORT_HTML.write_text(
        page_template(
            "数字技术中心 / 交付实施部智慧食堂项目周报",
            "基于团队 Excel 周报归纳本周项目交付、产品建设、技术攻关和 AI 提效进展，突出满足当前项目需要与做好技术产品引领两条主线。",
            report_body,
        ),
        encoding="utf-8",
    )

    brief_body = render_markdown(BRIEF_MD.read_text(encoding="utf-8"))
    BRIEF_HTML.write_text(
        page_template(
            "智慧食堂项目周报一页版",
            "面向经营层快速阅读：说明本周推进到哪里、形成了哪些可复用能力、下周需要抓住哪些闭环。",
            brief_body,
            is_brief=True,
        ),
        encoding="utf-8",
    )


if __name__ == "__main__":
    main()
