package com.lanyuanxiaoyao.service.ai.knowledge.service;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.lanyuanxiaoyao.service.ai.knowledge.entity.EmbeddingContext;
import com.lanyuanxiaoyao.service.ai.knowledge.entity.Knowledge;
import com.lanyuanxiaoyao.service.ai.knowledge.entity.vo.DataFileVO;
import com.yomahub.liteflow.core.FlowExecutor;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.eclipse.collections.api.factory.Lists;
import org.eclipse.collections.api.list.ImmutableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.document.Document;
import org.springframework.stereotype.Service;

/**
 * @author lanyuanxiaoyao
 * @version 20250522
 */
@Service
public class EmbeddingService {
  private static final Logger logger = LoggerFactory.getLogger(EmbeddingService.class);

  private final DataFileService dataFileService;
  private final FlowExecutor executor;
  private final KnowledgeService knowledgeService;
  private final GroupService groupService;
  private final ExecutorService executors = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

  @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
  public EmbeddingService(DataFileService dataFileService, FlowExecutor executor, KnowledgeService knowledgeService, GroupService groupService) {
    this.dataFileService = dataFileService;
    this.executor = executor;
    this.knowledgeService = knowledgeService;
    this.groupService = groupService;
  }

  public ImmutableList<Document> preview(String mode, String content) {
    if (content.length() > 2000) {
      content = content.substring(0, 2000);
    }
    EmbeddingContext context = EmbeddingContext.builder()
        .content(content)
        .config(EmbeddingContext.Config.builder()
            .splitStrategy(EmbeddingContext.Config.SplitStrategy.valueOf(mode))
            .build())
        .build();
    executor.execute2Resp("embedding_preview", null, context);
    return Lists.immutable.ofAll(context.getDocuments());
  }

  public ImmutableList<Document> preview(String mode, ImmutableList<String> ids) {
    DataFileVO vo = dataFileService.downloadFile(Long.parseLong(ids.get(0)));
    String content = FileUtil.readString(vo.getPath(), StandardCharsets.UTF_8);
    return preview(mode, content);
  }

  public void submit(Long id, String mode, String content) {
    executors.submit(() -> {
      Knowledge knowledge = knowledgeService.get(id);
      Long groupId = groupService.add(knowledge.getId(), StrUtil.format("文本-{}", IdUtil.nanoId(10)));
      EmbeddingContext context = EmbeddingContext.builder()
          .vectorSourceId(knowledge.getVectorSourceId())
          .groupId(groupId)
          .content(content)
          .config(EmbeddingContext.Config.builder()
              .splitStrategy(EmbeddingContext.Config.SplitStrategy.valueOf(mode))
              .build())
          .build();
      executor.execute2Resp("embedding_submit", null, context);
      groupService.finish(groupId);
    });
  }

  public void submit(Long id, String mode, ImmutableList<String> ids) {
    executors.submit(() -> {
      Knowledge knowledge = knowledgeService.get(id);
      List<Pair<Long, DataFileVO>> vos = Lists.mutable.empty();
      for (String fileId : ids) {
        DataFileVO vo = dataFileService.downloadFile(Long.parseLong(fileId));
        Long groupId = groupService.add(id, vo.getFilename());
        vos.add(Pair.of(groupId, vo));
      }
      for (Pair<Long, DataFileVO> pair : vos) {
        Long groupId = pair.getKey();
        DataFileVO vo = pair.getValue();
        EmbeddingContext context = EmbeddingContext.builder()
            .vectorSourceId(knowledge.getVectorSourceId())
            .groupId(groupId)
            .file(vo.getPath())
            .fileFormat(vo.getFilename())
            .config(EmbeddingContext.Config.builder()
                .splitStrategy(EmbeddingContext.Config.SplitStrategy.valueOf(mode))
                .build())
            .build();
        executor.execute2Resp("embedding_submit", null, context);
        groupService.finish(groupId);
      }
    });
  }
}
