/**
 * InsuWiki Phase 3: Claude Code 요약 파이프라인 — 프롬프트 템플릿 모듈
 * 설계: 미미르 (UX/프롬프트 설계자)
 *
 * 개요:
 *   보험약관 PDF(최대 800페이지)를 인덱싱한 후, 텍스트 청크를 3단계로 요약합니다.
 *   - Level 1 (핵심): 전체 약관 1~2문단 요약
 *   - Level 2 (섹션): 장(章)/절(節) 단위 요약
 *   - Level 3: 원문 청크 그대로 (요약 불필요, 이 파일에서 정의하지 않음)
 *
 * 품질 원칙:
 *   - 보험 전문 용어를 정확히 사용
 *   - 구조화된 출력 유도 (마크다운)
 *   - 환각(Hallucination) 방지: "약관에 명시된 내용만 요약", "추가 해석 금지"
 *   - 한국어 출력
 *
 * 사용법:
 *   import { buildLevel2Prompt, buildLevel1Prompt, buildDispatchPrompt } from './prompts/summary-prompts';
 *
 *   const { system, user } = buildLevel2Prompt('제1장 주계약', '..약관 섹션 원문..');
 *   const { system, user } = buildLevel1Prompt('삼성생명', '퍼펙트종신', '..Level2 요약 목록..');
 */

// ─────────────────────────────────────────────────────────────────────────────
// 공통 상수
// ─────────────────────────────────────────────────────────────────────────────

/** 모든 요약 프롬프트에 공통으로 적용되는 절대 금지 지시 */
const HALLUCINATION_GUARD = `
【절대 준수 사항 — 환각(Hallucination) 방지】
- 약관 원문에 명시된 내용만 요약합니다. 원문에 없는 내용은 절대 추가하지 않습니다.
- 수치(금액, 비율, 기간)는 원문 그대로 인용합니다. 추정하거나 반올림하지 않습니다.
- "아마도", "일반적으로", "보통은", "대개", "추정", "~인 것 같" 표현을 절대 사용하지 않습니다.
- 약관에서 확인할 수 없는 내용은 해당 항목을 생략하거나 "(원문에 해당 내용 없음)"으로 명시합니다.
- 다른 상품·회사 약관 내용과 혼동하거나 병합하지 않습니다.
`.trim();

/** 출처 명시 지침 */
const SOURCE_CITATION_GUIDE = `
- 특정 조항을 언급할 때는 가능한 경우 조항 번호(예: 제3조 제2항)를 함께 표기합니다.
- 중요한 수치·조건은 "(원문 인용)" 형태로 표기하여 원본 출처임을 명확히 합니다.
`.trim();

// ─────────────────────────────────────────────────────────────────────────────
// Level 2: 섹션(장/절) 단위 요약 프롬프트
// ─────────────────────────────────────────────────────────────────────────────

/**
 * LEVEL2_SYSTEM_PROMPT
 *
 * 역할: 보험약관 분석 전문가
 * 목적: 설계사/고객이 장(章)·절(節) 단위 섹션을 빠르게 파악할 수 있도록
 *       핵심 보장, 면책, 지급 절차를 구조화된 마크다운으로 요약합니다.
 */
export const LEVEL2_SYSTEM_PROMPT = `
당신은 보험약관 분석 전문가입니다.
15년 이상의 보험 실무 경험을 바탕으로 약관을 정밀하게 분석하며,
설계사와 고객이 즉시 이해할 수 있는 핵심 요약을 제공합니다.

【역할 및 임무】
주어진 약관 섹션(장 또는 절)을 분석하여 다음을 추출합니다:
1. 핵심 보장 내용 (어떤 위험을 커버하는가)
2. 면책·부담보·감액 조항 (보험금이 지급되지 않는 경우)
3. 보험금 지급 조건 및 절차
4. 주의가 필요한 특약 사항

【출력 형식 요구사항】
- 마크다운을 사용합니다: **볼드**, 목록(-), 소제목(###)
- 각 항목은 불릿 리스트로 간결하게 작성합니다
- 보험 전문 용어를 정확하게 사용합니다
  (예: 면책기간, 감액지급, 부담보, 주계약, 특약, 피보험자, 보험수익자)
- 300~500자 이내로 요약합니다 (원문이 짧으면 그에 맞게 축약 가능)
- 섹션 제목은 반드시 포함합니다

【출력 예시 구조】
### [섹션명]
**핵심 보장**
- [보장 내용 1]
- [보장 내용 2]

**면책·부담보·감액**
- [면책 조항 1]
- [감액 기준]

**지급 조건 및 절차**
- [청구 요건]
- [지급 절차]

**특약 주의사항**
- [주의 특약]

${HALLUCINATION_GUARD}
${SOURCE_CITATION_GUIDE}
`.trim();

/**
 * LEVEL2_USER_PROMPT_TEMPLATE
 *
 * 템플릿 변수 (실제 사용 시 buildLevel2Prompt() 함수가 치환합니다):
 *   {{sectionTitle}} — 섹션 제목 (예: "제1장 주계약 보장 내용")
 *   {{sectionText}}  — 섹션 원문 텍스트 (청크 집합)
 *
 * 직접 문자열 치환이 필요한 경우:
 *   template.replace('{{sectionTitle}}', title).replace('{{sectionText}}', text)
 */
export const LEVEL2_USER_PROMPT_TEMPLATE =
    '다음 보험약관 섹션을 분석하여 요약해 주세요.\n\n' +
    '【섹션 제목】\n' +
    '{{sectionTitle}}\n\n' +
    '【원문】\n' +
    '{{sectionText}}\n\n' +
    '위 원문을 바탕으로 아래 항목을 마크다운 형식으로 요약하세요:\n\n' +
    '1. **핵심 보장 내용**: 이 섹션에서 보장하는 위험/질병/사고의 종류와 보장 금액 기준\n' +
    '2. **면책·부담보·감액 조항**: 보험금이 지급되지 않거나 감액되는 구체적 사유\n' +
    '3. **보험금 지급 조건 및 절차**: 청구 요건, 진단 기준, 필요 서류, 지급 시한\n' +
    '4. **주의할 특약 사항**: 조건부 보장, 대기기간(면책기간), 중복 보장 제한 등\n\n' +
    '요약 분량: 300~500자 이내 (원문이 짧은 경우 그에 맞게 작성)\n' +
    '출력 언어: 한국어\n' +
    '원문에 없는 내용은 절대 추가하지 마세요.';

// ─────────────────────────────────────────────────────────────────────────────
// Level 1: 전체 약관 핵심 요약 프롬프트
// ─────────────────────────────────────────────────────────────────────────────

/**
 * LEVEL1_SYSTEM_PROMPT
 *
 * 역할: 보험상품 분석 수석 전문가
 * 목적: 복수의 Level 2 섹션 요약을 통합하여 해당 상품의 핵심을
 *       1~2문단(200~400자)으로 집약합니다.
 *       이 요약은 상품 선택 단계에서 설계사·고객이 최초로 읽는 "상품 개요"입니다.
 */
export const LEVEL1_SYSTEM_PROMPT = `
당신은 보험상품 분석 수석 전문가입니다.
수십 종의 생명·손해보험 약관을 비교·분석한 경험을 바탕으로,
복잡한 약관의 핵심을 명확하고 간결하게 요약합니다.

【역할 및 임무】
다수의 섹션 요약(Level 2)을 입력받아 상품 전체의 핵심을 1~2문단으로 집약합니다.
이 요약은 상품 선택·비교 단계에서 활용되므로 다음에 집중합니다:
1. 이 상품이 어떤 위험을 주로 커버하는가 (핵심 보장)
2. 어떤 경우에 보험금이 지급되지 않는가 (주요 면책)
3. 다른 유사 상품과 구별되는 특이사항·차별점

【출력 형식 요구사항】
- 1~2개 문단으로 작성합니다 (단락 구분은 빈 줄 하나)
- 보험 전문 용어를 정확하게 사용하되, 핵심만 압축합니다
- 200~400자 이내로 요약합니다
- 마크다운 볼드(**텍스트**)를 활용하여 핵심 키워드를 강조합니다
- 상품명과 회사명을 첫 문장에 자연스럽게 포함합니다

【출력 예시】
**[회사명] [상품명]**은 [주요 보장 위험]을 핵심으로 하는 [상품 유형]입니다.
[핵심 보장 내용 요약]. 단, **[주요 면책 조항]**의 경우 보험금이 지급되지 않으며,
[감액 또는 부담보 기준]에 유의해야 합니다.
[차별점 또는 특이사항]이 있어 [유사 상품 대비 특징]합니다.

${HALLUCINATION_GUARD}

【추가 지침】
- 입력된 섹션 요약 내용만을 근거로 작성합니다
- 섹션 요약에 포함되지 않은 다른 상품 정보를 유추하거나 추가하지 않습니다
- "이 상품은 좋습니다" 등의 주관적 평가 표현을 사용하지 않습니다
`.trim();

/**
 * LEVEL1_USER_PROMPT_TEMPLATE
 *
 * 템플릿 변수 (실제 사용 시 buildLevel1Prompt() 함수가 치환합니다):
 *   {{companyName}}     — 보험사명 (예: "삼성생명")
 *   {{productName}}     — 상품명 (예: "퍼펙트종신")
 *   {{level2Summaries}} — Level 2 섹션 요약 목록 (섹션명과 요약 포함)
 *
 * 직접 문자열 치환이 필요한 경우:
 *   template
 *     .replace('{{companyName}}', name)
 *     .replace('{{productName}}', name)
 *     .replace('{{level2Summaries}}', summaries)
 */
export const LEVEL1_USER_PROMPT_TEMPLATE =
    '다음은 【{{companyName}} / {{productName}}】 보험약관의 섹션별 요약입니다.\n' +
    '이 섹션 요약들을 종합하여 상품 전체의 핵심을 1~2문단으로 요약해 주세요.\n\n' +
    '【섹션별 요약 (Level 2)】\n' +
    '{{level2Summaries}}\n\n' +
    '위 섹션 요약을 바탕으로 다음 세 가지를 반드시 포함하여 작성하세요:\n\n' +
    '1. **핵심 보장**: 이 상품이 어떤 위험·질병·사고를 보장하는가\n' +
    '   (주계약 보장, 주요 특약 보장을 포함하되 핵심만 압축)\n\n' +
    '2. **주요 면책 사항**: 어떤 경우 보험금이 지급되지 않는가\n' +
    '   (주요 면책 사유, 부담보 조건, 감액 기준)\n\n' +
    '3. **특이사항·차별점**: 다른 유사 상품과 구별되는 점\n' +
    '   (독특한 보장 구조, 특수 조건, 주의가 필요한 제약 등)\n\n' +
    '요약 분량: 200~400자 이내 (1~2문단)\n' +
    '출력 언어: 한국어\n' +
    '섹션 요약에 없는 내용은 절대 추가하지 마세요.';

// ─────────────────────────────────────────────────────────────────────────────
// 디스패치 프롬프트: 아누(개발실장) → 팀봇 요약 작업 지시
// ─────────────────────────────────────────────────────────────────────────────

/**
 * DISPATCH_PROMPT_TEMPLATE
 *
 * 아누(개발실장)가 팀봇(Claude Code)에게 pending summary_jobs를 처리하도록
 * 지시하는 디스패치 프롬프트 템플릿입니다.
 *
 * 템플릿 변수 (실제 사용 시 buildDispatchPrompt() 함수가 치환합니다):
 *   {{pendingJobCount}} — 처리 대기 중인 summary_jobs 건수
 *   {{jobList}}         — 각 Job의 ID, 회사명, 상품명 목록 (멀티라인 텍스트)
 *
 * 직접 문자열 치환이 필요한 경우:
 *   template
 *     .replace(/\{\{pendingJobCount\}\}/g, String(count))
 *     .replace('{{jobList}}', listText)
 */
export const DISPATCH_PROMPT_TEMPLATE =
    '안녕하세요, 팀봇.\n' +
    '현재 Firestore `summary_jobs` 컬렉션에 처리 대기 중인 요약 작업이 **{{pendingJobCount}}건** 있습니다.\n' +
    '아래 목록의 모든 Job을 순서대로 처리하고 완료 보고를 해 주세요.\n\n' +
    '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n' +
    '📋 처리 대기 Job 목록 ({{pendingJobCount}}건)\n' +
    '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n' +
    '{{jobList}}\n' +
    '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n' +
    '【작업 순서 및 실행 명령어】\n\n' +
    '**Step 1. pending Job 목록 조회 및 확인**\n' +
    '```\n' +
    '# Firestore summary_jobs 컬렉션에서 pending 상태 Job 조회\n' +
    '# 각 Job의 companyId, companyName, productId, productName, chunksCount 확인\n' +
    'collection: summary_jobs\n' +
    'filter: status == "pending"\n' +
    '```\n\n' +
    '**Step 2. 각 Job의 청크(Level 3) 읽기**\n' +
    '```\n' +
    '# 해당 productId의 insurance_chunks 전체 조회\n' +
    'collection: insurance_chunks\n' +
    'filter: productId == "{productId}"\n' +
    'orderBy: pageNumber asc\n' +
    '```\n\n' +
    '**Step 3. 섹션 구분 및 Level 2 요약 생성**\n' +
    '```\n' +
    '# 1) 청크를 섹션(관/장/절) 단위로 그룹핑\n' +
    '#    - 청크 텍스트에서 "제N관", "제N장", "제N절", "부칙" 패턴으로 섹션 경계 감지\n' +
    '#    - 인접 청크를 동일 섹션으로 병합\n' +
    '# 2) 각 섹션별로 LEVEL2_SYSTEM_PROMPT + LEVEL2_USER_PROMPT_TEMPLATE 적용\n' +
    '#    - buildLevel2Prompt(sectionTitle, sectionText) 사용\n' +
    '# 3) 생성된 섹션 요약을 insurance_summaries 컬렉션에 level: 2 로 저장\n' +
    'collection: insurance_summaries\n' +
    'doc: 자동 생성 ID\n' +
    'fields:\n' +
    '  - companyId, productId, level: 2\n' +
    '  - sectionTitle (섹션 제목)\n' +
    '  - content (생성된 요약)\n' +
    '  - pageRange: { start, end }\n' +
    '  - createdAt, updatedAt\n' +
    '```\n\n' +
    '**Step 4. Level 1 핵심 요약 생성**\n' +
    '```\n' +
    '# 1) Step 3에서 저장된 모든 Level 2 요약을 불러와 합산\n' +
    '# 2) LEVEL1_SYSTEM_PROMPT + LEVEL1_USER_PROMPT_TEMPLATE 적용\n' +
    '#    - buildLevel1Prompt(companyName, productName, level2Summaries) 사용\n' +
    '# 3) 생성된 핵심 요약을 insurance_summaries 컬렉션에 level: 1 로 저장\n' +
    'collection: insurance_summaries\n' +
    'doc: 자동 생성 ID\n' +
    'fields:\n' +
    '  - companyId, productId, level: 1\n' +
    '  - content (생성된 핵심 요약)\n' +
    '  - createdAt, updatedAt\n' +
    '```\n\n' +
    '**Step 5. summary_job 상태 업데이트**\n' +
    '```\n' +
    '# 해당 Job 문서를 complete 상태로 업데이트\n' +
    'collection: summary_jobs\n' +
    'doc: {jobId}\n' +
    'update:\n' +
    '  - status: "complete"\n' +
    '  - updatedAt: serverTimestamp()\n' +
    '```\n\n' +
    '【요약 품질 기준】\n' +
    '다음 기준을 충족하지 않으면 해당 요약을 저장하지 말고 재생성하세요:\n\n' +
    '| 항목 | 기준 |\n' +
    '|---|---|\n' +
    '| Level 2 분량 | 300~500자 (섹션 원문이 짧은 경우 그에 맞게 조정 가능) |\n' +
    '| Level 1 분량 | 200~400자 (1~2문단) |\n' +
    '| 환각 여부 | "아마도", "추정", "일반적으로", "보통은" 등 불확실 표현 0건 |\n' +
    '| 원문 일치 | 수치(금액, 비율, 기간)는 원문과 100% 일치해야 함 |\n' +
    '| 구조 요건 | 마크다운 볼드·리스트 사용, 섹션 제목 포함 (Level 2) |\n' +
    '| 필수 항목 | Level 2: 핵심보장·면책·지급조건 모두 포함 |\n' +
    '| 필수 항목 | Level 1: 핵심보장·주요면책·차별점 모두 포함 |\n\n' +
    '【오류 처리】\n' +
    '- 청크가 없는 Job: `summary_jobs.status = "failed"` + error 메시지 기록 후 다음 Job 진행\n' +
    '- 섹션 감지 불가: 전체 텍스트를 하나의 섹션으로 처리하여 Level 2 생성\n' +
    '- 요약 생성 실패: 최대 3회 재시도, 실패 시 `status = "failed"` + error 기록\n' +
    '- Level 2가 하나도 없을 경우: Level 1 생성 건너뜀, `status = "failed"` + error 기록\n\n' +
    '【완료 보고 형식】\n' +
    '모든 Job 처리 후 아래 형식으로 결과를 보고하세요:\n' +
    '```\n' +
    '[요약 파이프라인 완료 보고]\n' +
    '- 총 처리 요청: {{pendingJobCount}}건\n' +
    '- 성공: N건\n' +
    '- 실패: N건 (사유 목록)\n' +
    '- Level 1 요약 생성: N건\n' +
    '- Level 2 요약 생성: 합계 N섹션\n' +
    '```\n\n' +
    '처리를 시작해 주세요.';

// ─────────────────────────────────────────────────────────────────────────────
// 빌더 함수: 템플릿 변수 치환
// ─────────────────────────────────────────────────────────────────────────────

/**
 * Level 2 섹션 요약용 프롬프트 쌍을 생성합니다.
 *
 * @param sectionTitle - 섹션 제목 (예: "제1장 주계약 보장 내용")
 * @param sectionText  - 섹션 원문 텍스트 (500~3,000자 권장)
 * @returns { system: string; user: string } 시스템 프롬프트 + 유저 프롬프트 쌍
 *
 * @example
 * const { system, user } = buildLevel2Prompt(
 *   '제3조 보험금 지급 사유',
 *   '피보험자가 이 약관의 보험기간 중 ...'
 * );
 * // Gemini / Claude API에 전달:
 * // messages: [{ role: 'system', content: system }, { role: 'user', content: user }]
 */
export function buildLevel2Prompt(
    sectionTitle: string,
    sectionText: string,
): { system: string; user: string } {
    const user = LEVEL2_USER_PROMPT_TEMPLATE
        .replace('{{sectionTitle}}', sectionTitle)
        .replace('{{sectionText}}', sectionText);

    return {
        system: LEVEL2_SYSTEM_PROMPT,
        user,
    };
}

/**
 * Level 1 전체 약관 핵심 요약용 프롬프트 쌍을 생성합니다.
 *
 * @param companyName     - 보험사명 (예: "삼성생명")
 * @param productName     - 상품명 (예: "퍼펙트종신")
 * @param level2Summaries - Level 2 섹션 요약 목록 (각 섹션의 제목과 요약을 포함한 멀티라인 텍스트)
 * @returns { system: string; user: string } 시스템 프롬프트 + 유저 프롬프트 쌍
 *
 * @example
 * const level2Text = level2SummaryDocs
 *   .map((doc, i) => `[섹션 ${i + 1}] ${doc.sectionTitle}\n${doc.summaryText}`)
 *   .join('\n\n---\n\n');
 *
 * const { system, user } = buildLevel1Prompt('삼성생명', '퍼펙트종신', level2Text);
 */
export function buildLevel1Prompt(
    companyName: string,
    productName: string,
    level2Summaries: string,
): { system: string; user: string } {
    const user = LEVEL1_USER_PROMPT_TEMPLATE
        .replace('{{companyName}}', companyName)
        .replace('{{productName}}', productName)
        .replace('{{level2Summaries}}', level2Summaries);

    return {
        system: LEVEL1_SYSTEM_PROMPT,
        user,
    };
}

/**
 * Job 목록 항목의 타입 정의
 */
export interface SummaryJobItem {
    /** Firestore summary_jobs 문서 ID */
    jobId: string;
    /** 보험사명 (예: "삼성생명") */
    companyName: string;
    /** 상품명 (예: "퍼펙트종신") */
    productName: string;
}

/**
 * 팀봇에게 요약 작업을 지시하는 디스패치 프롬프트를 생성합니다.
 *
 * @param pendingJobCount - 처리 대기 중인 summary_jobs 건수
 * @param jobList         - 각 Job의 ID, 회사명, 상품명 배열
 * @returns string 완성된 디스패치 프롬프트
 *
 * @example
 * const jobs: SummaryJobItem[] = [
 *   { jobId: 'samsung_life_perfect_jongsin_2403', companyName: '삼성생명', productName: '퍼펙트종신' },
 *   { jobId: 'hyundai_marine_driver_2501',        companyName: '현대해상',  productName: '운전자보험' },
 * ];
 * const prompt = buildDispatchPrompt(jobs.length, jobs);
 * // Claude Code / 팀봇 채팅에 붙여넣기
 */
export function buildDispatchPrompt(
    pendingJobCount: number,
    jobList: SummaryJobItem[],
): string {
    const jobListText = jobList
        .map(
            (job, index) =>
                `  ${index + 1}. [Job ID: ${job.jobId}] ${job.companyName} / ${job.productName}`,
        )
        .join('\n');

    return DISPATCH_PROMPT_TEMPLATE
        .replace(/\{\{pendingJobCount\}\}/g, String(pendingJobCount))
        .replace('{{jobList}}', jobListText);
}
