package com.hdkj.lt.io.service.impl;

import com.google.common.collect.Lists;
import com.hdkj.lt.base.constants.SymbolConstants;
import com.hdkj.lt.io.config.MinioOSSConfigProperties;
import com.hdkj.lt.io.mapper.DistSVGFileMapper;
import com.hdkj.lt.io.service.IObjectStorageService;
import com.hdkj.lt.modle.FileUploadDTO;
import io.minio.*;
import io.minio.messages.Item;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List;

/**
 * @Description
 * @Author wcx
 * @Date 2025/6/18 16:15
 * @Version 1.0
 */
@Slf4j
public class MinioIObjectStorageServiceImpl implements IObjectStorageService {

    private final MinioClient minioClient;

    private final DistSVGFileMapper distSVGFileMapper;

    private final MinioOSSConfigProperties minioOssConfigProperties;

    public MinioIObjectStorageServiceImpl(MinioClient minioClient, DistSVGFileMapper distSVGFileMapper, MinioOSSConfigProperties minioConfigProperties) {
        this.minioClient = minioClient;
        this.distSVGFileMapper = distSVGFileMapper;
        this.minioOssConfigProperties = minioConfigProperties;
    }

    @Override
    public byte[] getObject(String objectName) {
        GetObjectArgs args = GetObjectArgs.builder()
                .bucket(minioOssConfigProperties.getBucketName())
                .object(objectName).build();
        try (InputStream inputStream = minioClient.getObject(args)) {
            return IOUtils.toByteArray(inputStream);
        } catch (Exception e) {
            log.error("下载文件失败：{}", e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    @Override
    public List<FileUploadDTO> listObject(String fileDir) {
        try {
            List<FileUploadDTO> fileNameList = Lists.newArrayList();
            // 配置变更生效时间
            LocalDateTime configTime = distSVGFileMapper.getConfigFileChangeTime();
            List<Result<Item>> fileList;
            String keyMarker = null;
            do {
                ListObjectsArgs args = ListObjectsArgs.builder()
                        .bucket(minioOssConfigProperties.getBucketName())
                        .prefix(String.format("%s/", fileDir))
                        .delimiter(SymbolConstants.FORWARD_SLASH)
                        .maxKeys(minioOssConfigProperties.getMaxKeys())
                        .marker(keyMarker)
                        .build();

                // 迭代器转成集合
                fileList = Lists.newArrayList(minioClient.listObjects(args));
                // 查看本次查询是否还存在文件
                for (Result<Item> result : fileList) {
                    Item item = result.get();
                    if (!item.isDir() && this.isChangeFile(item, configTime)) {
                        LocalDateTime uploadTime = item.lastModified().withZoneSameInstant(ZoneId.systemDefault()).toLocalDateTime();
                        fileNameList.add(FileUploadDTO.builder().fileName(item.objectName()).uploadTime(uploadTime).build());
                    }
                }
                keyMarker = fileList.get(fileList.size() - 1).get().objectName();
            } while (CollectionUtils.size(fileList) == minioOssConfigProperties.getMaxKeys());
            return fileNameList;
        } catch (Exception e) {
            log.error("批量获取失败：{}", e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    @Override
    public void removeObject(String objectName) {
        try {
            RemoveObjectArgs args = RemoveObjectArgs.builder()
                    .bucket(minioOssConfigProperties.getBucketName())
                    .object(objectName)
                    .build();
            minioClient.removeObject(args);
        } catch (Exception e) {
            log.error("删除文件失败：{}", e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 判断是否异动文件
     */
    private Boolean isChangeFile(Item item, LocalDateTime configTime) {
        // 文件最后修改时间设置时区
        LocalDateTime dateAsLocal = item.lastModified()
                .withZoneSameInstant(ZoneId.systemDefault()).toLocalDateTime();
        // 配置时间设置时区时间
        LocalDateTime configTimeAsLocal = configTime.atZone(ZoneId.systemDefault()).toLocalDateTime();
        // 取配置时间之后且 后缀为.xml和.svg的异动文件及.txt终结文件
        return configTimeAsLocal.isBefore(dateAsLocal) &&
                StringUtils.endsWithAny(item.objectName().toLowerCase(), ".xml", ".svg", ".txt");

    }
}
