"""task-3070 B-3: 서버 동일 프롬프트를 N회 실호출해 마커 출력률을 측정한다.

★ 결함이 확률적이라 1회 호출로는 판정 불가(BASE 1회차에서 양쪽 다 마커가 나왔다).
사용: python3 realcall_n.py <server_dir> <label> <reps> <model>[,<model>...]
"""
import importlib.util, 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]
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"])

import inspect
kwargs = dict(topic=ROW["keyword"], channel="블로그",
              settings={"insuranceCategory": "건강보험", "contentTone": "자동"},
              skills=["base"], channel_prompt="", compliance_prompt="", profile_prompt="",
              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"out_{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=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} | prompt {len(PROMPT)}자 | image_count={ROW['image_count']} | {len(jobs)}회 호출")
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={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]
    ok = sum(1 for r in sub if r["marker"])
    exact = sum(1 for r in sub if r["items"] == r["target"])
    secs = [r["secs"] for r in sub]
    print(f"{LABEL}/{m}: 마커 {ok}/{len(sub)} · 개수정확 {exact}/{len(sub)} · "
          f"소요 min {min(secs)}s / max {max(secs)}s · >180s {sum(r['over180'] for r in sub)}건")
json.dump(res, open(os.path.join(HERE, f"res_{LABEL}.json"), "w"), ensure_ascii=False, indent=2)
