package com.gzzm.lobster.parse;

import net.cyan.arachne.annotation.Service;
import net.cyan.nest.annotation.Inject;

import java.util.Locale;

/**
 * ParserRegistry —— 按扩展名/mime 路由到对应 {@link DocumentParser} /
 * Route uploads to a parser by extension / mime.
 *
 * <p>支持矩阵：
 * <ul>
 *   <li>Word 家族（WordParser）：docx/doc/dot/dotx/docm/dotm/wps/wpt/rtf/odt/ott</li>
 *   <li>表格（SpreadsheetParser）：xlsx/xls/xlsm/xlsb/xlt/xltx/xltm/ods</li>
 *   <li>幻灯片（SlideParser）：pptx/ppt/pptm/pps/ppsx/ppsm/pot/potx/potm/odp</li>
 *   <li>PDF（PdfParser）：pdf</li>
 *   <li>OFD（OfdParser）：ofd —— Spire 先转 PDF 再走 PdfParser</li>
 *   <li>纯文本（TextParser）：txt/md/csv/tsv/json/log 及未知类型兜底</li>
 * </ul>
 * 未识别扩展名返回 {@link TextParser}；{@code pickForExtension} 对二进制扩展名返回 null
 * 让调用方降级成"仅保留原件不解析"。
 */
@Service
public class ParserRegistry {

    @Inject private WordParser wordParser;
    @Inject private PdfParser pdfParser;
    @Inject private TextParser textParser;
    @Inject private SpreadsheetParser spreadsheetParser;
    @Inject private SlideParser slideParser;
    @Inject private OfdParser ofdParser;

    /**
     * 根据原始文件名选择 parser。返回 null 表示暂不支持解析，但上传流程仍可继续
     * （原件落 ContentStore，markdown 留空并带占位说明，LLM 自行决定怎么办）.
     */
    public DocumentParser pickForFilename(String filename) {
        if (filename == null) return textParser;
        String n = filename.toLowerCase(Locale.ROOT);
        int dot = n.lastIndexOf('.');
        if (dot < 0 || dot == n.length() - 1) return textParser;
        String ext = n.substring(dot + 1);
        return pickForExtension(ext);
    }

    /** 按扩展名选择——外部已知 ext 时直接调. */
    public DocumentParser pickForExtension(String ext) {
        if (ext == null) return textParser;
        switch (ext.toLowerCase(Locale.ROOT)) {
            // Word 家族 —— Spire.Doc FileFormat.Auto 统一识别
            case "docx": case "doc":
            case "dotx": case "dot":
            case "docm": case "dotm":
            case "wps":  case "wpt":
            case "rtf":
            case "odt":  case "ott":
                return wordParser;
            // 表格 —— Spire.Xls 自动识别
            case "xlsx": case "xls":
            case "xlsm": case "xlsb":
            case "xlt":  case "xltx": case "xltm":
            case "ods":
                return spreadsheetParser;
            // 幻灯片 —— Spire.Presentation FileFormat.AUTO
            case "pptx": case "ppt":
            case "pptm":
            case "pps":  case "ppsx": case "ppsm":
            case "pot":  case "potx": case "potm":
            case "odp":
                return slideParser;
            case "pdf":
                return pdfParser;
            case "ofd":
                return ofdParser;
            case "txt":
            case "md":
            case "markdown":
            case "csv":
            case "tsv":
            case "json":
            case "log":
                return textParser;
            default:
                return null;
        }
    }

    public WordParser word() { return wordParser; }
    public PdfParser pdf() { return pdfParser; }
    public TextParser text() { return textParser; }
    public SpreadsheetParser spreadsheet() { return spreadsheetParser; }
    public SlideParser slide() { return slideParser; }
    public OfdParser ofd() { return ofdParser; }
}
