package com.cloudhandson.vpdbackoffice.service;

import com.cloudhandson.vpdbackoffice.domain.vector.VectorChunk;
import java.util.ArrayList;
import java.util.List;

/**
 * Small, deterministic paragraph/sentence chunker for the demonstration flow.
 * Production ingestion can replace this with a tokenizer-aware chunker without
 * changing the tag/VPD data contract.
 */
public final class VectorChunker {

  private static final int MIN_CHUNK_SIZE = 80;
  private static final int MAX_CHUNK_SIZE = 2000;

  private VectorChunker() {
  }

  public static List<VectorChunk> chunk(String content, int requestedSize) {
    if (content == null || content.isBlank()) {
      throw new AppException("청킹할 문서 본문을 입력하세요.");
    }
    int chunkSize = Math.max(MIN_CHUNK_SIZE, Math.min(requestedSize <= 0 ? 600 : requestedSize, MAX_CHUNK_SIZE));
    List<VectorChunk> chunks = new ArrayList<>();
    String normalized = content.replace("\r\n", "\n").replace('\r', '\n').trim();
    String[] paragraphs = normalized.split("\\n\\s*\\n+");
    StringBuilder current = new StringBuilder();
    for (String paragraph : paragraphs) {
      String trimmed = paragraph.trim();
      if (trimmed.isEmpty()) {
        continue;
      }
      if (current.length() > 0 && current.length() + trimmed.length() + 1 > chunkSize) {
        appendChunks(chunks, current.toString(), chunkSize);
        current.setLength(0);
      }
      if (current.length() > 0) {
        current.append('\n');
      }
      current.append(trimmed);
    }
    if (current.length() > 0) {
      appendChunks(chunks, current.toString(), chunkSize);
    }
    if (chunks.isEmpty()) {
      throw new AppException("청킹할 문서 본문을 입력하세요.");
    }
    List<VectorChunk> numbered = new ArrayList<>();
    for (int index = 0; index < chunks.size(); index++) {
      numbered.add(new VectorChunk(index + 1, chunks.get(index).text()));
    }
    return List.copyOf(numbered);
  }

  private static void appendChunks(List<VectorChunk> chunks, String text, int chunkSize) {
    String remaining = text.trim();
    while (remaining.length() > chunkSize) {
      int cut = lastBreak(remaining, chunkSize);
      chunks.add(new VectorChunk(0, remaining.substring(0, cut).trim()));
      remaining = remaining.substring(cut).trim();
    }
    if (!remaining.isEmpty()) {
      chunks.add(new VectorChunk(0, remaining));
    }
  }

  private static int lastBreak(String text, int chunkSize) {
    int sentence = Math.max(text.lastIndexOf('.', chunkSize), text.lastIndexOf('。', chunkSize));
    if (sentence >= chunkSize / 2) {
      return sentence + 1;
    }
    int whitespace = text.lastIndexOf(' ', chunkSize);
    return whitespace >= chunkSize / 2 ? whitespace : chunkSize;
  }
}
