"""파이프라인 실행 리포트 생성기.

data/runs/{run_id}/ 의 중간 산출물을 읽어
단계별 진행 과정을 한눈에 볼 수 있는 HTML 리포트를 생성한다.

사용법:
    python scripts/generate_run_report.py                   # 최신 run
    python scripts/generate_run_report.py 1774572796252     # 특정 run
"""
from __future__ import annotations

import json
import sys
from pathlib import Path

PROJECT_ROOT = Path(__file__).parent.parent
RUNS_DIR = PROJECT_ROOT / "data" / "runs"


def load_json(path: Path) -> dict | list | None:
    if not path.exists():
        return None
    with open(path, encoding="utf-8") as f:
        return json.load(f)


def load_text(path: Path) -> str | None:
    if not path.exists():
        return None
    return path.read_text(encoding="utf-8")


def generate_report(run_id: str) -> str:
    run_dir = RUNS_DIR / run_id

    if not run_dir.exists():
        return f"<html><body><h1>Run not found: {run_id}</h1></body></html>"

    # 데이터 로드
    step1 = load_json(run_dir / "step1_analysis.json")
    step1b = load_json(run_dir / "step1b_concepts.json")
    step2 = load_json(run_dir / "step2_layout.json")
    step2b = load_json(run_dir / "step2b_allocation.json")
    step3 = load_json(run_dir / "step3_filled_blocks.json")
    step4_css = load_json(run_dir / "step4_css_adjustment.json")
    step4_measure = load_json(run_dir / "step4_measurement_round1.json")
    step5 = load_json(run_dir / "step5_review_round1.json")
    final_html = load_text(run_dir / "final.html")

    html = f"""<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>파이프라인 리포트 — Run {run_id}</title>
<style>
@import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css');
* {{ margin:0; padding:0; box-sizing:border-box; }}
body {{ font-family:'Pretendard Variable',sans-serif; background:#f1f5f9; color:#1e293b; line-height:1.7; }}
.container {{ max-width:1200px; margin:0 auto; padding:40px 20px; }}
h1 {{ font-size:28px; font-weight:900; margin-bottom:8px; }}
.run-id {{ font-size:14px; color:#64748b; margin-bottom:40px; }}
.step {{ background:#fff; border-radius:12px; padding:28px 32px; margin-bottom:24px; box-shadow:0 1px 3px rgba(0,0,0,0.08); }}
.step-header {{ display:flex; align-items:center; gap:14px; margin-bottom:16px; }}
.step-badge {{ background:#2563eb; color:#fff; font-size:13px; font-weight:700; padding:4px 14px; border-radius:20px; white-space:nowrap; }}
.step-badge.code {{ background:#16a34a; }}
.step-badge.sonnet {{ background:#f59e0b; color:#1e293b; }}
.step-title {{ font-size:20px; font-weight:800; }}
.step-desc {{ font-size:14px; color:#64748b; margin-bottom:16px; }}
table {{ border-collapse:collapse; width:100%; margin:12px 0; }}
th {{ background:#1e293b; color:#fff; padding:10px 14px; text-align:left; font-size:13px; font-weight:700; }}
td {{ padding:8px 14px; border-bottom:1px solid #e2e8f0; font-size:13px; vertical-align:top; }}
tr:nth-child(even) td {{ background:#f8fafc; }}
.json-block {{ background:#f8fafc; border:1px solid #e2e8f0; border-radius:8px; padding:16px; font-family:'Consolas',monospace; font-size:12px; white-space:pre-wrap; word-break:break-all; max-height:400px; overflow-y:auto; }}
.tag {{ display:inline-block; padding:2px 10px; border-radius:12px; font-size:11px; font-weight:700; margin:2px; }}
.tag-purpose {{ background:#dbeafe; color:#1e40af; }}
.tag-role {{ background:#f0fdf4; color:#166534; }}
.tag-layer {{ background:#fef3c7; color:#92400e; }}
.tag-relation {{ background:#fce7f3; color:#9d174d; }}
.tag-area {{ background:#e0e7ff; color:#3730a3; }}
.tag-type {{ background:#f1f5f9; color:#334155; border:1px solid #cbd5e1; }}
.arrow {{ text-align:center; font-size:28px; color:#94a3b8; padding:8px 0; }}
.highlight {{ background:#fef9c3; padding:2px 6px; border-radius:4px; }}
.warn {{ color:#dc2626; font-weight:700; }}
.ok {{ color:#16a34a; font-weight:700; }}
.weight-bar {{ height:20px; border-radius:4px; display:inline-block; vertical-align:middle; }}
.final-preview {{ border:2px solid #2563eb; border-radius:12px; overflow:hidden; margin-top:16px; }}
.final-preview iframe {{ width:1280px; height:720px; border:none; transform-origin:top left; }}
.overflow-row {{ background:#fef2f2 !important; }}
</style>
</head>
<body>
<div class="container">
<h1>Design Agent 파이프라인 리포트</h1>
<div class="run-id">Run ID: {run_id} | 생성: {_ts_to_str(run_id)}</div>
"""

    # ── Step 1A ──
    if step1:
        topics = step1.get("topics", [])
        page_struct = step1.get("page_structure", {})
        html += f"""
<div class="step">
    <div class="step-header">
        <span class="step-badge">Kei 실장</span>
        <span class="step-title">Step 1A: 꼭지 추출 + 스토리라인 설계</span>
    </div>
    <div class="step-desc">원본 콘텐츠를 분석하여 핵심 메시지, 꼭지 구조, 페이지 비중을 설계한다.</div>

    <table>
        <tr><th>항목</th><th>값</th></tr>
        <tr><td>제목</td><td><strong>{step1.get('title','')}</strong></td></tr>
        <tr><td>핵심 메시지</td><td class="highlight">{step1.get('core_message','')}</td></tr>
        <tr><td>정보 구조</td><td>{step1.get('info_structure','')[:200]}</td></tr>
    </table>

    <h3 style="margin:16px 0 8px; font-size:15px;">페이지 구조 (비중)</h3>
    <table>
        <tr><th>역할</th><th>topic_ids</th><th>비중(weight)</th><th>시각화</th></tr>
"""
        colors = {"본심": "#2563eb", "배경": "#64748b", "첨부": "#f59e0b", "결론": "#16a34a"}
        for role, info in page_struct.items():
            if isinstance(info, dict):
                w = info.get("weight", 0)
                tids = info.get("topic_ids", [])
                c = colors.get(role, "#94a3b8")
                bar_w = int(w * 400)
                html += f'<tr><td><strong>{role}</strong></td><td>{tids}</td><td>{w:.0%}</td>'
                html += f'<td><span class="weight-bar" style="width:{bar_w}px; background:{c};"></span></td></tr>\n'
        html += "</table>\n"

        html += """<h3 style="margin:16px 0 8px; font-size:15px;">꼭지 목록</h3>
    <table>
        <tr><th>#</th><th>제목</th><th>purpose</th><th>role</th><th>layer</th><th>section_title</th></tr>
"""
        for t in topics:
            st = t.get("section_title", "")
            html += f"""<tr>
    <td>{t.get('id','')}</td>
    <td>{t.get('title','')}</td>
    <td><span class="tag tag-purpose">{t.get('purpose','')}</span></td>
    <td><span class="tag tag-role">{t.get('role','')}</span></td>
    <td><span class="tag tag-layer">{t.get('layer','')}</span></td>
    <td>{st if st else '-'}</td>
</tr>\n"""
        html += "</table></div>\n"

    html += '<div class="arrow">▼</div>\n'

    # ── Step 1B ──
    if step1b:
        concepts = step1b.get("concepts", [])
        html += f"""
<div class="step">
    <div class="step-header">
        <span class="step-badge">Kei 실장</span>
        <span class="step-title">Step 1B: 컨셉 구체화</span>
    </div>
    <div class="step-desc">각 꼭지의 관계 성격(relation_type), 표현 힌트(expression_hint), 원본 데이터를 구체화한다.</div>

    <table>
        <tr><th>#</th><th>제목</th><th>relation_type</th><th>expression_hint</th><th>source_data</th></tr>
"""
        for c in concepts:
            tid = c.get("topic_id") or c.get("id", "?")
            html += f"""<tr>
    <td>{tid}</td>
    <td>{c.get('title','')}</td>
    <td><span class="tag tag-relation">{c.get('relation_type','')}</span></td>
    <td style="max-width:300px">{c.get('expression_hint','')[:120]}</td>
    <td style="max-width:300px">{c.get('source_data','')[:120]}</td>
</tr>\n"""
        html += "</table></div>\n"

    html += '<div class="arrow">▼</div>\n'

    # ── Step 2 ──
    if step2:
        blocks = step2.get("blocks", [])
        overflows = step2.get("overflow", [])
        html += f"""
<div class="step">
    <div class="step-header">
        <span class="step-badge">Kei 실장</span>
        <span class="step-title">Step 2 (A-2 + B): 블록 배치</span>
    </div>
    <div class="step-desc">
        <strong>Step A:</strong> 규칙 기반 프리셋 선택<br>
        <strong>Step A-2 (Kei):</strong> 각 꼭지에 적합한 블록 확정 (코드 레벨 강제)<br>
        <strong>Step B (Sonnet):</strong> zone 배치 + char_guide만 결정 (블록 타입 변경 불가)
    </div>

    <p><strong>프리셋:</strong> <code>{step2.get('preset','')}</code></p>

    <table>
        <tr><th>area</th><th>블록 타입</th><th>purpose</th><th>topic</th><th>이유</th><th>크기</th></tr>
"""
        for b in blocks:
            html += f"""<tr>
    <td><span class="tag tag-area">{b.get('area','')}</span></td>
    <td><span class="tag tag-type">{b.get('type','')}</span></td>
    <td><span class="tag tag-purpose">{b.get('purpose','')}</span></td>
    <td>{b.get('topic_id','')}</td>
    <td style="max-width:300px">{b.get('reason','')[:100]}</td>
    <td>{b.get('size','')}</td>
</tr>\n"""
        html += "</table>\n"

        if overflows:
            html += '<h3 style="margin:16px 0 8px; font-size:15px; color:#dc2626;">높이 초과 예상</h3>\n<table>\n'
            html += '<tr><th>zone</th><th>예산(px)</th><th>합계(px)</th><th>초과(px)</th></tr>\n'
            for o in overflows:
                html += f'<tr class="overflow-row"><td>{o.get("area","")}</td><td>{o.get("budget_px","")}</td><td>{o.get("total_px","")}</td><td class="warn">+{o.get("overflow_px","")}</td></tr>\n'
            html += "</table>\n"
        html += "</div>\n"

    html += '<div class="arrow">▼</div>\n'

    # ── Step 2B (Allocation) ──
    if step2b:
        html += f"""
<div class="step">
    <div class="step-header">
        <span class="step-badge code">코드 (결정론적)</span>
        <span class="step-title">Step 2B: 공간 할당</span>
    </div>
    <div class="step-desc">Kei의 비중(weight)을 기반으로 각 zone 내 블록별 max_height_px와 max_chars를 수학적으로 계산한다.</div>
    <div class="json-block">{json.dumps(step2b, ensure_ascii=False, indent=2)}</div>
</div>
"""
    html += '<div class="arrow">▼</div>\n'

    # ── Step 3 ──
    if step3:
        filled = step3.get("blocks", [])
        html += f"""
<div class="step">
    <div class="step-header">
        <span class="step-badge">Kei 편집자</span>
        <span class="step-title">Step 3: 텍스트 편집</span>
    </div>
    <div class="step-desc">원본 콘텐츠에서 각 블록의 슬롯에 맞는 텍스트를 추출/편집한다. 원본 보존 원칙.</div>

    <table>
        <tr><th>area</th><th>블록 타입</th><th>topic</th><th>글자 수</th><th>데이터 (요약)</th></tr>
"""
        for b in filled:
            data_str = json.dumps(b.get("data", {}), ensure_ascii=False)
            preview = data_str[:200] + ("..." if len(data_str) > 200 else "")
            html += f"""<tr>
    <td><span class="tag tag-area">{b.get('area','')}</span></td>
    <td><span class="tag tag-type">{b.get('type','')}</span></td>
    <td>{b.get('topic_id','')}</td>
    <td>{b.get('char_count','')}</td>
    <td style="max-width:400px; font-size:12px; word-break:break-all;">{preview}</td>
</tr>\n"""
        html += "</table></div>\n"

    html += '<div class="arrow">▼</div>\n'

    # ── Step 4 (CSS + Measurement) ──
    html += f"""
<div class="step">
    <div class="step-header">
        <span class="step-badge sonnet">Sonnet 실무자</span>
        <span class="step-title">Step 4: CSS 조정 + 렌더링</span>
    </div>
    <div class="step-desc">텍스트 양에 맞게 CSS 변수(폰트, 여백)를 조정하고 Jinja2로 HTML을 조립한다.</div>
"""
    if step4_css:
        html += f'<div class="json-block">{json.dumps(step4_css, ensure_ascii=False, indent=2)}</div>\n'

    if step4_measure:
        slide = step4_measure.get("slide", {})
        zones = step4_measure.get("zones", {})
        slide_status = '<span class="ok">OK</span>' if not slide.get("overflowed") else f'<span class="warn">+{slide.get("excess_px",0)}px 초과</span>'

        html += f"""
    <h3 style="margin:16px 0 8px; font-size:15px;">Phase L: Selenium 렌더링 측정</h3>
    <p>슬라이드 전체: {slide.get('scrollHeight','?')}px / {slide.get('clientHeight','?')}px — {slide_status}</p>
    <table>
        <tr><th>zone</th><th>scrollHeight</th><th>clientHeight</th><th>상태</th><th>블록 상세</th></tr>
"""
        for zn, zd in zones.items():
            z_status = '<span class="ok">OK</span>' if not zd.get("overflowed") else f'<span class="warn">+{zd.get("excess_px",0)}px</span>'
            block_details = ", ".join(
                f'{bl.get("block_type","?")}:{bl.get("scrollHeight","?")}px'
                for bl in zd.get("blocks", [])
            )
            html += f'<tr><td>{zn}</td><td>{zd.get("scrollHeight","")}</td><td>{zd.get("clientHeight","")}</td><td>{z_status}</td><td style="font-size:12px">{block_details}</td></tr>\n'
        html += "</table>\n"
    html += "</div>\n"

    html += '<div class="arrow">▼</div>\n'

    # ── Step 5 ──
    if step5:
        needs = step5.get("needs_adjustment", False)
        issues = step5.get("issues", [])
        adjs = step5.get("adjustments", [])
        html += f"""
<div class="step">
    <div class="step-header">
        <span class="step-badge">Kei 실장</span>
        <span class="step-title">Step 5: 최종 검수</span>
    </div>
    <div class="step-desc">렌더링 결과를 Kei가 검수. overflow 없으면 skip.</div>
    <p><strong>조정 필요:</strong> {'<span class="warn">예</span>' if needs else '<span class="ok">아니오</span>'}</p>
"""
        if issues:
            html += '<h4>이슈:</h4><ul>\n'
            for iss in issues:
                html += f'<li>{iss}</li>\n'
            html += '</ul>\n'
        if adjs:
            html += '<h4>조정 사항:</h4>\n<table><tr><th>area</th><th>action</th><th>detail</th></tr>\n'
            for adj in adjs:
                html += f'<tr><td>{adj.get("block_area","")}</td><td>{adj.get("action","")}</td><td>{adj.get("detail","")[:100]}</td></tr>\n'
            html += '</table>\n'
        html += "</div>\n"
    else:
        html += """
<div class="step">
    <div class="step-header">
        <span class="step-badge">Kei 실장</span>
        <span class="step-title">Step 5: 최종 검수</span>
    </div>
    <div class="step-desc"><span class="ok">Skip — overflow 없음.</span></div>
</div>
"""

    html += '<div class="arrow">▼</div>\n'

    # ── Final ──
    if final_html:
        # iframe으로 최종 결과물 미리보기
        import html as html_lib
        escaped = html_lib.escape(final_html)
        html += f"""
<div class="step">
    <div class="step-header">
        <span class="step-badge code">최종 결과</span>
        <span class="step-title">완성 슬라이드</span>
    </div>
    <div class="final-preview">
        <iframe srcdoc="{escaped}" style="transform:scale(0.85); width:1280px; height:720px;"></iframe>
    </div>
</div>
"""

    html += """
</div>
</body>
</html>"""
    return html


def _ts_to_str(run_id: str) -> str:
    try:
        from datetime import datetime
        ts = int(run_id) / 1000
        return datetime.fromtimestamp(ts).strftime("%Y-%m-%d %H:%M:%S")
    except Exception:
        return run_id


def main():
    if len(sys.argv) > 1:
        run_id = sys.argv[1]
    else:
        # 최신 run 자동 선택
        runs = sorted(RUNS_DIR.iterdir(), key=lambda p: p.name, reverse=True)
        if not runs:
            print("data/runs/ 에 실행 결과가 없습니다.")
            sys.exit(1)
        run_id = runs[0].name

    print(f"리포트 생성: run={run_id}")
    report = generate_report(run_id)

    output_path = RUNS_DIR / run_id / "report.html"
    output_path.write_text(report, encoding="utf-8")
    print(f"저장: {output_path}")
    print(f"브라우저에서 열기: file:///{output_path}")


if __name__ == "__main__":
    main()
