"""데모 픽스처 생성: 실제 LLM로 extract → 자동매핑 → generate → export 5종을 1회 실행해 저장.

데모 모드(헤더 토글)에서 /extract, /generate, /export 가 이 결과를 즉시 반환한다.
"""
from __future__ import annotations

import base64
import json
import shutil
from pathlib import Path

from app.config import BACKEND_ROOT, settings
from app.export.adapters import pptx_adapter
from app.export.harness import SUPPORTED, export_report
from app.services import pipeline

FIX = BACKEND_ROOT / "demo_fixtures"
FIX.mkdir(exist_ok=True)
SAMPLE = (BACKEND_ROOT / ".." / ".." / "sample" / "report_sample.png").resolve()
FUND = "069500"
DATASET = "kodex_etf_demo"
NARR = "etf_narrative_factors"
NARR_COLS = ["performance_summary", "market_context", "risk_factors", "defensive_factors", "outlook_points"]

FIELD_KEY_MAP = {
    "base_date": ("etf_master", "base_date"),
    "department": ("etf_master", "department"),
    "email": ("etf_master", "contact_email"),
    "contact_email": ("etf_master", "contact_email"),
    "text": ("etf_master", "report_title"),
    "title": ("etf_master", "report_title"),
    "report_title": ("etf_master", "report_title"),
}
COLLECTION_BY_TYPE = {
    "line_chart": ("etf_performance", "period_order", "asc", None),
    "bar_chart": ("etf_performance", "period_order", "asc", None),
    "metric_table": ("etf_performance", "period_order", "asc", None),
    "holdings_table": ("etf_holdings_top10", "weight", "desc", 10),
    "table": ("etf_holdings_top10", "weight", "desc", 10),
}
PERF_SERIES = ["etf_return", "benchmark_return"]
HOLD_ROLE_COL = {"index": None, "name": "holding_name", "value": "weight"}


def auto_col_for_role(table, role, series_idx):
    if table == "etf_performance":
        if role == "x":
            return "period"
        if role == "series":
            return PERF_SERIES[series_idx] if series_idx < len(PERF_SERIES) else PERF_SERIES[0]
    if table == "etf_holdings_top10":
        return HOLD_ROLE_COL.get(role)
    return None


def auto_map(ir: dict) -> dict:
    for comp in ir["report"]["components"]:
        spec = comp.get("dataSpec", {})
        for f in spec.get("fields", []) or []:
            if f.get("binding"):
                continue
            key = f.get("key")
            if f.get("role") == "narrative_input" or f.get("dataType") == "text":
                refs = ([{"table": NARR, "column": key}] if key in NARR_COLS
                        else [{"table": NARR, "column": c} for c in NARR_COLS])
                f["binding"] = {"source": "columns", "refs": refs}
            elif key in FIELD_KEY_MAP:
                t, c = FIELD_KEY_MAP[key]
                f["binding"] = {"source": "column", "table": t, "column": c}
            else:
                f["binding"] = {"source": "manual", "value": f.get("label", "")}
        col = spec.get("collection")
        if col and col.get("enabled"):
            cfg = COLLECTION_BY_TYPE.get(comp["type"])
            if cfg:
                table, order_by, order_dir, limit = cfg
                col["datasetId"] = DATASET
                col["table"] = table
                col["orderBy"] = col.get("orderBy") or order_by
                col["orderDir"] = col.get("orderDir") or order_dir
                if col.get("limit") is None:
                    col["limit"] = limit
                series_idx = 0
                for c in col.get("columns", []):
                    if not c.get("column"):
                        c["column"] = auto_col_for_role(table, c.get("role"), series_idx)
                    if c.get("role") == "series":
                        series_idx += 1
    return ir


def main():
    img = SAMPLE.read_bytes()
    b64 = base64.b64encode(img).decode()

    print("extract (real LLM)…")
    extract_res = pipeline.run_extract(b64, "image/png")
    (FIX / "extract.json").write_text(json.dumps(extract_res, ensure_ascii=False, indent=2), encoding="utf-8")
    print("  components:", len(extract_res["ir"]["report"]["components"]))

    mapped = auto_map(json.loads(json.dumps(extract_res["ir"])))

    print("generate (real LLM)…")
    gen_res = pipeline.run_generate(mapped, FUND)
    (FIX / "generate.json").write_text(json.dumps(gen_res, ensure_ascii=False, indent=2), encoding="utf-8")
    print("  components:", len(gen_res["view"].get("components", [])))

    vm = gen_res["view"]
    sample_url = "data:image/png;base64," + b64

    print("preview (LLM HTML, page = sample as reference + background)…")
    from app.services.render_llm import render_pages_html_llm

    preview_html, _ = render_pages_html_llm(
        [{"view": vm, "referenceImageDataUrl": sample_url, "backgroundImageDataUrl": sample_url}]
    )
    (FIX / "preview.html").write_text(preview_html, encoding="utf-8")
    print(f"  preview.html ({len(preview_html)} bytes)")

    print("export 5 formats (LLM-unified)…")
    pptx_adapter.BUILDER_CACHE.unlink(missing_ok=True)
    manifest = {}
    for fmt in SUPPORTED:
        r = export_report(fmt, vm, reference_image_data_url=sample_url, background_image_data_url=sample_url)
        dest = FIX / f"report.{fmt}"
        shutil.copy(r["path"], dest)
        manifest[fmt] = dest.name
        print(f"  {fmt}: {dest.name} ({dest.stat().st_size} bytes)")
    (FIX / "exports.json").write_text(json.dumps(manifest, ensure_ascii=False, indent=2), encoding="utf-8")
    print("DONE → demo_fixtures/")


if __name__ == "__main__":
    main()
