import type { ScriptContext } from '../../shared/input.types';
import { buildRichFactBlock, buildDeepExtensions } from '../../shared/fact-block';
import type { DeepPlan, DeepWriteInput, DeepVerifyInput } from './types';

/** 深度档事实块 = 标准厚块 + 深度扩展(价值/风险 + 历史联系);三步共用,给"分析"全信息 */
function deepFacts(ctx: ScriptContext): string {
  const ext = buildDeepExtensions(ctx);
  return ext ? `${buildRichFactBlock(ctx)}\n\n${ext}` : buildRichFactBlock(ctx);
}

/** 步骤1:规划 user prompt —— 深度厚事实块(全信息),产出大纲由 plan 的 system + schema 约束 */
export function buildPlanPrompt(ctx: ScriptContext): string {
  return `${deepFacts(ctx)}

---
# 你的任务(本步:规划,不写话术)
基于以上事实,规划这通回访电话拆成几段、每段讲什么。要点须来自上面事实,不编造。

按"从果(目标)倒推到因"来排:先想清这通电话要达成的果(让患者明白该回来处理本次问题),再倒推为达成它患者需要先被讲清什么,据此把内容排成**层层递进、逻辑清晰**的段落(每段 intent 写明承上启下;具体怎么分段由你定,不套固定段式)。后果要客观说清、但不吓唬不推销。段数 3-6。`;
}

/** 步骤2:写 user prompt —— 深度厚事实块 + 上一步大纲(+ repair:上一稿 + 逐条修正约束) */
export function buildWritePrompt(input: DeepWriteInput): string {
  const outline = renderPlanOutline(input.plan);

  // ── repair 轮:不是"凭大纲重写",而是"在上一稿上,严格按自检逐条改" ──
  if (input.repairIssues?.length) {
    const prev = input.prevDraft
      ? input.prevDraft.sections.map((s, i) => `### 第${i + 1}段:${s.title}\n${s.markdown}`).join('\n\n')
      : '(上一稿缺失,按大纲重写并满足下列修正)';
    const issues = input.repairIssues
      .map((it, i) => `${i + 1}. 【${it.section}】问题:${it.problem}\n   必须改成:${it.fix}`)
      .join('\n');
    return `${deepFacts(input.ctx)}

---
# 本步任务:修订(不是重写)
上一稿没通过【接地 + 安全】自检。**在上一稿基础上,严格逐条改掉下面每一处问题**,改完输出完整修订稿。

## 上一稿(待修订)
${prev}

## 必须修正的问题(逐条,缺一不可)
${issues}

## 修订铁律
- 上面每一条都必须改到位,**一条都不能漏**;改法以"必须改成"为准。
- **只动被点名的地方**,其余句子保持原样,不要顺手重写或新增事实。
- 修正不得引入新的违规:不报价/不承诺疗效/不写死具体时间(用【时间段】占位)/≤18 岁不提拍片。
- 段落结构沿用上一稿(标题可不变),输出完整的多段话术。`;
  }

  return `${deepFacts(input.ctx)}

---
# 本步大纲(按它逐段写,可微调措辞,不要新增事实)
${outline}

# 写的时候保持
- **层层递进、逻辑层次清晰**:顺着大纲推进,段与段承上启下,别并列罗列或跳跃。
- **后果说清但有分寸**:不处理的后果客观讲明(结合病历 + 牙科常识),让患者理解严重性;但**不夸大、不吓唬(别下"会掉光""很危险"式吓人结论)、不推销促单报价**——为患者着想地讲,不是吓他/催他。`;
}

/** 步骤3:独立对抗校验 user prompt —— 事实 + 待验草稿(新开上下文,对抗) */
export function buildVerifyPrompt(input: DeepVerifyInput): string {
  const draft = input.draft.sections
    .map((s, i) => `### 第${i + 1}段:${s.title}\n${s.markdown}`)
    .join('\n\n');
  return `${deepFacts(input.ctx)}

---
# 你的任务(本步:对抗校验,不改写)
逐句核对下面这份话术草稿:
1. **接地**:每个说法能否追到上面"本次回访患者信息"里的事实?追不到 = 编造 → 记 issue。
2. **安全**:有无报价/费用、疗效承诺、写死具体时间(应保留【时间段】)、≤18 提拍片?有 = 越界 → 记 issue。
3. **逻辑与分寸**:
   - 从果推因:是否围绕"让患者明白该回来处理本次问题"展开,没跑题;
   - 层层递进:段与段是否层层递进、承上启下,而非并列罗列 / 跳跃 / 重复;
   - 逻辑层次清晰:该说的有没有缺(点了问题没说后果、说了后果没给到诊出路);
   - 把后果说清但不越界:不处理的后果是否客观说明了?有没有**吓唬/制造恐慌**("会掉光""很危险"式)或**推销/促单/施压**口吻?以上任一不到位 → 记 issue。
4. **患者听得懂**:有无诊断代码(如 K08)、英文/内部枚举、生硬术语,或含糊其辞("上小磨牙或下小磨牙"没说清哪颗)?有 = 记 issue,要求改成大白话/说清。
①②③④ 全部通过 → pass=true、issues 空;任一不过 → pass=false 并逐条列出(段、问题、修法)。

## 待校验草稿
${draft}`;
}

function renderPlanOutline(plan: DeepPlan): string {
  return plan.sections
    .map(
      (s, i) =>
        `${i + 1}. 【${s.title}】(${s.intent})\n${s.points.map((p) => `   - ${p}`).join('\n')}`,
    )
    .join('\n');
}
