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

import cn.hutool.core.date.DateUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.model.*;
import com.hdkj.lt.base.constants.CommonConstant;
import com.hdkj.lt.base.constants.SymbolConstants;
import com.hdkj.lt.io.config.AliyunOSSConfigProperties;
import com.hdkj.lt.io.mapper.DistSVGFileMapper;
import com.hdkj.lt.io.service.IObjectStorageService;
import com.hdkj.lt.modle.FileUploadDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import java.time.LocalDateTime;

import java.io.IOException;
import java.io.InputStream;
import java.time.ZoneId;
import java.util.List;
import java.util.stream.Collectors;

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

    private final OSS ossClient;

    private final DistSVGFileMapper distSVGFileMapper;

    private final AliyunOSSConfigProperties aliyunOssConfigProperties;

    public AliyunIObjectStorageServiceImpl(OSS ossClient, DistSVGFileMapper distSVGFileMapper, AliyunOSSConfigProperties aliyunOssConfigProperties) {
        this.ossClient = ossClient;
        this.distSVGFileMapper = distSVGFileMapper;
        this.aliyunOssConfigProperties = aliyunOssConfigProperties;
    }

    @Override
    public byte[] getObject(String objectName) {
        GetObjectRequest request = new GetObjectRequest(aliyunOssConfigProperties.getBucketName(), objectName);
        OSSObject response = ossClient.getObject(request);
        try (InputStream inputStream = response.getObjectContent();) {
            return IOUtils.toByteArray(inputStream);
        } catch (IOException e) {
            log.error("下载文件失败：{}", e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    @Override
    public List<FileUploadDTO> listObject(String fileDir) {
        ListObjectsRequest listObjectsRequest = new ListObjectsRequest(aliyunOssConfigProperties.getBucketName(),
                String.format("%s/", fileDir), null, SymbolConstants.FORWARD_SLASH, aliyunOssConfigProperties.getMaxKeys());
        List<FileUploadDTO> fileNameList = Lists.newArrayList();
        // 配置变更生效时间
        LocalDateTime configTime = distSVGFileMapper.getConfigFileChangeTime();
        // 分页文件对象
        ObjectListing response;
        do {
            response = ossClient.listObjects(listObjectsRequest);
            fileNameList.addAll(response.getObjectSummaries()
                    .stream()
                    .filter(e -> this.isChangeFile(e, configTime))
                    .map(e -> FileUploadDTO.builder().fileName(e.getKey()).uploadTime(DateUtil.toLocalDateTime(e.getLastModified())).build())
                    .collect(Collectors.toList()));

            // 设置获取下一页的文件数据
            listObjectsRequest.setMarker(response.getNextMarker());
        } while (response.isTruncated());
        return fileNameList;
    }

    @Override
    public void removeObject(String objectName) {
        GenericRequest request = new GenericRequest(aliyunOssConfigProperties.getBucketName(), objectName);
        ossClient.deleteObject(request);
    }


    /**
     * 判断是否异动文件
     */
    private Boolean isChangeFile(OSSObjectSummary objectSummary, LocalDateTime configTime) {
        // 大于配置文件时、非文件夹、是svg和xml后缀
        if (!this.isFolder(objectSummary)) {
            // 文件最后修改时间设置时区
            LocalDateTime dateAsLocal = objectSummary.getLastModified()
                    .toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
            // 配置时间设置时区时间
            LocalDateTime configTimeAsLocal = configTime.atZone(ZoneId.systemDefault()).toLocalDateTime();
            // 取配置时间之后且 后缀为.xml和.svg的异动文件及.txt终结文件
            return configTimeAsLocal.isBefore(dateAsLocal) &&
                    StringUtils.endsWithAny(objectSummary.getKey().toLowerCase(), ".xml", ".svg", ".txt");
        }
        return Boolean.FALSE;
    }

    /**
     * 判断OSS对象是否为文件夹
     */
    private Boolean isFolder(OSSObjectSummary objectSummary) {
        return StringUtils.endsWithIgnoreCase(objectSummary.getKey(), SymbolConstants.FORWARD_SLASH)
                && Long.compare(objectSummary.getSize(), Long.valueOf(CommonConstant.ZERO)) == 0;
    }
}
