import { Injectable } from '@nestjs/common';
import {
  KnowledgeChunkEntity,
  ChunkType,
  ChunkMetadata,
} from '../../domain/entities/knowledge-chunk.entity';
import { KnowledgeArticleEntity } from '../../domain/entities/knowledge-article.entity';

/**
 * 文本分块策略配置
 */
export interface ChunkingConfig {
  /** 最大块大小（字符数） */
  maxChunkSize: number;
  /** 块重叠大小 */
  overlapSize: number;
  /** 是否按语义边界分割 */
  semanticSplit: boolean;
}

const DEFAULT_CONFIG: ChunkingConfig = {
  maxChunkSize: 500,
  overlapSize: 50,
  semanticSplit: true,
};

/**
 * 文本分块服务
 * 将长文本智能分割为适合检索的小块
 */
@Injectable()
export class ChunkingService {
  /**
   * 将文章内容分割为块
   */
  chunkArticle(
    article: KnowledgeArticleEntity,
    config: ChunkingConfig = DEFAULT_CONFIG,
  ): KnowledgeChunkEntity[] {
    const content = article.content;

    // 检测内容格式
    if (this.isMarkdown(content)) {
      return this.chunkMarkdown(article.id, content, config);
    }

    // 纯文本分块
    return this.chunkPlainText(article.id, content, config);
  }

  /**
   * 检测是否为Markdown格式
   */
  private isMarkdown(content: string): boolean {
    const markdownPatterns = [
      /^#+\s/m,           // 标题
      /\*\*.+\*\*/,       // 加粗
      /\[.+\]\(.+\)/,     // 链接
      /^-\s/m,            // 列表
      /^\d+\.\s/m,        // 有序列表
      /```/,              // 代码块
    ];

    return markdownPatterns.some(pattern => pattern.test(content));
  }

  /**
   * Markdown内容分块
   */
  private chunkMarkdown(
    articleId: string,
    content: string,
    config: ChunkingConfig,
  ): KnowledgeChunkEntity[] {
    const chunks: KnowledgeChunkEntity[] = [];
    const sections = this.splitByHeadings(content);

    let chunkIndex = 0;
    let currentSectionTitle = '';

    for (const section of sections) {
      // 更新当前章节标题
      const headingMatch = section.match(/^(#+)\s+(.+)$/m);
      if (headingMatch) {
        currentSectionTitle = headingMatch[2];
      }

      // 如果章节内容过长，进一步分割
      if (section.length > config.maxChunkSize) {
        const subChunks = this.splitLongSection(section, config);

        for (const subContent of subChunks) {
          const chunkType = this.detectChunkType(subContent);
          const metadata: ChunkMetadata = {
            sectionTitle: currentSectionTitle,
            headingLevel: headingMatch ? headingMatch[1].length : undefined,
          };

          const chunk = KnowledgeChunkEntity.create({
            articleId,
            content: subContent.trim(),
            chunkIndex,
            chunkType,
            metadata,
          });

          // 设置前后链接
          if (chunks.length > 0) {
            metadata.prevChunkId = chunks[chunks.length - 1].id;
            chunks[chunks.length - 1].metadata.nextChunkId = chunk.id;
          }

          chunks.push(chunk);
          chunkIndex++;
        }
      } else if (section.trim()) {
        const chunkType = this.detectChunkType(section);
        const metadata: ChunkMetadata = {
          sectionTitle: currentSectionTitle,
          headingLevel: headingMatch ? headingMatch[1].length : undefined,
        };

        const chunk = KnowledgeChunkEntity.create({
          articleId,
          content: section.trim(),
          chunkIndex,
          chunkType,
          metadata,
        });

        if (chunks.length > 0) {
          metadata.prevChunkId = chunks[chunks.length - 1].id;
          chunks[chunks.length - 1].metadata.nextChunkId = chunk.id;
        }

        chunks.push(chunk);
        chunkIndex++;
      }
    }

    return chunks;
  }

  /**
   * 按标题分割Markdown
   */
  private splitByHeadings(content: string): string[] {
    // 在标题前分割，但保留标题
    const parts = content.split(/(?=^#+\s)/m);
    return parts.filter(part => part.trim());
  }

  /**
   * 分割过长的章节
   */
  private splitLongSection(content: string, config: ChunkingConfig): string[] {
    const chunks: string[] = [];

    if (config.semanticSplit) {
      // 优先按段落分割
      const paragraphs = content.split(/\n\n+/);
      let currentChunk = '';

      for (const para of paragraphs) {
        if (currentChunk.length + para.length > config.maxChunkSize) {
          if (currentChunk) {
            chunks.push(currentChunk);
          }
          // 如果单个段落就超过限制，按句子分割
          if (para.length > config.maxChunkSize) {
            chunks.push(...this.splitBySentences(para, config));
          } else {
            currentChunk = para;
          }
        } else {
          currentChunk = currentChunk ? `${currentChunk}\n\n${para}` : para;
        }
      }

      if (currentChunk) {
        chunks.push(currentChunk);
      }
    } else {
      // 简单按字符数分割（带重叠）
      chunks.push(...this.splitBySize(content, config));
    }

    return chunks;
  }

  /**
   * 按句子分割
   */
  private splitBySentences(content: string, config: ChunkingConfig): string[] {
    // 中英文句子结束符
    const sentenceEndings = /([。！？.!?])/g;
    const sentences = content.split(sentenceEndings);

    const chunks: string[] = [];
    let currentChunk = '';

    for (let i = 0; i < sentences.length; i += 2) {
      const sentence = sentences[i] + (sentences[i + 1] || '');

      if (currentChunk.length + sentence.length > config.maxChunkSize) {
        if (currentChunk) {
          chunks.push(currentChunk);
        }
        currentChunk = sentence;
      } else {
        currentChunk += sentence;
      }
    }

    if (currentChunk) {
      chunks.push(currentChunk);
    }

    return chunks;
  }

  /**
   * 按大小分割（带重叠）
   */
  private splitBySize(content: string, config: ChunkingConfig): string[] {
    const chunks: string[] = [];
    let start = 0;

    while (start < content.length) {
      const end = Math.min(start + config.maxChunkSize, content.length);
      chunks.push(content.slice(start, end));
      start = end - config.overlapSize;
    }

    return chunks;
  }

  /**
   * 纯文本分块
   */
  private chunkPlainText(
    articleId: string,
    content: string,
    config: ChunkingConfig,
  ): KnowledgeChunkEntity[] {
    const textChunks = config.semanticSplit
      ? this.splitLongSection(content, config)
      : this.splitBySize(content, config);

    return textChunks.map((text, index) =>
      KnowledgeChunkEntity.create({
        articleId,
        content: text.trim(),
        chunkIndex: index,
        chunkType: ChunkType.PARAGRAPH,
      }),
    );
  }

  /**
   * 检测块类型
   */
  private detectChunkType(content: string): ChunkType {
    // 标题
    if (/^#+\s/.test(content)) {
      return ChunkType.TITLE;
    }

    // 代码块
    if (/```[\s\S]*```/.test(content)) {
      return ChunkType.CODE;
    }

    // 列表
    if (/^[-*]\s/m.test(content) || /^\d+\.\s/m.test(content)) {
      return ChunkType.LIST;
    }

    // 表格
    if (/\|.+\|/.test(content) && /\|-+\|/.test(content)) {
      return ChunkType.TABLE;
    }

    // FAQ（问答格式）
    if (/^[问Q][:：]/.test(content) || /^[答A][:：]/.test(content)) {
      return ChunkType.FAQ;
    }

    return ChunkType.PARAGRAPH;
  }

  /**
   * 为FAQ内容创建专门的块
   */
  createFAQChunks(
    articleId: string,
    faqs: Array<{ question: string; answer: string }>,
  ): KnowledgeChunkEntity[] {
    return faqs.map((faq, index) =>
      KnowledgeChunkEntity.create({
        articleId,
        content: `问：${faq.question}\n答：${faq.answer}`,
        chunkIndex: index,
        chunkType: ChunkType.FAQ,
        metadata: {
          hasKeywords: true,
        },
      }),
    );
  }
}
