/**
 * 회의 녹취 텍스트 → 사실 기반 구조화 회의록(Actionable Minutes) LLM 프롬프트.
 * 사용자 정의 규칙: Fact/Discussion/Decision/Risk/Action 분류, 메타데이터 우선.
 */
export function buildMeetPrompt(transcript: string, metadata: string): string {
    const metaBlock = metadata.trim()
        || '(메타데이터 미입력 — 녹취록 내용에서 추론하거나 "확인 불가"로 표기)';
    return `# 임무 (Objective)
제공된 회의 녹취 텍스트와 메타데이터를 기반으로, 사실 기반의 구조화된
회의록(Actionable Minutes)을 생성한다. 외부/도메인 지식은 *STT 오타 보정과 용어
해석*에만 사용하고, *녹취록에 없는 새로운 사실을 추가*하는 데는 절대 쓰지 않는다.

# 역할 (Role)
- Fact Extractor: 녹취록에 명시적으로 존재하는 사실만 추출
- Attribution Tracker: 누가 무엇을 말했는지 발언 주체를 끝까지 추적해 오귀속을 방지
- Decision Tracker: 결정 여부 구분
- Action Organizer: 실행 항목 구조화
- Context Filter: 불필요한 발언(잡담) 제거

# 데이터 우선순위 (Data Priority)
1순위: 메타데이터 / 2순위: 녹취록 내용. 충돌 시 반드시 메타데이터를 사용한다.

# STT 오타 보정 (Transcription Noise Handling — 이 녹취록은 음성→텍스트 변환물이라 오타가 많다)
- 발음이 유사한 단어가 잘못 표기돼 있다(예: "Dovrunner"→"Doverunner", "페어플레이"→"페어플래이"). **한 단어의 철자에 집착하지 말고 주변 문맥(앞뒤 키워드)으로 의미를 복원하라.**
- 발음이 유사한 명백한 오타는 문맥상 맞는 기술 용어·고유명사로 **정규화**하라. 흔한 기술 용어(DRM, SDK, 딥링크, API, 렌더링, 페어플레이, 암호화 등)는 도메인 지식으로 보정해도 된다.
- 메타데이터에 인명·기업명·제품명·용어가 주어졌으면 그것을 **정답 표기**로 보고, 녹취록의 유사 오타를 그 표기로 맞춘다(메타데이터는 사실상 용어집 역할).
- **핵심 구분 (절대 혼동 금지)**: '녹취록에 *있는* 단어의 철자를 문맥으로 바로잡는 것'은 허용·권장된다. '녹취록에 *없는* 사실(수치·결정·없던 항목)을 지어내는 것'은 금지다. **철자 보정 ≠ 사실 날조.**
- 철자가 틀려도 문맥상 의미가 분명하면 그 의미를 확정된 것으로 다뤄라 — **오타 하나 때문에 멀쩡한 내용 전체를 "확인 불가"로 막지 말 것.**
- 정규화는 했지만 문맥으로도 정체가 끝내 모호한 용어에 한해, 정규화 표기 옆에 원문을 함께 남긴다: 예) \`Doverunner(원문: "Dovrunner", 표기 불확실)\`.

# 처리 절차 (Processing Flow)
1. Speaker Tracking — 발언자 ID/이름을 끝까지 유지한다. **누가 한 말인지를 절대 임의로 바꾸거나 합치지 말 것.**
2. Topic Reclustering — 이 녹취록은 비선형이다(A→B→Z→다시 A 식으로 주제가 튄다). 녹취록 전체를 훑어 **흩어진 발언을 주제별로 다시 묶은 뒤** 정리한다. 녹취록상 앞뒤로 붙어 있다는 이유만으로 두 발언을 인과·연결 관계로 엮지 말 것(**인접 ≠ 연결**).
3. Deconstruction — 잡담을 제거하고 의미 단위로 분해하되, 각 단위에 발언 주체를 보존한다.
4. Classification — 모든 내용을 Fact / Discussion / Decision / Risk / Action 으로 분류한다.
5. Decision Logic
   - 명확한 합의 표현 → Decision
   - 실행 주체 + 행동 → Action
   - 제안/의견 → Discussion
   - 조건 부족 / 합의 불명확 → Open Issue
6. Structuring — 중복 제거, 핵심만 유지, 짧고 명확한 문장을 사용한다.

# 근거·정확성 규칙 (Grounding Rules — 반드시 준수, 할루시네이션 방지)
- **녹취록에 명시된 내용만 적는다.** 추론으로 빈칸을 메우거나, 별개의 발언을 하나의 인과 사슬로 합성하지 말 것.
- **근거 인용 의무**: 모든 '결정 사항'과 '액션 아이템'에는 근거가 된 발언 원문 일부(20자 내외)를 따옴표로 함께 적는다(오타는 보정 표기로 인용 가능). **인용할 원문 발언을 녹취록에서 찾을 수 없는 항목은 결정·액션이 아니다** — 그런 항목은 만들지 말거나 오픈 이슈로 내려라. 이 인용은 날조 방지 장치다.
- **발언 주체가 불명확하면 추측하지 말 것.** 누가 말했는지 확실하지 않으면 이름을 붙이지 말고 "(발언 주체 불명확)"으로 표기하거나 "~라는 의견이 제시됨"처럼 주체 없이 중립적으로 서술한다. 어떤 발언자의 말을 다른 발언자의 결론으로 옮기는 것은 가장 심각한 오류다.
- **녹취록에 없는 숫자·날짜·금액·결정·없던 항목을 만들어내지 말 것.** (단, 녹취록에 *있는데 철자만 틀린* 용어·고유명사를 문맥으로 정규화하는 것은 허용 — 위 'STT 오타 보정' 참조.) 정말 근거 없는 *사실*만 "확인 필요"로 둔다.
- 어떤 항목의 *내용 자체*가 녹취록에서 약하거나 모호하면(=철자 문제가 아니라 사실이 불확실) 지어내지 말고 해당 항목 끝에 "(확인 필요)"를 붙인다. 단순 표기 오타는 여기 해당하지 않는다.
- Decision은 명시적 합의 표현이 있을 때만 '결정됨'이다. 합의가 불명확하면 '논의 중' 또는 오픈 이슈로 둔다.

# 출력 검증 (Validation)
출력 전 내부적으로 점검한다: ① 각 발언이 올바른 주체에게 귀속됐는가 ② 인접 발언을 임의로 연결하지 않았는가 ③ Decision은 실제 합의인가 ④ 녹취록에 없는 정보를 추가하지 않았는가 ⑤ Action은 실행 가능한가.
단, 검증 과정·체크 로그는 출력하지 말 것. 최종 회의록만 출력한다.

[메타데이터]
${metaBlock}

[회의 녹취록]
\`\`\`
${transcript}
\`\`\`

${OUTPUT_FORMAT}`;
}

/** 최종 회의록 출력 형식 — 단일샷(buildMeetPrompt)과 병합 단계(buildMeetReducePrompt)가 공유. */
const OUTPUT_FORMAT = `# 출력 형식 (Output Format — 정확히 이 구조를 유지)

# [회의 제목]

- **날짜**: [YYYY년 MM월 DD일 | 확인 불가]
- **참석자**: [메타데이터 기준 | 없을 경우: 논의 참여 주체]
- **주제 요약**: [한 문장 요약]

## 🔹 요약 보고
핵심 논의 요약 3~5개를 글머리표로 작성.

## 1. 주요 논의 사항
각 안건마다 아래 구조로:
### [안건 제목]
- **현황**:
- **핵심 논의**: 쟁점이 되거나 주체가 중요한 발언은 "OOO: ~" 형태로 발언자를 밝힌다. 주체가 불명확하면 이름을 붙이지 말 것.
- **결론**: [결정됨 / 논의 중 / 보류]

## 2. 리스크 및 이슈

## 3. 결정 사항
각 결정 끝에 근거 발언을 인용한다: \`- [결정 내용] — 근거: "발언 원문 일부"\`

## 4. 오픈 이슈

## 5. 액션 아이템
각 행은 반드시 녹취록 근거로 작성한다. 표 셀 안에서는 줄바꿈과 \`|\` 문자를 쓰지 말 것.
| 담당 | 작업 내용 | 작업 상세 | 기한 | 상태 |
| --- | --- | --- | --- | --- |

- **작업 내용**: 한 줄짜리 작업명. 캘린더 일정 제목으로 그대로 쓰이므로 그 자체로 무슨 일인지 식별되게 작성한다. ("검토", "확인" 같은 단독 동사 금지)
- **작업 상세**: 이 작업이 **무엇이고, 왜 필요하며, 구체적으로 무엇을 수행해야 하는지**를 2~3문장으로 적는다(배경·목적·수행 범위·산출물). 녹취록에서 언급된 대상·수치·조건을 그대로 인용하고, **마지막에 근거 발언 원문 일부를 \`근거: "…"\` 형태로 덧붙인다**. 근거가 부족하면 "추가 확인 필요: …" 형태로 무엇을 확인해야 하는지 명시한다. 단순히 작업명을 반복하지 말 것.
- **상태**: 다음 중 정확히 하나로 분류한다 (캘린더 자동 등록 게이트가 이 값으로 분기하므로 형식 엄수):
  - \`확정\` — 진행 합의가 명시적이고 기한도 언급됨.
  - \`진행미정\` — 작업이 언급됐으나 실제로 진행할지 합의가 명확하지 않음.
  - \`기한미정\` — 하기로 확정됐으나 완료일/D-Day 가 정해지지 않음.
  - \`조건부: <선행작업>\` — 다른 작업·사건이 끝나야 진행 (선행작업을 짧게 명시. 예: \`조건부: 계약 체결 후\`).
  - \`반복: <주기>\` — 정기 반복 업무 (예: \`반복: 매주 목요일\`).
  확신이 없으면 \`확정\`이 아니라 \`진행미정\`/\`기한미정\` 쪽으로 보수적으로 분류한다.

위 형식을 정확히 따르고, 모든 내용은 한국어로 작성하시오.`;

/**
 * [세그먼트 추출 단계 — Map] 긴 녹취록(단일 컨텍스트 초과)을 조각으로 나눠
 * 각 조각에서 사실만 추출한다. 입력이 짧아 모델이 충실해지고(lost-in-the-middle
 * 방지), 60K 자르기로 후반부가 통째로 사라지던 문제를 없앤다.
 */
export function buildMeetExtractPrompt(segment: string, metadata: string, segIndex: number, segTotal: number): string {
    const metaBlock = metadata.trim() || '(메타데이터 없음)';
    return `# 임무
긴 회의 녹취록의 **${segIndex}/${segTotal}번째 조각**이다. 이 조각에 *명시된 내용만* 아래 형식으로 추출하라.
최종 회의록은 나중에 모든 조각을 합쳐 작성하므로, 여기서는 요약·해석하지 말고 **누락 없이 추출**하는 것이 임무다.

# 규칙 (할루시네이션 방지)
- 이 조각에 없는 사실·수치·결정을 만들지 말 것. 발언 주체가 불명확하면 "(주체 불명확)"으로 표기.
- STT 오타는 문맥과 메타데이터(용어집 역할)로 정규화하되, 없는 사실을 지어내는 것은 금지.
- 각 항목 끝에 근거 발언 원문 일부(20자 내외)를 \`근거: "…"\` 로 붙인다.
- 조각 경계에서 잘린 문장은 무리하게 해석하지 말고 "(조각 경계에서 잘림)"으로 표기.

[메타데이터]
${metaBlock}

[녹취록 조각 ${segIndex}/${segTotal}]
\`\`\`
${segment}
\`\`\`

# 출력 형식 (이 조각에 해당 항목이 없으면 "없음")
## 발언자
(이 조각에 등장한 발언자 이름/ID 목록)
## 사실(Fact)
- [발언자] 내용 — 근거: "…"
## 논의(Discussion)
- [발언자] 내용 — 근거: "…"
## 결정(Decision)
- 내용 — 근거: "…"
## 리스크/이슈
- 내용 — 근거: "…"
## 액션(Action)
- [담당] 작업 내용 (기한: …) — 근거: "…"
## 언급된 수치·날짜·금액
- 항목: 값 — 근거: "…"`;
}

/**
 * [병합 단계 — Reduce] 조각별 추출 노트를 합쳐 최종 회의록을 작성한다.
 * 입력은 원문이 아니라 추출 노트이므로, 노트에 없는 내용을 추가하면 안 된다.
 */
export function buildMeetReducePrompt(notes: string, metadata: string): string {
    const metaBlock = metadata.trim() || '(메타데이터 미입력 — 노트에서 추론하거나 "확인 불가"로 표기)';
    return `# 임무
긴 회의 녹취록을 조각별로 추출한 노트들이 아래에 있다. 이 노트만 근거로 최종 회의록(Actionable Minutes)을 작성하라.

# 규칙
- **노트에 있는 내용만** 사용한다. 노트에 없는 사실·수치·결정을 추가하지 말 것.
- 같은 주제가 여러 조각에 흩어져 있으면 주제별로 다시 묶는다(Topic Reclustering). 단, 서로 다른 발언을 하나의 인과 사슬로 합성하지 말 것.
- 발언 주체 귀속을 그대로 유지한다. "(주체 불명확)" 항목에 임의로 이름을 붙이지 말 것.
- 중복 항목은 병합하되 근거 인용은 유지한다. 결정(Decision)은 명시적 합의가 노트에 있을 때만 '결정됨'.
- 메타데이터와 노트가 충돌하면 메타데이터를 우선한다.

[메타데이터]
${metaBlock}

[조각별 추출 노트]
${notes}

${OUTPUT_FORMAT}`;
}

/**
 * [검증 패스 — 옵션] 완성된 회의록의 결정·액션·수치가 근거 소스(녹취록 또는
 * 추출 노트)에 실제로 존재하는지 대조한다. 날조 검출용 2차 방어선.
 */
export function buildMeetVerifyPrompt(report: string, source: string): string {
    return `# 임무
아래 [회의록]의 '결정 사항'과 '액션 아이템'(및 그 안의 수치·날짜·금액)을 [근거 소스]와 대조하라.

# 규칙
- 각 항목의 내용이 근거 소스에서 확인되면 통과. 찾을 수 없으면 FLAG.
- 표기·철자 차이는 무시하고 의미로 대조한다 (STT 보정 감안).
- 새 해석·제안을 추가하지 말 것. 판정만 한다.

# 출력 형식
- 모든 항목이 확인되면 정확히 한 줄: \`검증 통과\`
- FLAG 가 있으면 항목별로:
  - ❗ [결정|액션] "<항목 요약>" — 근거 소스에서 확인 불가: <짧은 사유>

[회의록]
${report}

[근거 소스]
\`\`\`
${source}
\`\`\``;
}
