"""task-2401 — 25장 stratified L1 evidence 생성 스크립트.

5 카테고리 × 5 패턴 × Latin square 사이즈 배분 → 25 PNG.
모든 PNG pass=True 검증. 실패 시 즉시 sys.exit(1).
"""
from __future__ import annotations

import importlib.util
import json
import sys
from pathlib import Path

# ─── 경로 설정 ─────────────────────────────────────────────────────────────
WORKSPACE = Path('/home/jay/workspace')
EVIDENCE_DIR = Path(__file__).parent / 'evidence'
EVIDENCE_DIR.mkdir(parents=True, exist_ok=True)
RESULTS_JSON = Path(__file__).parent / 'evidence' / 'results.json'


def _load(name: str, path: Path):
    spec = importlib.util.spec_from_file_location(name, path)
    assert spec is not None, f'failed to spec {path}'
    assert spec.loader is not None, f'no loader for {path}'
    mod = importlib.util.module_from_spec(spec)
    sys.modules[name] = mod
    spec.loader.exec_module(mod)
    return mod


# ─── 모듈 로드 ─────────────────────────────────────────────────────────────
render_mod = _load('_sc_render_run', WORKSPACE / 'skills/satori-cardnews/scripts/render_one.py')

# ─── 25 조합 매트릭스 ──────────────────────────────────────────────────────
CATEGORIES = ['financial', 'saas', 'consumer', 'luxury', 'tech_minimal']
PATTERNS = ['h1_photo_card', 'h2_illustration', 'h3_gpt_style', 'h4_gradient', 'h5_user_photo']
SIZES = [(1080, 1080), (1080, 1350), (1200, 630), (1200, 675), (1080, 1920)]

# Latin square: (i+j) % 5
def get_size(i: int, j: int) -> tuple[int, int]:
    return SIZES[(i + j) % 5]

# ─── 25 케이스 한글 텍스트 ────────────────────────────────────────────────
CASE_TEXTS: dict[tuple[str, str], tuple[str, str]] = {
    ('financial', 'h1_photo_card'):      ('내 보험료 지금 바로 비교', '5분 만에 최저가 보험 찾기'),
    ('financial', 'h2_illustration'):    ('실손보험 완벽 가이드', '청구 방법부터 갱신까지 한눈에'),
    ('financial', 'h3_gpt_style'):       ('종신보험 vs 정기보험', '나에게 맞는 선택 기준 정리'),
    ('financial', 'h4_gradient'):        ('2026 보험 트렌드 총정리', '꼭 알아야 할 변경 사항 7가지'),
    ('financial', 'h5_user_photo'):      ('보험료 절약 꿀팁', '매월 3만원 아끼는 방법'),

    ('saas', 'h1_photo_card'):           ('팀 협업 효율 300% 향상', '우리 팀만의 워크플로우 만들기'),
    ('saas', 'h2_illustration'):         ('SaaS 도입 전 체크리스트', '실패 없는 도입을 위한 10가지'),
    ('saas', 'h3_gpt_style'):            ('구독 비용 최적화 전략', '사용하지 않는 기능 정리하기'),
    ('saas', 'h4_gradient'):             ('데이터 기반 의사결정', 'AI 분석 도구 활용 완전 정복'),
    ('saas', 'h5_user_photo'):           ('스타트업 필수 툴스택', '월 10만원으로 운영하는 법'),

    ('consumer', 'h1_photo_card'):       ('오늘의 특가 한정 할인', '24시간만 진행되는 특별 혜택'),
    ('consumer', 'h2_illustration'):     ('신상품 출시 기념 이벤트', '첫 구매 고객 50% 할인'),
    ('consumer', 'h3_gpt_style'):        ('리뷰 이벤트 참여하기', '별점 5개 남기고 적립금 받기'),
    ('consumer', 'h4_gradient'):         ('여름 시즌 컬렉션 공개', '트렌디한 아이템 모아보기'),
    ('consumer', 'h5_user_photo'):       ('고객 만족도 1위 달성', '4만 명이 선택한 브랜드'),

    ('luxury', 'h1_photo_card'):         ('프리미엄 라이프스타일', '당신만을 위한 특별한 경험'),
    ('luxury', 'h2_illustration'):       ('한정판 에디션 공개', '전 세계 500개만 제작된 작품'),
    ('luxury', 'h3_gpt_style'):          ('장인 정신의 결정체', '100년 전통을 이어받은 기술'),
    ('luxury', 'h4_gradient'):           ('익스클루시브 멤버십', 'VIP만을 위한 프라이빗 서비스'),
    ('luxury', 'h5_user_photo'):         ('컬렉터를 위한 선택', '가치가 오르는 아이템 큐레이션'),

    ('tech_minimal', 'h1_photo_card'):   ('개발 생산성을 높이는 법', '현직 개발자가 알려주는 팁'),
    ('tech_minimal', 'h2_illustration'): ('클린 코드 작성 원칙', '유지보수가 쉬운 코드 만들기'),
    ('tech_minimal', 'h3_gpt_style'):    ('AI 코딩 도구 비교', 'Copilot vs Cursor vs Codeium'),
    ('tech_minimal', 'h4_gradient'):     ('타입스크립트 마이그레이션', '단계별 전환 가이드 완성본'),
    ('tech_minimal', 'h5_user_photo'):   ('오픈소스 기여 시작하기', '첫 PR 날리는 방법 정리'),
}


def main() -> None:
    results: list[dict] = []
    fail_count = 0

    print(f"\n{'='*60}")
    print("task-2401 — 25장 stratified L1 evidence 생성")
    print(f"{'='*60}\n")

    for i, cat in enumerate(CATEGORIES):
        for j, pat in enumerate(PATTERNS):
            w, h = get_size(i, j)
            title, body = CASE_TEXTS[(cat, pat)]
            fname = f"{cat}_{pat}_{w}x{h}.png"
            output_path = EVIDENCE_DIR / fname

            print(f"[{i*5+j+1:02d}/25] {cat} × {pat} @ {w}×{h}")
            print(f"       title: {title}")
            print(f"       body:  {body}")

            try:
                result = render_mod.render_and_verify(
                    brand=cat,
                    pattern=pat,
                    size=(w, h),
                    title=title,
                    body=body,
                    output_path=output_path,
                )

                file_size_kb = output_path.stat().st_size / 1024 if output_path.exists() else 0
                tofu_score = result.get('metrics', {}).get('tofu_score', -1)
                passed = result.get('pass', False)

                record = {
                    'idx': i * 5 + j + 1,
                    'category': cat,
                    'pattern': pat,
                    'size': f'{w}x{h}',
                    'title': title,
                    'body': body,
                    'filename': fname,
                    'pass': passed,
                    'file_size_kb': round(file_size_kb, 2),
                    'tofu_score': tofu_score,
                    'checks': result.get('checks', {}),
                    'mode': result.get('mode', ''),
                    'errors': result.get('errors', []),
                }
                results.append(record)

                status = 'PASS' if passed else 'FAIL'
                print(f"       → {status} | {file_size_kb:.1f}KB | tofu={tofu_score:.3f}")

                if not passed:
                    fail_count += 1
                    print(f"       !! FAIL errors: {result.get('errors', [])}")

            except Exception as exc:
                fail_count += 1
                record = {
                    'idx': i * 5 + j + 1,
                    'category': cat,
                    'pattern': pat,
                    'size': f'{w}x{h}',
                    'title': title,
                    'body': body,
                    'filename': fname,
                    'pass': False,
                    'file_size_kb': 0,
                    'tofu_score': -1,
                    'checks': {},
                    'mode': 'ERROR',
                    'errors': [str(exc)],
                }
                results.append(record)
                print(f"       !! EXCEPTION: {exc}")

    # ─── results.json 저장 ──────────────────────────────────────────────────
    RESULTS_JSON.write_text(json.dumps(results, ensure_ascii=False, indent=2))
    print(f"\n결과 저장: {RESULTS_JSON}")

    # ─── summary ────────────────────────────────────────────────────────────
    pass_count = sum(1 for r in results if r['pass'])
    total = len(results)
    avg_size = sum(r['file_size_kb'] for r in results) / total if total else 0
    avg_tofu = sum(r['tofu_score'] for r in results if r['tofu_score'] >= 0) / max(1, sum(1 for r in results if r['tofu_score'] >= 0))

    print(f"\n{'='*60}")
    print(f"SUMMARY")
    print(f"{'='*60}")
    print(f"  pass:         {pass_count}/{total}")
    print(f"  평균 파일크기:  {avg_size:.1f} KB")
    print(f"  평균 tofu점수: {avg_tofu:.4f}")
    print(f"{'='*60}\n")

    if fail_count > 0:
        print(f"!!! {fail_count}장 FAIL — 재확인 필요")
        sys.exit(1)
    else:
        print("전체 25장 PASS")


if __name__ == '__main__':
    main()
