package org.dromara.knowledge.data;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.exception.ServiceException;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 文档解析器工厂
 * 统一管理所有文档解析器，根据文件扩展名选择合适的解析器
 *
 * @author pengles
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class DocumentParserFactory {

    private final List<DocumentParser> parsers;
    private final Map<String, DocumentParser> parserMap = new HashMap<>();

    /**
     * 初始化解析器映射
     * 通过构造函数注入所有 DocumentParser 实现，并建立文件扩展名到解析器的映射
     */
    private void initParserMap() {
        if (!parserMap.isEmpty()) {
            return;
        }

        // PDF 解析器
        parserMap.put("pdf", findParserByClass(PdfDocumentParser.class));
        // Word 解析器
        parserMap.put("doc", findParserByClass(WordDocumentParser.class));
        parserMap.put("docx", findParserByClass(WordDocumentParser.class));
        // Excel 解析器
        parserMap.put("xls", findParserByClass(ExcelDocumentParser.class));
        parserMap.put("xlsx", findParserByClass(ExcelDocumentParser.class));
        // Markdown 解析器
        parserMap.put("md", findParserByClass(MarkdownDocumentParser.class));
        // HTML 解析器
        parserMap.put("html", findParserByClass(HtmlDocumentParser.class));
        parserMap.put("htm", findParserByClass(HtmlDocumentParser.class));
        // CSV 解析器
        parserMap.put("csv", findParserByClass(CsvDocumentParser.class));
        // 文本解析器（作为默认）
        parserMap.put("txt", findParserByClass(TextDocumentParser.class));
        parserMap.put("json", findParserByClass(TextDocumentParser.class));
        parserMap.put("xml", findParserByClass(TextDocumentParser.class));

        log.info("文档解析器工厂初始化完成，已注册 {} 种文件类型", parserMap.size());
    }

    /**
     * 根据类类型查找解析器
     */
    private DocumentParser findParserByClass(Class<? extends DocumentParser> clazz) {
        return parsers.stream()
                .filter(parser -> clazz.isInstance(parser))
                .findFirst()
                .orElseGet(() -> {
                    try {
                        DocumentParser instance = clazz.getDeclaredConstructor().newInstance();
                        log.warn("解析器 {} 未注册为 Spring Bean，使用默认实例", clazz.getSimpleName());
                        return instance;
                    } catch (Exception e) {
                        throw new ServiceException("无法创建解析器实例: " + clazz.getName() + ": " + e.getMessage());
                    }
                });
    }

    /**
     * 根据文件扩展名获取解析器
     *
     * @param extension 文件扩展名（不包含点号）
     * @return 文档解析器
     */
    public DocumentParser getParser(String extension) {
        initParserMap();
        String ext = extension != null ? extension.toLowerCase() : "";
        DocumentParser parser = parserMap.get(ext);
        if (parser == null) {
            // 如果没有找到对应的解析器，使用文本解析器作为默认
            parser = parserMap.get("txt");
            log.warn("未找到文件扩展名 {} 的解析器，使用默认文本解析器", extension);
        }
        return parser;
    }

    /**
     * 根据文件名获取解析器
     *
     * @param filename 文件名
     * @return 文档解析器
     */
    public DocumentParser getParserByFilename(String filename) {
        String extension = extractExtension(filename);
        return getParser(extension);
    }

    /**
     * 解析文档
     *
     * @param bytes    文件字节数组
     * @param filename 文件名
     * @return 解析后的文本内容
     */
    public String parse(byte[] bytes, String filename) {
        DocumentParser parser = getParserByFilename(filename);
        return parser.parse(bytes, filename);
    }

    /**
     * 检查是否支持该文件类型
     *
     * @param extension 文件扩展名
     * @return 是否支持
     */
    public boolean isSupported(String extension) {
        initParserMap();
        String ext = extension != null ? extension.toLowerCase() : "";
        return parserMap.containsKey(ext);
    }

    /**
     * 获取支持的文件扩展名列表
     *
     * @return 支持的文件扩展名列表
     */
    public List<String> getSupportedExtensions() {
        initParserMap();
        return parserMap.keySet().stream().sorted().toList();
    }

    /**
     * 从文件名中提取扩展名
     */
    private String extractExtension(String filename) {
        if (filename == null || filename.isEmpty()) {
            return "";
        }
        int lastDotIndex = filename.lastIndexOf('.');
        if (lastDotIndex > 0 && lastDotIndex < filename.length() - 1) {
            return filename.substring(lastDotIndex + 1);
        }
        return "";
    }
}
