"""task-3070 B-3: **프로덕션 충실도** 프롬프트로 claude -p 를 N회 실호출.

짧은 프롬프트(4,098자)로는 BASE 도 마커 10/10 이 나왔다 — 재현되지 않는다.
프로덕션은 (a) naver-blog 채널 프롬프트, (b) 금소법 체크리스트, (c) 스킬,
(d) 설계사 프로필을 함께 넣는다. 특히 (a) 는 "소제목(■ 또는 ▶ 기호 사용,
## 마크다운 아님)" 으로 `##` 사용을 명시 금지한다 — 마커와 정면 충돌.

사용: python3 realcall_prod.py <server_dir> <label> <reps> <model>[,<model>...]
"""
import importlib.util, inspect, json, os, re, subprocess, sys, time
from concurrent.futures import ThreadPoolExecutor

SERVER_DIR = os.path.abspath(sys.argv[1]); LABEL = sys.argv[2]
REPS = int(sys.argv[3]); MODELS = sys.argv[4].split(",")
HERE = os.path.dirname(os.path.abspath(__file__))

sys.path.insert(0, SERVER_DIR)
spec = importlib.util.spec_from_file_location("bm_main", os.path.join(SERVER_DIR, "main.py"))
main = importlib.util.module_from_spec(spec); sys.modules["bm_main"] = main
spec.loader.exec_module(main)

ROW = json.load(open(os.path.join(HERE, "benchmark_fixture.json")))[0]
CHANNEL_PROMPT = open(os.path.join(HERE, "channel_prompt.txt")).read()
FCPA = json.load(open(os.path.join(HERE, "fcpa.json")))

# 서버 금소법 프롬프트 조립 재현(full 레벨 = 전체 체크리스트)
_lines = [f"- [{i.get('category','')}] {i.get('content', i.get('text',''))}"
          for i in FCPA if isinstance(i, dict)]
COMPLIANCE = "[금융소비자보호법 준수 규정]\n" + "\n".join(_lines)
PROFILE = ("[설계사 프로필 정보]\n소속: OO생명 · 직함: 재무설계사\n"
           "[콘텐츠 하단에 반드시 포함할 문구]\n"
           "※ 본 게시물은 광고이며, 보험계약 체결 전 상품설명서 및 약관을 반드시 확인하시기 바랍니다.\n"
           "※ 유료 광고 포함\n제0000-0000000-00호 | OO생명")

bm = main.BenchmarkGrounding(
    keyword=ROW["keyword"], url=ROW["url"], channel=ROW["channel"], rank=ROW["rank"],
    title=ROW["title"], bodyText=ROW["body_text"], sourceCharCount=ROW["char_count"],
    sourceImageCount=ROW["image_count"], sourceBodyKeywordCount=ROW["body_keyword_count"],
    charCount=ROW["char_count"], imageCount=ROW["image_count"],
    bodyKeywordCount=ROW["body_keyword_count"])

kwargs = dict(
    topic=ROW["keyword"], channel="네이버 블로그",
    settings={"insuranceCategory": "건강보험", "contentTone": "전문가",
              "lifeStage": "40대 가장", "targetAge": "40-50대", "targetConcern": "암 진단비"},
    skills=os.environ.get("BM_SKILLS","base,pro_blog,naver_seo").split(","), channel_prompt=CHANNEL_PROMPT,
    compliance_prompt=COMPLIANCE, profile_prompt=PROFILE, personal_reg_prompt="",
    extra_prompt="", benchmark_prompt=main.build_benchmark_prompt(bm))
if "benchmark" in inspect.signature(main.build_content_prompt).parameters:
    kwargs["benchmark"] = bm
PROMPT = main.build_content_prompt(**kwargs)

MARKER_RE = re.compile(r"^[ \t]*#{1,6}[ \t]*이미지\s*프롬프트[ \t]*$", re.M)
ITEM_RE = re.compile(r"^\s*(\d+)\.\s+\S", re.M)

def run(job):
    model, i = job
    env = {**os.environ}; env.pop("CLAUDECODE", None)
    t0 = time.time()
    try:
        p = subprocess.run(["claude", "-p", "--model", model, "--output-format", "text"],
                           input=PROMPT.encode(), capture_output=True, timeout=900, env=env)
        rc, raw = p.returncode, p.stdout.decode(errors="replace").strip()
    except subprocess.TimeoutExpired:
        rc, raw = -9, ""
    dt = time.time() - t0
    post = main.limit_hashtags(raw)
    m = MARKER_RE.search(post)
    items = len(ITEM_RE.findall(post[m.end():])) if m else 0
    open(os.path.join(HERE, f"pout_{LABEL}_{model}_{i}.md"), "w").write(post)
    return dict(label=LABEL, model=model, rep=i, rc=rc, secs=round(dt, 1), chars=len(post),
                marker_raw=bool(MARKER_RE.search(raw)), marker=bool(m), items=items,
                target=ROW["image_count"], over180=dt > 180, over420=dt > 420)

jobs = [(m, i) for m in MODELS for i in range(1, REPS + 1)]
print(f"### {LABEL} | PROD-LIKE prompt {len(PROMPT)}자 | image_count={ROW['image_count']} | {len(jobs)}회")
print(f"### 꼬리 160자: {PROMPT[-160:]!r}\n")
open(os.path.join(HERE, f"prompt_{LABEL}.txt"), "w").write(PROMPT)
with ThreadPoolExecutor(max_workers=5) as ex:
    res = list(ex.map(run, jobs))
res.sort(key=lambda r: (r["model"], r["rep"]))
for r in res:
    print(f"[{LABEL}/{r['model']}#{r['rep']}] rc={r['rc']} {r['secs']}s {r['chars']}자 "
          f"marker(raw)={r['marker_raw']} marker={r['marker']} 항목={r['items']}/{r['target']}"
          + (" ★>180s" if r["over180"] else ""))
print("\n=== 요약 ===")
for m in MODELS:
    sub = [r for r in res if r["model"] == m]
    secs = [r["secs"] for r in sub]
    print(f"{LABEL}/{m}: 마커 {sum(r['marker'] for r in sub)}/{len(sub)} · "
          f"개수정확 {sum(r['items']==r['target'] for r in sub)}/{len(sub)} · "
          f"min {min(secs)}s / max {max(secs)}s · >180s {sum(r['over180'] for r in sub)}건 · "
          f">420s {sum(r['over420'] for r in sub)}건")
json.dump(res, open(os.path.join(HERE, f"pres_{LABEL}.json"), "w"), ensure_ascii=False, indent=2)
