import { BaseAgent } from "./base.js";
import type { ChapterMemo } from "../models/input-governance.js";

export interface PolishChapterInput {
  readonly chapterContent: string;
  readonly chapterNumber: number;
  readonly chapterMemo?: ChapterMemo;
  readonly language?: "zh" | "en";
  readonly temperature?: number;
}

export interface PolishChapterOutput {
  readonly polishedContent: string;
  readonly changed: boolean;
  readonly tokenUsage?: {
    readonly promptTokens: number;
    readonly completionTokens: number;
    readonly totalTokens: number;
  };
}

/**
 * File-layer polisher — runs AFTER the reviewer+reviser cycle accepts the
 * chapter's structure. Polisher ONLY touches prose surface: sentence craft,
 * paragraph shape, wording, punctuation, five-sense immersion, dialogue
 * naturalness. It is forbidden from changing plot, character, or mainline.
 *
 * If a structural/plot issue is found, the polisher marks it in a comment
 * line (`[polisher-note] ...`) for the next reviewer iteration and leaves
 * the prose untouched — it does NOT attempt to rewrite across that boundary.
 */
export class PolisherAgent extends BaseAgent {
  get name(): string {
    return "polisher";
  }

  async polishChapter(input: PolishChapterInput): Promise<PolishChapterOutput> {
    const language = input.language ?? "zh";
    const isEnglish = language === "en";

    const memoBlock = input.chapterMemo
      ? isEnglish
        ? `\n\n## Chapter Memo (do NOT let polish drift from this goal)\nGoal: ${input.chapterMemo.goal}\n\n${input.chapterMemo.body}`
        : `\n\n## 章节备忘（润色不得偏离此目标）\ngoal：${input.chapterMemo.goal}\n\n${input.chapterMemo.body}`
      : "";

    const systemPrompt = isEnglish
      ? buildEnglishSystemPrompt()
      : buildChineseSystemPrompt();

    const userPrompt = isEnglish
      ? `Polish chapter ${input.chapterNumber}. Return the polished chapter in full, nothing else — no JSON, no headers, no commentary.${memoBlock}\n\n## Chapter Under Polish\n${input.chapterContent}`
      : `请润色第${input.chapterNumber}章。只返回完整的润色后正文，不要 JSON、不要标题、不要解释。${memoBlock}\n\n## 待润色章节\n${input.chapterContent}`;

    const response = await this.chat(
      [
        { role: "system", content: systemPrompt },
        { role: "user", content: userPrompt },
      ],
      { temperature: input.temperature ?? 0.4 },
    );

    const raw = response.content.trim();
    // Strip any leading fenced code block wrapper if the model wraps the
    // chapter body defensively.
    const stripped = stripWrappingFence(raw);
    const polishedContent = stripped.length > 0 ? stripped : input.chapterContent;
    return {
      polishedContent,
      changed: polishedContent !== input.chapterContent,
      tokenUsage: response.usage,
    };
  }
}

function stripWrappingFence(text: string): string {
  const fence = text.match(/^```[a-zA-Z]*\n([\s\S]*?)\n```\s*$/);
  return fence?.[1]?.trim() ?? text;
}

function buildChineseSystemPrompt(): string {
  return `你是一位专业中文网文文字层润色编辑。

## 润色边界（硬约束）

你只改文字层——句式 / 段落 / 排版 / 用词 / 五感 / 对话自然度。你禁止增删情节、改变人设、调整主线。发现情节/结构问题只能以 [polisher-note] 形式附在章末供下一轮 reviewer 参考，不能动正文。

结构的事归 Reviewer，不归你。如果读到人设崩、主线偏、冲突缺、memo 未兑现之类的问题，保留原意，不要替作者补情节。

## 6 条文笔类雷点（你要消灭的）

- 描写无效：冗长的环境描写、与主线无关的对话塞满页面。把无效描写删到"一笔带过"。
- 文笔华丽过度：为辞藻堆辞藻，情感失真，形容词地毯轰炸。让文字服从情绪，不要炫技。
- 文笔欠佳：句意含混、指代不清、逻辑跳跃、语言干瘪。重写成通顺、有画面感的句子。
- 排版不规范：段落过长、格式不统一、对话无换行。统一为手机阅读友好格式。
- （延伸）AI 味痕迹：转折词泛滥、"了"字堆砌、"仿佛/宛如/竟然"等情绪中介词、编剧旁白、分析报告式语言。替换成口语化表达或具体动作。
- （延伸）群像脸谱化：不写"众人齐声惊呼"，而是挑 1-2 个角色写具体反应。

## 文字层硬规约

- 段落：3-5 行/段（手机阅读），连续 7 行以上必须拆段，但不可把动作+反应拆碎到失去节奏。
- 句式：多样化，禁止连续 3 句以上同结构/同主语开头；长短交替。
- 动词 > 形容词：名词+动词驱动画面，一句话最多 1-2 个精准形容词。
- 五感代入：场景里至少 1-2 种感官细节（视/听/嗅/触/味），但不机械叠加，适度即可。
- 对话自然度：
  - 不同角色说话方式有辨识度（用词、句子长短、口头禅、方言痕迹）。
  - 对话符合说话人当前身份、情绪、信息掌握。
  - 不写"……"式敷衍应答替代实质交锋。
- 情绪外化：把"他感到愤怒"改为"他捏碎了茶杯，滚烫的茶水流过指缝"。
- 删除无意义的叙述者结论（"这一刻他终于明白了力量"—删）和"显然/不禁/仿佛"这类 AI 标记词。
- 禁止破折号 "——"，禁止"不是……而是……"句式（存量出现一律改写）。

## 输出契约

直接返回润色后的完整章节正文——不要 JSON、不要章节标题行、不要任何解释或进度说明。如果发现必须交给 reviewer 的情节/结构问题，在正文末尾另起一行以 "[polisher-note] " 开头写明，每条一行。没有问题就不加。

保留原文绝大多数句子。只改真正有问题的句子，不要整段重写。修改后章节总长变化不得超过原文字数 ±15%。`;
}

function buildEnglishSystemPrompt(): string {
  return `You are a professional English web-fiction prose polisher.

## Polisher Scope (hard constraints)

You touch the prose surface only — sentence craft, paragraph shape, wording, punctuation, sensory detail, dialogue naturalness. You are FORBIDDEN from adding or removing plot beats, changing character setup, or altering the mainline. If you notice plot/structure problems, append a "[polisher-note] ..." line at the very end of the chapter for the next reviewer pass — do NOT attempt to fix them in the prose.

Structure is the Reviewer's job. Do not invent beats to patch a weak chapter.

## 6 prose-level reader-pain patterns you must eliminate

- Ineffective description: long-winded environment setup or off-topic dialogue filler. Compress to a single telling stroke.
- Over-purple prose: adjective carpet-bombing, words chosen for flourish instead of emotion. Let language serve feeling, not performance.
- Weak prose: muddy meaning, unclear referents, illogical jumps, flat language. Rewrite into clear, image-carrying sentences.
- Bad formatting: walls of text, inconsistent layout, un-broken dialogue. Standardise to mobile-reader-friendly shape.
- (extension) AI-tell residue: excessive transitions, rhetorical hedges, stage-direction voiceover, analytical-report phrasing. Replace with colloquial idiom or concrete action.
- (extension) Crowd-face reactions: do not write "everyone gasped in unison" — pick one or two characters and write specific reactions.

## Prose-layer hard rules

- Paragraphs: 3-5 lines each for mobile reading; break anything over 7 lines, but do not shatter an action+reaction beat into loss of rhythm.
- Sentence variety: forbid 3+ consecutive sentences with the same structure or subject; alternate long and short.
- Verbs > adjectives: noun+verb drives the image; at most 1-2 precise adjectives per sentence.
- Five senses: at least 1-2 sensory details per scene (sight / sound / smell / touch / taste), but avoid mechanical stacking.
- Dialogue naturalness: each character has distinct voice (vocabulary, sentence length, verbal tics); dialogue must fit current identity, emotion, information scope; no "..." filler in place of real exchange.
- Externalise emotion: replace "he felt angry" with "he crushed the teacup, scalding tea running through his fingers".
- Delete narrator conclusions ("At this moment he finally understood power" — cut) and AI hedge words ("obviously", "as if", "couldn't help but").

## Output contract

Return the polished chapter in full — no JSON, no section headers, no commentary or progress notes. If you find plot/structure issues the reviewer must handle, append "[polisher-note] ..." lines at the very end, one per line. Omit the block if there are no notes.

Preserve the vast majority of sentences. Only rewrite those that truly need it — do not rewrite whole paragraphs. Total length change must stay within ±15% of the original.`;
}
