package com.luojia_channel.modules.file.utils;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.luojia_channel.common.exception.FileException;
import com.luojia_channel.common.utils.RedisUtil;
import com.luojia_channel.modules.file.dto.UploadChunkDTO;
import com.luojia_channel.modules.file.dto.UploadFileDTO;
import com.luojia_channel.modules.file.entity.LjFile;
import com.luojia_channel.modules.file.mapper.LjFileMapper;
import io.minio.MinioClient;
import io.minio.StatObjectArgs;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

import static com.luojia_channel.modules.file.constants.FileConstant.*;

@Component
@RequiredArgsConstructor
public class ValidateFileUtil {
    private final LjFileMapper ljFileMapper;
    private final RedisUtil redisUtil;
    private final GeneratePathUtil generatePathUtil;
    private final MinioClient minioClient;
    // 验证分片参数
    public void validateChunk(UploadChunkDTO chunkDTO) {
        if (chunkDTO.getFile().isEmpty()) {
            throw new FileException("分片数据不能为空");
        }
        if (StrUtil.isBlank(chunkDTO.getFileMd5())) {
            throw new FileException("文件MD5缺失");
        }
        if (chunkDTO.getChunkNumber() < 0) {
            throw new FileException("分片编号不能为负数");
        }
        if (chunkDTO.getTotalChunks() <= 0) {
            throw new FileException("总分片数必须大于0");
        }
        if(chunkDTO.getChunkNumber() >= chunkDTO.getTotalChunks()){
            throw new FileException("分片序号不能大于分片总数");
        }
    }
    // 校验普通文件上传
    public void validateFile(UploadFileDTO dto) {
        if (dto.getFile().isEmpty()) {
            throw new FileException("文件不能为空");
        }
        // MD5校验
        if (StrUtil.isBlank(dto.getFileMd5())) {
            throw new FileException("文件MD5缺失");
        }
        // 类型校验
        if (!Arrays.asList("image", "video").contains(dto.getFileType())) {
            throw new FileException("不支持的文件类型");
        }
        // 大小校验
        if(dto.getFile().getSize() > MAX_UPLOAD_SIZE){
            throw new FileException("上传文件大小过大");
        }
    }

    // 秒传检查
    public Long getExistedFileId(String fileMd5) {
        LjFile file = ljFileMapper.selectOne(Wrappers.<LjFile>lambdaQuery()
                .eq(LjFile::getFileMd5, fileMd5));
        if(file == null){
            return null;
        }
        return file.getId();
    }

    // 检查分片是否已上传
    public boolean isChunkUploaded(String fileMd5, int chunkNumber) {
        String objectName = generatePathUtil.getChunkObjectName(fileMd5, chunkNumber);
        String redisKey = CHUNK_PREFIX + fileMd5;
        // 检查redis中是否已记录该分片
        if (redisUtil.sIsMember(redisKey, chunkNumber)) {
            return true;
        }
        try {
            minioClient.statObject(
                    StatObjectArgs.builder()
                            .bucket(CHUNK_BUCKET)
                            .object(objectName)
                            .build()
            );
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    // 检查所有分片是否已上传
    public boolean areAllChunksUploaded(String fileMd5, int totalChunks) {
        String key = CHUNK_PREFIX + fileMd5;
        List<Integer> uploadedChunks = redisUtil.sGet(key);
        return uploadedChunks.size() == totalChunks;
    }

    public String getExistedFileUrl(String fileMd5) {
        LjFile file = ljFileMapper.selectOne(Wrappers.<LjFile>lambdaQuery()
                .eq(LjFile::getFileMd5, fileMd5));
        if(file == null){
            return null;
        }
        return file.getFileUrl();
    }
}
