#!/usr/bin/env python3
# Generates docs/4plus1/diagrams/scenarios-view.svg per fireworks-tech-graph 4+1 baseline rules.
lines = []
W, H = 1280, 640
lines.append('<?xml version="1.0" encoding="UTF-8"?>')
lines.append(f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {W} {H}" width="{W}" height="{H}" font-family="Segoe UI, Arial, sans-serif" font-size="13">')
lines.append('<title>Scenarios View (baseline, UML Use Case)</title>')
lines.append(f'<rect x="0" y="0" width="{W}" height="{H}" fill="#ffffff"/>')
lines.append(f'<rect x="0" y="0" width="{W}" height="60" fill="#f1f5f9"/>')
lines.append(f'<text x="40" y="36" font-size="20" font-weight="700" fill="#0f172a">Scenarios View — S1~S5 关键用例 (baseline, UML Use Case)</text>')
lines.append(f'<text x="40" y="52" font-size="11" fill="#64748b">2 actors (Developer / Reviewer) · 5 use-case ellipses · «covers» 列出每场景跨越的元素</text>')
lines.append('<defs><marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" fill="#2563eb"/></marker>')
lines.append('<marker id="arrowAmber" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" fill="#d97706"/></marker></defs>')

# System boundary (dashed rect, centered)
sb_x, sb_y, sb_w, sb_h = 380, 90, 540, 470
lines.append(f'<rect x="{sb_x}" y="{sb_y}" width="{sb_w}" height="{sb_h}" fill="none" stroke="#1e40af" stroke-width="2" stroke-dasharray="6 6" rx="12"/>')
lines.append(f'<text x="{sb_x+14}" y="{sb_y+24}" font-size="12" font-weight="700" fill="#1e40af">System Boundary · HarnessToolKit</text>')

# Actors: Developer (left), Reviewer (right)
# Developer stick-figure (left)
ax_dev = 200; ay_dev = 280
lines.append(f'<circle cx="{ax_dev}" cy="{ay_dev-50}" r="14" fill="#fef3c7" stroke="#92400e" stroke-width="1.8"/>')
lines.append(f'<line x1="{ax_dev}" y1="{ay_dev-36}" x2="{ax_dev}" y2="{ay_dev+10}" stroke="#92400e" stroke-width="1.8"/>')
lines.append(f'<line x1="{ax_dev}" y1="{ay_dev-20}" x2="{ax_dev-22}" y2="{ay_dev}" stroke="#92400e" stroke-width="1.8"/>')
lines.append(f'<line x1="{ax_dev}" y1="{ay_dev-20}" x2="{ax_dev+22}" y2="{ay_dev}" stroke="#92400e" stroke-width="1.8"/>')
lines.append(f'<line x1="{ax_dev}" y1="{ay_dev+10}" x2="{ax_dev-18}" y2="{ay_dev+40}" stroke="#92400e" stroke-width="1.8"/>')
lines.append(f'<line x1="{ax_dev}" y1="{ay_dev+10}" x2="{ax_dev+18}" y2="{ay_dev+40}" stroke="#92400e" stroke-width="1.8"/>')
lines.append(f'<text x="{ax_dev}" y="{ay_dev+62}" text-anchor="middle" font-size="13" font-weight="700" fill="#0f172a">Developer</text>')
lines.append(f'<text x="{ax_dev}" y="{ay_dev+78}" text-anchor="middle" font-size="10" fill="#64748b">E-020 · IDE 用户</text>')

# Reviewer stick-figure (right)
ax_rev = 1100; ay_rev = 180
lines.append(f'<circle cx="{ax_rev}" cy="{ay_rev-50}" r="14" fill="#f5d0fe" stroke="#5b21b6" stroke-width="1.8"/>')
lines.append(f'<line x1="{ax_rev}" y1="{ay_rev-36}" x2="{ax_rev}" y2="{ay_rev+10}" stroke="#5b21b6" stroke-width="1.8"/>')
lines.append(f'<line x1="{ax_rev}" y1="{ay_rev-20}" x2="{ax_rev-22}" y2="{ay_rev}" stroke="#5b21b6" stroke-width="1.8"/>')
lines.append(f'<line x1="{ax_rev}" y1="{ay_rev-20}" x2="{ax_rev+22}" y2="{ay_rev}" stroke="#5b21b6" stroke-width="1.8"/>')
lines.append(f'<line x1="{ax_rev}" y1="{ay_rev+10}" x2="{ax_rev-18}" y2="{ay_rev+40}" stroke="#5b21b6" stroke-width="1.8"/>')
lines.append(f'<line x1="{ax_rev}" y1="{ay_rev+10}" x2="{ax_rev+18}" y2="{ay_rev+40}" stroke="#5b21b6" stroke-width="1.8"/>')
lines.append(f'<text x="{ax_rev}" y="{ay_rev+62}" text-anchor="middle" font-size="13" font-weight="700" fill="#0f172a">Reviewer</text>')
lines.append(f'<text x="{ax_rev}" y="{ay_rev+78}" text-anchor="middle" font-size="10" fill="#64748b">E-021 · 人工裁决</text>')

# Use cases (5 ellipses inside boundary)
# cx fixed at center of boundary
uc_cx = sb_x + sb_w//2  # 380+270 = 650
uc_rx, uc_ry = 170, 38
uc_data = [
    ("S1", "项目初始化",            "covers: E-012, E-001, E-014, E-004", 140),
    ("S2", "编辑触发门祡",          "covers: E-020, E-004, E-003", 220),
    ("S3", "9-step 流水线",         "covers: E-009, E-021, E-003, E-004, E-011", 300),
    ("S4", "Skill 镜像更新",        "covers: E-014, E-012", 380),
    ("S5", "Spec 编译为规则",       "covers: E-017, E-004", 460),
]
uc_centers = []
for sid, name, cov, cy in uc_data:
    lines.append(f'<ellipse cx="{uc_cx}" cy="{cy}" rx="{uc_rx}" ry="{uc_ry}" fill="#ffffff" stroke="#2563eb" stroke-width="1.8"/>')
    lines.append(f'<text x="{uc_cx}" y="{cy-3}" text-anchor="middle" font-size="14" font-weight="700" fill="#0f172a">{sid}·{name}</text>')
    lines.append(f'<text x="{uc_cx}" y="{cy+14}" text-anchor="middle" font-size="9" fill="#64748b">{cov}</text>')
    uc_centers.append((uc_cx, cy, sid))

def edge(x1, y1, x2, y2, label="", color="#2563eb", dash=None, marker="arrow"):
    d = f' stroke-dasharray="{dash}"' if dash else ''
    lines.append(f'<path d="M {x1},{y1} L {x2},{y2}" fill="none" stroke="{color}" stroke-width="1.5"{d} marker-end="url(#{marker})"/>')
    if label:
        mx, my = (x1+x2)/2, (y1+y2)/2
        lines.append(f'<rect x="{mx-len(label)*3-2}" y="{my-8}" width="{len(label)*6+4}" height="14" fill="#ffffff" opacity="0.9"/>')
        lines.append(f'<text x="{mx}" y="{my+2}" text-anchor="middle" font-size="9" fill="{"#5b21b6" if color=="#7c3aed" else "#1e40af"}">{label}</text>')

# Actor -> use-case arrows
dev_right_x = ax_dev + 22  # right hand
rev_left_x  = ax_rev - 22  # left hand
for _, cy in [(uc_centers[0][1], uc_centers[0]), (uc_centers[1][1], uc_centers[1]), (uc_centers[2][1], uc_centers[2]), (uc_centers[3][1], uc_centers[3]), (uc_centers[4][1], uc_centers[4])]:
    pass

# Each use case gets an arrow from Developer; S3 also gets one from Reviewer
for ucx, ucy, sid in uc_centers:
    edge(dev_right_x, ay_dev, ucx - uc_rx, ucy, f"«triggers»", color="#2563eb")

# Reviewer -> S3 (HITL)
s3_cy = uc_centers[2][1]
edge(rev_left_x, ay_rev, uc_cx + uc_rx, s3_cy, "«HITL 放行/拒绝»", color="#7c3aed", marker="arrowAmber")

# <<include>> arrows between use cases (optional small ones) — S3 includes S2 (pipeline triggers gate)
edge(uc_cx - 30, uc_centers[2][1] - uc_ry, uc_cx - 30, uc_centers[1][1] + uc_ry, "«include»", color="#6b7280", dash="3,2")

# Legend on right side
lx, ly = 1000, 320
lines.append(f'<rect x="{lx}" y="{ly}" width="240" height="120" fill="#f8fafc" stroke="#cbd5e1" rx="6"/>')
lines.append(f'<text x="{lx+12}" y="{ly+18}" font-size="11" font-weight="700" fill="#475569">图例</text>')
lines.append(f'<line x1="{lx+14}" y1="{ly+38}" x2="{lx+54}" y2="{ly+38}" stroke="#2563eb" stroke-width="1.5" marker-end="url(#arrow)"/>')
lines.append(f'<text x="{lx+60}" y="{ly+42}" font-size="10" fill="#0f172a">«triggers» 主体</text>')
lines.append(f'<line x1="{lx+14}" y1="{ly+58}" x2="{lx+54}" y2="{ly+58}" stroke="#7c3aed" stroke-width="1.5" marker-end="url(#arrowAmber)"/>')
lines.append(f'<text x="{lx+60}" y="{ly+62}" font-size="10" fill="#0f172a">«HITL» 评审放行</text>')
lines.append(f'<line x1="{lx+14}" y1="{ly+78}" x2="{lx+54}" y2="{ly+78}" stroke="#6b7280" stroke-width="1.5" stroke-dasharray="3 2" marker-end="url(#arrow)"/>')
lines.append(f'<text x="{lx+60}" y="{ly+82}" font-size="10" fill="#0f172a">«include» 包含用例</text>')
lines.append(f'<text x="{lx+14}" y="{ly+102}" font-size="9" fill="#64748b">covers 列表标注场景跨域元素</text>')

# Coverage note bottom
lines.append(f'<rect x="40" y="570" width="{W-80}" height="22" fill="#fef3c7" fill-opacity="0.4" stroke="#92400e" rx="4"/>')
lines.append(f'<text x="50" y="586" font-size="10" fill="#7c2d12">cross-view 一致性:每场景 «covers» 列出的 E-0XX 元素均出现在 Logical/Development/Physical 至少一个视图中</text>')

# footer
lines.append(f'<rect x="0" y="{H-44}" width="{W}" height="44" fill="#f1f5f9" stroke="#cbd5e1"/>')
lines.append(f'<text x="40" y="{H-26}" font-size="11" fill="#0f172a">机器可校验源:scenarios-view.mmd + harness-toolkit-baseline.yaml</text>')
lines.append(f'<text x="40" y="{H-10}" font-size="10" fill="#64748b">本图按 per-view 裁剪策略产出，不代表完整关系集(详见 ADR-0018)</text>')
lines.append('</svg>')

out = 'docs/4plus1/diagrams/scenarios-view.svg'
with open(out, 'w', encoding='utf-8') as f:
    f.write('\n'.join(lines))
print(f"WROTE {out} ({len(lines)} lines)")
