/**
 * 内容一致性跟踪器（事中预防）
 *
 * 解决 issue：质量检查是"事后纠错"，问题发现得晚，rewrite 成本高。
 *
 * 在内容生成过程中维护一个运行中的"全书术语表/关键概念档案"，
 * 每章生成后自动校验关键术语和逻辑是否一致，发现问题可即时触发修正。
 *
 * 核心思路：
 *   - 逐章/逐节生成时，提取并缓存关键术语、定义、角色设定
 *   - 后续章节生成后，快速比对缓存中的术语定义是否一致
 *   - 发现冲突立即记录，生成完成后汇总报告
 */

/** 术语定义记录 */
export interface TermRecord {
  term: string;           // 术语/概念名
  definition: string;     // 定义/描述
  firstChapter: number;   // 首次出现的章节号
  chapterOccurrences: number[]; // 出现的章节号列表
}

/** 一致性检查结果 */
export interface ConsistencyIssue {
  type: 'conflicting_definition' | 'missing_definition' | 'inconsistent_naming' | 'logical_contradiction';
  severity: 'high' | 'medium' | 'low';
  term: string;
  chapterA: number;
  chapterB?: number;
  description: string;
}

/** 一致性报告 */
export interface ConsistencyReport {
  terms: TermRecord[];
  issues: ConsistencyIssue[];
  hasConflicts: boolean;
}

export class BookConsistencyTracker {
  private terms: Map<string, TermRecord> = new Map();
  private chapterContentCache: Map<number, string> = new Map();
  private issues: ConsistencyIssue[] = [];

  /**
   * 记录一个新生成的章节内容，提取关键术语。
   */
  registerChapter(
    chapterNumber: number,
    chapterTitle: string,
    content: string
  ): void {
    this.chapterContentCache.set(chapterNumber, content);

    // 简单正则提取可能的术语定义模式（中文常见格式）
    // 模式1：xxx 是指 / xxx 指的是 / xxx 定义为
    const definitionPatterns = [
      /([^\s，,。.；;]{2,15})[（(]([^）)]{2,20})[）)]/g,           // 术语（英文/缩写）
      /([^\s，,。.；;]{2,20})(?:是指|指的是|定义为|即|也就是|意为)\s*([^\s，,。.；;]{2,30})/g, // 术语是指xxx
    ];

    for (const pattern of definitionPatterns) {
      let match: RegExpExecArray | null;
      while ((match = pattern.exec(content)) !== null) {
        const term = match[1].trim();
        const definition = match[2].trim();

        // 过滤太短的噪声
        if (term.length < 2 || definition.length < 1) continue;

        const existing = this.terms.get(term);
        if (existing) {
          existing.chapterOccurrences.push(chapterNumber);
          // 检查定义是否冲突
          if (existing.definition !== definition &&
              this.levenshteinSimilarity(existing.definition, definition) < 0.6) {
            this.issues.push({
              type: 'conflicting_definition',
              severity: 'high',
              term,
              chapterA: existing.firstChapter,
              chapterB: chapterNumber,
              description: `术语"${term}"在第${existing.firstChapter}章定义为"${existing.definition}"，第${chapterNumber}章定义为"${definition}"，差异较大`,
            });
          }
        } else {
          this.terms.set(term, {
            term,
            definition,
            firstChapter: chapterNumber,
            chapterOccurrences: [chapterNumber],
          });
        }
      }
    }
  }

  /**
   * 获取全书术语摘要，可嵌入后续章节的提示词中
   * @param maxTerms 最多返回的术语数
   * @param currentChapter 当前正在生成的章节号（排除该章自身的术语）
   */
  getTermContext(maxTerms: number = 20, currentChapter?: number): string {
    const entries = Array.from(this.terms.values())
      .filter(t => currentChapter === undefined || !t.chapterOccurrences.includes(currentChapter))
      .slice(0, maxTerms);

    if (entries.length === 0) return '';

    const lines = entries.map(t =>
      `- ${t.term}：${t.definition}（见第${t.firstChapter}章）`
    );
    return `\n## 已建立的关键概念/术语（请保持一致定义）\n${lines.join('\n')}`;
  }

  /**
   * 获取所有发现的一致性问题
   */
  getIssues(): ConsistencyIssue[] {
    return [...this.issues];
  }

  /**
   * 生成完整的术语一致性报告
   */
  generateReport(): ConsistencyReport {
    return {
      terms: Array.from(this.terms.values()),
      issues: [...this.issues],
      hasConflicts: this.issues.length > 0,
    };
  }

  /**
   * 简单字符串相似度（Levenshtein 距离比）
   */
  private levenshteinSimilarity(a: string, b: string): number {
    const maxLen = Math.max(a.length, b.length);
    if (maxLen === 0) return 1;
    const distance = this.levenshteinDistance(a, b);
    return 1 - distance / maxLen;
  }

  private levenshteinDistance(a: string, b: string): number {
    const matrix: number[][] = [];
    for (let i = 0; i <= a.length; i++) {
      matrix[i] = [i];
    }
    for (let j = 0; j <= b.length; j++) {
      matrix[0][j] = j;
    }
    for (let i = 1; i <= a.length; i++) {
      for (let j = 1; j <= b.length; j++) {
        if (a[i - 1] === b[j - 1]) {
          matrix[i][j] = matrix[i - 1][j - 1];
        } else {
          matrix[i][j] = Math.min(
            matrix[i - 1][j] + 1,
            matrix[i][j - 1] + 1,
            matrix[i - 1][j - 1] + 1
          );
        }
      }
    }
    return matrix[a.length][b.length];
  }
}
