# -*- coding: utf-8 -*-
"""生成科研促销复盘图表：纯内联 SVG -> Chrome headless PNG"""
import json
import subprocess
from pathlib import Path

ROOT = Path('/Users/liuxinyuan/Desktop/Hermes输出-工作类')
OUT = ROOT / '营销活动' / '科研促销复盘_20261103' / '图表'
OUT.mkdir(parents=True, exist_ok=True)
DATA = json.load(open(ROOT / '营销活动' / '科研促销复盘_20261103' / '数据' / 'promo_review_2026.json', encoding='utf-8'))
FONT = "'Songti SC','STSong','SimSun',serif"
NAVY = '#1F4E79'
TEAL = '#2A9D8F'
ORANGE = '#E9A800'
LIGHT = '#EEF6FB'
GREY = '#5F6B7A'

def esc(s):
    return str(s).replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')

def frame(w, h, title, subtitle):
    return f'''<svg xmlns="http://www.w3.org/2000/svg" width="{w}" height="{h}" viewBox="0 0 {w} {h}">
<rect width="{w}" height="{h}" fill="#FFFFFF"/>
<text x="60" y="58" font-family="{FONT}" font-size="34" font-weight="700" fill="{NAVY}">{esc(title)}</text>
<text x="60" y="96" font-family="{FONT}" font-size="19" fill="{GREY}">{esc(subtitle)}</text>
<line x1="60" y1="116" x2="{w-60}" y2="116" stroke="#D8E2EE" stroke-width="2"/>
'''

def yuan(v):
    return f'{v/10000:,.2f}万'

def monthly_chart():
    w, h = 1600, 900
    vals = DATA['monthly_baseline']
    s = frame(w, h, '4–9 月月度销售额与促销折月对照', '口径：B 促销统计同一批 8 名销售员；4–9 月含促销日，为保守基线')
    x0, y0, pw, ph = 100, 155, 1400, 590
    maxv = 90000
    # grid
    for i in range(0, 7):
        y = y0 + ph - ph * i / 6
        s += f'<line x1="{x0}" y1="{y:.1f}" x2="{x0+pw}" y2="{y:.1f}" stroke="#E6ECF3" stroke-width="1"/>'
        s += f'<text x="{x0-14}" y="{y+6:.1f}" text-anchor="end" font-family="{FONT}" font-size="17" fill="{GREY}">{int(maxv*i/6/10000)}万</text>'
    bw = 130
    gap = (pw - bw * len(vals)) / (len(vals) + 1)
    for i, row in enumerate(vals):
        v = row['amount']
        bh = ph * v / maxv
        x = x0 + gap + i * (bw + gap)
        y = y0 + ph - bh
        s += f'<rect x="{x:.1f}" y="{y:.1f}" width="{bw}" height="{bh:.1f}" rx="5" fill="{NAVY}"/>'
        s += f'<text x="{x+bw/2:.1f}" y="{y-12:.1f}" text-anchor="middle" font-family="{FONT}" font-size="21" font-weight="700" fill="{NAVY}">{yuan(v)}</text>'
        s += f'<text x="{x+bw/2:.1f}" y="{y0+ph+34}" text-anchor="middle" font-family="{FONT}" font-size="20" fill="#1F2937">{row["month"][5:]}月</text>'
        s += f'<text x="{x+bw/2:.1f}" y="{y0+ph+62}" text-anchor="middle" font-family="{FONT}" font-size="16" fill="{GREY}">{row["orders"]} 单</text>'
    # reference lines
    y_avg = y0 + ph - ph * DATA['summary']['baseline_monthly'] / maxv
    y_promo = y0 + ph - ph * DATA['summary']['promo_monthly_equivalent'] / maxv
    s += f'<line x1="{x0}" y1="{y_avg:.1f}" x2="{x0+pw}" y2="{y_avg:.1f}" stroke="{ORANGE}" stroke-width="3" stroke-dasharray="10 7"/>'
    s += f'<text x="{x0+12}" y="{y_avg-10:.1f}" text-anchor="start" font-family="{FONT}" font-size="18" fill="{ORANGE}">4–9 月月均 4.02 万</text>'
    s += f'<line x1="{x0}" y1="{y_promo:.1f}" x2="{x0+pw}" y2="{y_promo:.1f}" stroke="{TEAL}" stroke-width="3" stroke-dasharray="10 7"/>'
    s += f'<text x="{x0+12}" y="{y_promo-10:.1f}" text-anchor="start" font-family="{FONT}" font-size="18" fill="{TEAL}">促销折月 7.61 万（+89.0%）</text>'
    s += f'<text x="60" y="{h-30}" font-family="{FONT}" font-size="16" fill="{GREY}">注：9 月已含浙江 8/20–9/30、广东 9/1–9/30 促销销售，因此 9 月柱子高于其他月份；促销折月按浙江 42 天、广东 46 天折算 30 天。</text>'
    return s + '</svg>'

def region_chart():
    w, h = 1600, 820
    vals = DATA['region']
    s = frame(w, h, '区域：基线月均与促销折月', '同一批销售员；折月按浙江 42 天、广东 46 天折算')
    x0, y0, pw, ph = 120, 160, 1320, 510
    maxv = 50000
    for i in range(0, 6):
        y = y0 + ph - ph * i / 5
        s += f'<line x1="{x0}" y1="{y:.1f}" x2="{x0+pw}" y2="{y:.1f}" stroke="#E6ECF3" stroke-width="1"/>'
        s += f'<text x="{x0-14}" y="{y+6:.1f}" text-anchor="end" font-family="{FONT}" font-size="17" fill="{GREY}">{int(maxv*i/5/10000)}万</text>'
    group_w = 260
    bar_w = 90
    for i, row in enumerate(vals):
        base = row['baseline_monthly']; promo = row['promo_monthly']
        cx = x0 + pw * (i + 1) / (len(vals) + 1)
        xb = cx - bar_w - 12
        xp = cx + 12
        hb = ph * base / maxv; hp = ph * promo / maxv
        s += f'<rect x="{xb:.1f}" y="{y0+ph-hb:.1f}" width="{bar_w}" height="{hb:.1f}" rx="5" fill="#B8CCE4"/>'
        s += f'<rect x="{xp:.1f}" y="{y0+ph-hp:.1f}" width="{bar_w}" height="{hp:.1f}" rx="5" fill="{NAVY}"/>'
        s += f'<text x="{xb+bar_w/2:.1f}" y="{y0+ph-hb-10:.1f}" text-anchor="middle" font-family="{FONT}" font-size="18" fill="#456">{yuan(base)}</text>'
        s += f'<text x="{xp+bar_w/2:.1f}" y="{y0+ph-hp-10:.1f}" text-anchor="middle" font-family="{FONT}" font-size="18" font-weight="700" fill="{NAVY}">{yuan(promo)}</text>'
        s += f'<text x="{cx:.1f}" y="{y0+ph+38}" text-anchor="middle" font-family="{FONT}" font-size="22" font-weight="700" fill="#1F2937">{row["region"]}</text>'
        s += f'<text x="{cx:.1f}" y="{y0+ph+68}" text-anchor="middle" font-family="{FONT}" font-size="18" fill="{TEAL}">+{row["growth"]*100:.1f}%</text>'
        s += f'<text x="{cx:.1f}" y="{y0+ph+96}" text-anchor="middle" font-family="{FONT}" font-size="16" fill="{GREY}">{row["orders"]} 单 / {row["groups"]} 组</text>'
    # legend
    s += f'<rect x="{x0}" y="{h-78}" width="26" height="18" fill="#B8CCE4"/><text x="{x0+36}" y="{h-63}" font-family="{FONT}" font-size="18" fill="{GREY}">4–9 月月均</text>'
    s += f'<rect x="{x0+220}" y="{h-78}" width="26" height="18" fill="{NAVY}"/><text x="{x0+256}" y="{h-63}" font-family="{FONT}" font-size="18" fill="{GREY}">促销折月</text>'
    return s + '</svg>'

def sales_chart():
    rows = sorted(DATA['sales'], key=lambda x: x['amount'], reverse=True)
    w, h = 1600, 1120
    s = frame(w, h, '销售员：基线月均与促销折月', '按促销额降序；折月按所属区域窗口折算 30 天')
    x0, y0, pw, row_h = 360, 170, 1130, 100
    maxv = 18000
    for i in range(0, 6):
        x = x0 + pw * i / 5
        s += f'<line x1="{x:.1f}" y1="{y0}" x2="{x:.1f}" y2="{y0+row_h*len(rows)}" stroke="#E6ECF3" stroke-width="1"/>'
        tick = '' if i == 0 else f'{maxv*i/5/10000:.1f}万'
        s += f'<text x="{x:.1f}" y="{y0-12}" text-anchor="middle" font-family="{FONT}" font-size="17" fill="{GREY}">{tick}</text>'
    for i, row in enumerate(rows):
        y = y0 + i * row_h
        base = row['baseline_monthly']; promo = row['promo_monthly']
        s += f'<text x="{x0-22}" y="{y+30}" text-anchor="end" font-family="{FONT}" font-size="21" font-weight="700" fill="#1F2937">{row["sales"]}</text>'
        s += f'<text x="{x0-22}" y="{y+56}" text-anchor="end" font-family="{FONT}" font-size="16" fill="{GREY}">{row["region"]} · {row["orders"]} 单</text>'
        wb = pw * base / maxv; wp = pw * promo / maxv
        s += f'<rect x="{x0}" y="{y+12}" width="{wb:.1f}" height="25" rx="4" fill="#B8CCE4"/>'
        s += f'<rect x="{x0}" y="{y+45}" width="{wp:.1f}" height="25" rx="4" fill="{NAVY}"/>'
        s += f'<text x="{x0+max(wb,wp)+12:.1f}" y="{y+31}" font-family="{FONT}" font-size="17" fill="#456">{yuan(base)}</text>'
        s += f'<text x="{x0+max(wb,wp)+12:.1f}" y="{y+64}" font-family="{FONT}" font-size="17" font-weight="700" fill="{NAVY}">{yuan(promo)}  ({row["growth"]*100:+.1f}%)</text>'
    s += f'<rect x="{x0}" y="{h-58}" width="26" height="18" fill="#B8CCE4"/><text x="{x0+36}" y="{h-43}" font-family="{FONT}" font-size="18" fill="{GREY}">4–9 月月均</text>'
    s += f'<rect x="{x0+220}" y="{h-58}" width="26" height="18" fill="{NAVY}"/><text x="{x0+256}" y="{h-43}" font-family="{FONT}" font-size="18" fill="{GREY}">促销折月</text>'
    return s + '</svg>'

def tier_chart():
    order = ['未达标', '1K', '2K', '5K', '1W']
    vals = []
    for t in order:
        n = sum(1 for x in DATA['groups'] if x['tier'] == t)
        vals.append(n)
    w, h = 1600, 820
    s = frame(w, h, '课题组档位分布：35 个达档，29 个未达 1,000 元', '按客户×课题组为归集实体；取最高档，赠品按现有促销统计口径')
    x0, y0, pw, ph = 130, 160, 1320, 500
    maxv = 35
    for i in range(0, 8):
        y = y0 + ph - ph * i / 7
        s += f'<line x1="{x0}" y1="{y:.1f}" x2="{x0+pw}" y2="{y:.1f}" stroke="#E6ECF3" stroke-width="1"/>'
        s += f'<text x="{x0-14}" y="{y+6:.1f}" text-anchor="end" font-family="{FONT}" font-size="17" fill="{GREY}">{int(maxv*i/7)}</text>'
    bw = 150
    gap = (pw - bw * len(order)) / (len(order) + 1)
    colors = ['#C9D3DF', '#9BB7D4', '#5B8DB8', NAVY, TEAL]
    for i, (t, v) in enumerate(zip(order, vals)):
        bh = ph * v / maxv
        x = x0 + gap + i * (bw + gap)
        y = y0 + ph - bh
        s += f'<rect x="{x:.1f}" y="{y:.1f}" width="{bw}" height="{bh:.1f}" rx="5" fill="{colors[i]}"/>'
        s += f'<text x="{x+bw/2:.1f}" y="{y-14:.1f}" text-anchor="middle" font-family="{FONT}" font-size="26" font-weight="700" fill="{NAVY}">{v}</text>'
        s += f'<text x="{x+bw/2:.1f}" y="{y0+ph+38}" text-anchor="middle" font-family="{FONT}" font-size="22" fill="#1F2937">{t}</text>'
        s += f'<text x="{x+bw/2:.1f}" y="{y0+ph+66}" text-anchor="middle" font-family="{FONT}" font-size="16" fill="{GREY}">个课题组</text>'
    s += f'<text x="60" y="{h-30}" font-family="{FONT}" font-size="16" fill="{GREY}">注：1K=1,000 元，2K=2,000 元，5K=5,000 元，1W=10,000 元；未达标不含测试单、赠品行。</text>'
    return s + '</svg>'

def render(name, svg, h):
    html = f'''<!doctype html><html><head><meta charset="utf-8"><style>html,body{{margin:0;padding:0;background:#fff}}svg{{display:block}}</style></head><body>{svg}</body></html>'''
    hp = OUT / f'{name}.html'
    hp.write_text(html, encoding='utf-8')
    png = OUT / f'{name}.png'
    cmd = ['/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '--headless', '--disable-gpu',
           '--hide-scrollbars', f'--window-size=1600,{h}', f'--screenshot={png}', f'file://{hp}']
    subprocess.run(cmd, check=False, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=60)
    print(png, png.stat().st_size if png.exists() else 'MISSING')

if __name__ == '__main__':
    render('01_月度趋势', monthly_chart(), 900)
    render('02_区域对比', region_chart(), 820)
    render('03_销售员对比', sales_chart(), 1120)
    render('04_课题组档位', tier_chart(), 820)
