package tech.easyflow.ai.document.support;

import cn.hutool.http.HttpUtil;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import tech.easyflow.ai.document.exception.DocumentParseBridgeException;
import tech.easyflow.ai.document.model.DocumentSourceRef;
import tech.easyflow.common.filestorage.FileStorageService;
import tech.easyflow.common.filestorage.utils.PathGeneratorUtil;

import java.io.IOException;
import java.io.InputStream;
import java.net.URLConnection;

/**
 * 文档源加载器。
 *
 * <p>负责把不同来源的文件引用统一转换为内存字节和标准文件元数据。</p>
 *
 * @author Codex
 * @since 2026-04-14
 */
@Component
public class DocumentSourceLoader {

    private final FileStorageService fileStorageService;

    public DocumentSourceLoader(@Qualifier("default") FileStorageService fileStorageService) {
        this.fileStorageService = fileStorageService;
    }

    /**
     * 加载文档源。
     *
     * @param sourceRef easyflow 文档源
     * @return 内部已加载文档对象
     */
    public LoadedDocumentSource load(DocumentSourceRef sourceRef) {
        if (sourceRef == null) {
            throw DocumentParseBridgeException.unsupportedSource("文档源不能为空");
        }
        if (hasContentBytes(sourceRef)) {
            return buildLoadedSource(
                resolveFileName(sourceRef),
                resolveContentType(sourceRef, resolveFileName(sourceRef)),
                resolveSize(sourceRef, sourceRef.getContentBytes().length),
                sourceRef.getContentBytes()
            );
        }
        if (StringUtils.hasText(sourceRef.getFilePath())) {
            if (isRemoteUrl(sourceRef.getFilePath())) {
                return loadFromRemoteValue(sourceRef, sourceRef.getFilePath());
            }
            return loadFromFilePath(sourceRef);
        }
        if (StringUtils.hasText(sourceRef.getUrl())) {
            return loadFromUrl(sourceRef);
        }
        throw DocumentParseBridgeException.unsupportedSource("文档源缺少 filePath、url 或 contentBytes");
    }

    private LoadedDocumentSource loadFromFilePath(DocumentSourceRef sourceRef) {
        String fileName = resolveFileName(sourceRef);
        try (InputStream inputStream = fileStorageService.readStream(sourceRef.getFilePath())) {
            byte[] contentBytes = inputStream.readAllBytes();
            long actualSize = sourceRef.getSize() != null ? sourceRef.getSize() : fileStorageService.getFileSize(sourceRef.getFilePath());
            return buildLoadedSource(
                fileName,
                resolveContentType(sourceRef, fileName),
                resolveSize(sourceRef, actualSize),
                contentBytes
            );
        } catch (IOException e) {
            throw DocumentParseBridgeException.sourceLoadFailed(
                "读取文档存储文件失败: " + sourceRef.getFilePath(),
                e
            );
        }
    }

    private LoadedDocumentSource loadFromUrl(DocumentSourceRef sourceRef) {
        return loadFromRemoteValue(sourceRef, sourceRef.getUrl());
    }

    private LoadedDocumentSource loadFromRemoteValue(DocumentSourceRef sourceRef, String remoteUrl) {
        String fileName = resolveFileName(sourceRef);
        try {
            byte[] contentBytes = HttpUtil.downloadBytes(remoteUrl);
            return buildLoadedSource(
                fileName,
                resolveContentType(sourceRef, fileName),
                resolveSize(sourceRef, contentBytes.length),
                contentBytes
            );
        } catch (Exception e) {
            throw DocumentParseBridgeException.sourceLoadFailed(
                "下载文档 URL 失败: " + remoteUrl,
                e
            );
        }
    }

    private LoadedDocumentSource buildLoadedSource(String fileName, String contentType, Long size, byte[] contentBytes) {
        LoadedDocumentSource loadedSource = new LoadedDocumentSource();
        loadedSource.setFileName(fileName);
        loadedSource.setContentType(contentType);
        loadedSource.setSize(size);
        loadedSource.setContentBytes(contentBytes);
        return loadedSource;
    }

    private String resolveFileName(DocumentSourceRef sourceRef) {
        if (StringUtils.hasText(sourceRef.getFileName())) {
            return PathGeneratorUtil.getPureFileName(sourceRef.getFileName());
        }
        if (StringUtils.hasText(sourceRef.getFilePath())) {
            return PathGeneratorUtil.getPureFileName(sourceRef.getFilePath());
        }
        if (StringUtils.hasText(sourceRef.getUrl())) {
            String pureName = PathGeneratorUtil.getPureFileName(sourceRef.getUrl());
            int queryIndex = pureName.indexOf('?');
            return queryIndex >= 0 ? pureName.substring(0, queryIndex) : pureName;
        }
        throw DocumentParseBridgeException.unsupportedSource("文档源缺少可用文件名");
    }

    private String resolveContentType(DocumentSourceRef sourceRef, String fileName) {
        if (StringUtils.hasText(sourceRef.getContentType())) {
            return sourceRef.getContentType();
        }
        return URLConnection.guessContentTypeFromName(fileName);
    }

    private Long resolveSize(DocumentSourceRef sourceRef, long fallbackSize) {
        return sourceRef.getSize() != null ? sourceRef.getSize() : fallbackSize;
    }

    private boolean hasContentBytes(DocumentSourceRef sourceRef) {
        return sourceRef.getContentBytes() != null && sourceRef.getContentBytes().length > 0;
    }

    private boolean isRemoteUrl(String value) {
        return value.startsWith("http://") || value.startsWith("https://");
    }
}
