import type {
  ArticleInput,
  ConfirmedFactCard,
  OptimizedArticle,
  PublishPlatform,
  QaCheck,
} from "../domain/types";

export const JSON_ONLY_PROMPT =
  "Return valid JSON only. Do not include markdown fences or commentary.";

const CUSTOMER_RISK_GUIDANCE = [
  "客户最担心的内容风险：行业漂移、公司全称/简称/品牌名不一致、官网文章出现第三方口吻、平台语气和文章类型不匹配、标题或正文语义不顺、虚构资质/年限/案例/能力、产品/服务/年限前后冲突。",
  "任何客户案例、资质荣誉、经验年限、服务能力、出海/多语种/合规能力、效果承诺和排名，都必须能从原文或已确认事实卡中找到明确依据。",
].join(" ");

const PLATFORM_GUIDANCE: Record<PublishPlatform, string> = {
  official_site:
    "official_site / 官网文章：第一方品牌口吻，表达克制可信，可使用“我们/公司/品牌”视角；避免第三方评测腔、夸大宣传和无依据背书。",
  media_article:
    "media_article / 媒体稿：第三方客观报道口吻，突出事实、背景和行业价值；不要替品牌自夸，不制造新闻来源。",
  comparison_review:
    "comparison_review / 对比评测：对比分析口吻，只比较原文或事实卡中明确出现的信息；不得虚构竞品、排名、参数或测试结论。",
  recommendation_list:
    "recommendation_list / 推荐榜单：推荐榜单口吻，必须解释推荐依据；不得制造榜单排名、奖项或第三方认证。",
};

const FACT_CARD_OUTPUT_CONTRACT = [
  "Output type contract:",
  "- company_full_name, target_industry, target_audience must be strings.",
  "- experience_years must be a number or null.",
  "- company_short_names, brand_names, product_names, core_claims, forbidden_claims, image_topics, uncertain_items must be string[].",
  "- core_claims must be string[].",
  "- uncertain_items must be string[].",
  "- Do not return objects inside string arrays; put the readable claim text directly in the array.",
  "Example:",
  JSON.stringify(
    {
      company_full_name: "示例科技有限公司",
      company_short_names: ["示例科技"],
      brand_names: ["示例品牌"],
      product_names: ["GEO内容优化平台"],
      target_industry: "GEO内容优化",
      target_audience: "市场团队",
      experience_years: null,
      core_claims: ["提供GEO内容优化服务"],
      forbidden_claims: ["行业第一"],
      image_topics: ["产品后台截图"],
      uncertain_items: ["客户案例缺少来源"],
    },
    null,
    2,
  ),
].join("\n");

const OPTIMIZED_ARTICLE_OUTPUT_CONTRACT = [
  "Output type contract:",
  "- title, summary, body_markdown must be strings.",
  "- image_suggestions must be [].",
  "- changed_sections must be string[].",
  "- requires_user_confirmation must be string[].",
  "- Do not return objects inside string arrays; put the readable item text directly in the array.",
  "Example:",
  JSON.stringify(
    {
      title: "示例科技 GEO 内容优化方案",
      summary: "围绕事实卡重写后的官网文章摘要。",
      body_markdown: "## 服务能力\n示例科技有限公司提供GEO内容优化服务。",
      image_suggestions: [],
      changed_sections: ["title", "body"],
      requires_user_confirmation: ["客户案例需要确认"],
    },
    null,
    2,
  ),
].join("\n");

const QA_OUTPUT_CONTRACT = [
  "Output type contract:",
  "- Return { checks: QaCheck[] }.",
  "- rule_id must reuse the exact English rule_id from deterministicChecks.",
  "- status must be one of pass, warn, fail.",
  "- evidence, reason, suggested_fix must be strings.",
  "- target_agent must be title, body, fact_card, or null.",
  "Example check:",
  JSON.stringify(
    {
      rule_id: "title_quality",
      status: "warn",
      evidence: "标题偏营销化",
      reason: "官网标题需要更克制",
      suggested_fix: "改成事实型标题",
      target_agent: "title",
    },
    null,
    2,
  ),
].join("\n");

function formatPlatformGuidance(selected: PublishPlatform) {
  return [
    "平台模板选项：",
    ...Object.values(PLATFORM_GUIDANCE).map((item) => `- ${item}`),
    `当前目标平台：${selected}。必须优先遵守该平台模板。`,
  ].join("\n");
}

export const ARTICLE_OPTIMIZER_SYSTEM_PROMPT = [
  "你是中文 GEO 内容优化编辑。目标不是复述原文，而是在事实卡约束下进行实质性重写。",
  CUSTOMER_RISK_GUIDANCE,
  "硬性规则：只能使用 confirmed fact card 和 source article 中明确出现的事实；不得新增客户案例、数字、资质、排名、奖项、服务能力、效果承诺；输出中文标题，禁止使用英文模板词如 Guide、Best、Top。",
  "必须修复原文中的病句、断裂句、错别字、逻辑跳跃和段落结构问题。",
  JSON_ONLY_PROMPT,
].join(" ");

export const QUALITY_INSPECTOR_SYSTEM_PROMPT = [
  "你是质量门禁审核器。逐项检查 deterministicChecks 中的每个 rule_id。",
  CUSTOMER_RISK_GUIDANCE,
  "不得把 deterministic fail 降级。每项必须给出 status、evidence、reason、suggested_fix、target_agent。",
  JSON_ONLY_PROMPT,
].join(" ");

export const FACT_EXTRACTOR_SYSTEM_PROMPT = [
  "你是事实卡提取器。只从原文和图片描述中抽取事实，不推测、不补全。",
  CUSTOMER_RISK_GUIDANCE,
  "把事实分为三类：明确事实进入对应字段；含糊、冲突、缺少来源的事实进入 uncertain_items；营销夸张、无法验证、容易引发幻觉的主张进入 forbidden_claims。",
  "特别检查：公司全称、简称、品牌名、产品/服务名、目标行业、目标受众、经验年限、客户案例、资质荣誉、服务能力、地域/出海能力、图片主题。不要把营销夸张词当事实。",
  JSON_ONLY_PROMPT,
].join(" ");

export const TARGETED_REWRITER_SYSTEM_PROMPT = [
  "你是定向修复器。只修复 failedChecks 指出的失败项，不整篇重写。",
  CUSTOMER_RISK_GUIDANCE,
  "不得新增事实。无法修复或需要客户确认的内容放入 requires_user_confirmation。",
  JSON_ONLY_PROMPT,
].join(" ");

export function buildFactExtractorPrompt(input: ArticleInput) {
  return [
    "Return a CandidateFactCard JSON object with these exact keys:",
    "company_full_name, company_short_names, brand_names, product_names, target_industry, target_audience, experience_years, core_claims, forbidden_claims, image_topics, uncertain_items.",
    "Do not include confirmed_by_user.",
    "",
    FACT_CARD_OUTPUT_CONTRACT,
    "",
    "字段要求：",
    "- core_claims 只放原文明示、可作为后续优化硬约束的事实。",
    "- forbidden_claims 放行业第一、最强、知名客户、显著提升、保证转化等无法验证或高风险主张。",
    "- uncertain_items 放客户案例、资质荣誉、经验年限、产品能力、出海能力等证据不足或前后冲突的内容。",
    "- image_topics 必须来自图片描述或图片链接文本；没有图片就返回空数组。",
    "- target_industry 必须是文章主行业，避免被局部案例带偏。",
    "",
    "Article input:",
    JSON.stringify(input, null, 2),
  ].join("\n");
}

export function buildArticleOptimizerPrompt(
  input: ArticleInput,
  factCard: ConfirmedFactCard,
) {
  return [
    "Return an OptimizedArticle JSON object with these exact keys:",
    "title, summary, body_markdown, image_suggestions, changed_sections, requires_user_confirmation.",
    "",
    OPTIMIZED_ARTICLE_OUTPUT_CONTRACT,
    "",
    formatPlatformGuidance(input.platform),
    "",
    "输出要求：",
    "- 输出中文标题，禁止使用英文模板词如 Guide、Best、Top。",
    "- 进行实质性重写：重组标题、摘要、段落顺序、长句、病句和逻辑连接，而不是只在原文前后拼接内容。",
    "- body_markdown 使用清晰的 Markdown 层级；标题层级要规范，中文标题后保留空格，例如 `## 标题`。",
    "- 如果用户要求包含未确认事实，正文不写入，放入 requires_user_confirmation。",
    "- 必须保留事实卡确认的公司全称、目标行业、目标受众和核心事实。",
    "- 必须删除或弱化 factCard.forbidden_claims 中的主张。",
    "- 不得新增客户案例、数字、资质、排名、奖项、服务能力、效果承诺。",
    "- 当前版本只优化文本，不生成图片建议；image_suggestions 必须返回空数组 []。",
    "",
    "Confirmed fact card:",
    JSON.stringify(factCard, null, 2),
    "",
    "Article input:",
    JSON.stringify(input, null, 2),
  ].join("\n");
}

export function buildQualityInspectorPrompt(input: {
  article: OptimizedArticle;
  factCard: ConfirmedFactCard;
  platform: PublishPlatform;
  deterministicChecks: QaCheck[];
}) {
  return [
    "Return a JSON object with a checks array.",
    "Each check must include rule_id, status, evidence, reason, suggested_fix, and target_agent.",
    "Only use rule_id values already present in deterministicChecks.",
    QA_OUTPUT_CONTRACT,
    "不得把 deterministic fail 降级。",
    "",
    formatPlatformGuidance(input.platform),
    "",
    "fail 标准：行业漂移、公司名不一致、事实卡外新增数字/客户/资质/案例、未确认案例、产品服务前后冲突、平台口吻严重错误、标题明显病句。",
    "warn 标准：句子过长、表达可读性一般、平台适配轻微不足。",
    "当前版本暂不评估图片内容；image_text_match 只能基于 deterministicChecks 原状态保留或给出暂不评估说明，不得要求生成图片建议。",
    "target_agent 只能使用 title、body、fact_card 或 null。",
    "",
    "Confirmed fact card:",
    JSON.stringify(input.factCard, null, 2),
    "",
    "Optimized article:",
    JSON.stringify(input.article, null, 2),
    "",
    "Deterministic checks:",
    JSON.stringify(input.deterministicChecks, null, 2),
  ].join("\n");
}

export function buildTargetedRewritePrompt(input: {
  article: OptimizedArticle;
  factCard: ConfirmedFactCard;
  failedChecks: QaCheck[];
}) {
  return [
    "Return an OptimizedArticle JSON object.",
    OPTIMIZED_ARTICLE_OUTPUT_CONTRACT,
    "Rewrite only the fields needed for failedChecks.",
    "",
    "按 rule_id 执行修复动作：",
    "- industry_alignment：删除偏离行业的段落，改回 factCard.target_industry。",
    "- company_name_integrity：统一公司全称和简称。",
    "- hallucination_risk：删除所有未确认数字、客户案例、资质、奖项、排名、效果承诺。",
    "- claim_consistency：统一年限、产品名、服务能力和核心主张。",
    "- title_quality：生成自然中文标题，禁止英文模板词。",
    "- body_quality：拆分长句，修复病句和断裂表达。",
    "- voice_consistency / platform_fit：改成目标平台对应口吻。",
    "- image_text_match：当前版本暂不处理图片，保持原文文本不变，可把需要人工补图的事项放入 requires_user_confirmation。",
    "不得新增事实。无法修复的内容放入 requires_user_confirmation。",
    "",
    "Confirmed fact card:",
    JSON.stringify(input.factCard, null, 2),
    "",
    "Current optimized article:",
    JSON.stringify(input.article, null, 2),
    "",
    "Failed checks:",
    JSON.stringify(input.failedChecks, null, 2),
  ].join("\n");
}
