package com.cmvr.test.service;

import com.cmvr.common.config.properties.MinioProperties;
import com.cmvr.common.core.minio.MinioService;
import com.cmvr.common.exception.GlobalException;
import com.cmvr.llm.util.LargeModelFileUploadUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.io.File;
import java.nio.file.Files;
import java.net.URI;
import java.net.URLDecoder;

/**
 * MinIO文件转存商道服务，统一处理对象地址解析和大小限制。
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ShangdaoFileService
{
    private static final int MAX_FILE_BYTES = 20 * 1024 * 1024;

    private final MinioService minioService;
    private final MinioProperties minioProperties;

    /**
     * 下载指定MinIO对象并上传商道。
     *
     * @param fileUrl 包含bucket的MinIO访问地址，或bucket内对象路径
     * @return 商道临时下载地址，仅用于随后调用大模型
     */
    public String uploadFromMinio(String fileUrl)
    {
        String objectName = resolveObjectName(fileUrl);
        File temporaryFile = null;
        try
        {
            temporaryFile = minioService.getFile(minioProperties.getBucketName(), objectName);
            if (temporaryFile.length() > MAX_FILE_BYTES)
            {
                throw new GlobalException("巡检媒体文件不能超过20MB");
            }
            byte[] bytes = Files.readAllBytes(temporaryFile.toPath());
            String shangdaoUrl = LargeModelFileUploadUtil.uploadFile(bytes);
            if (StringUtils.isBlank(shangdaoUrl))
            {
                throw new GlobalException("商道文件上传未返回文件地址");
            }
            return shangdaoUrl;
        }
        catch (GlobalException ex)
        {
            throw ex;
        }
        catch (Exception ex)
        {
            log.error("MinIO文件上传商道失败，fileUrl={}，objectName={}", fileUrl, objectName, ex);
            throw new GlobalException("巡检图片上传商道失败");
        }
        finally
        {
            if (temporaryFile != null && temporaryFile.exists() && !temporaryFile.delete())
            {
                log.warn("删除MinIO临时文件失败，path={}", temporaryFile.getAbsolutePath());
            }
        }
    }

    /**
     * 从完整URL或对象路径中提取当前bucket内的objectName，并拒绝目录穿越路径。
     */
    private String resolveObjectName(String fileUrl)
    {
        String value = StringUtils.trimToNull(fileUrl);
        if (value == null)
        {
            throw new GlobalException("imageUrl不能为空");
        }

        String bucketName = StringUtils.trimToEmpty(minioProperties.getBucketName());
        try
        {
            String path = value;
            if (value.contains("://"))
            {
                path = new URI(value).getRawPath();
            }
            path = URLDecoder.decode(path, "UTF-8").replace('\\', '/');
            String bucketPrefix = "/" + bucketName + "/";
            int bucketIndex = path.indexOf(bucketPrefix);
            if (bucketIndex >= 0)
            {
                path = path.substring(bucketIndex + bucketPrefix.length());
            }
            else
            {
                path = StringUtils.removeStart(path, "/");
                path = StringUtils.removeStart(path, bucketName + "/");
            }
            String objectName = StringUtils.trimToNull(path);
            if (objectName == null || objectName.contains(".."))
            {
                throw new GlobalException("imageUrl不是有效的MinIO对象地址");
            }
            return objectName;
        }
        catch (GlobalException ex)
        {
            throw ex;
        }
        catch (Exception ex)
        {
            throw new GlobalException("无法解析MinIO文件地址: " + value);
        }
    }

}
