package org.springblade.system.util;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.springblade.common.core.domain.entity.SysDictData;
import org.springblade.common.utils.bean.FileDto;
import org.springblade.system.mapper.SysDictDataMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;

/**
 * 文件处理工具类
 *
 * @author bonus
 */
@Component
public class WebFileUtils {
    // 常见的图片扩展名（小写）
    private static final Set<String> IMAGE_EXTENSIONS;
    private static String UPLOAD_DIR;

    @Resource
    private SysDictDataMapper dictDataMapper;

    private static final List<String> BLOCKED_PATTERNS = Arrays.asList(
            "<", ">", "[", "]", "(", ")", "/", "'", "\"", "@", "!", "+",
            "%3c", "%3e", "%2b",
            "script", "alert", "svg", "confirm", "prompt", "onload", "img", "src"
    );


    static {
        HashSet<String> set = new HashSet<>();
        set.add("jpg");
        set.add("jpeg");
        set.add("png");
        set.add("gif");
        set.add("bmp");
        set.add("webp");
        set.add("tiff");
        set.add("svg");
        set.add("ico");
        IMAGE_EXTENSIONS = Collections.unmodifiableSet(set);
    }


    @Value("${bonus.profile}")
    private String uploadDir;

    @PostConstruct
    public void init() {
        UPLOAD_DIR = uploadDir;
    }


    public FileDto upload(MultipartFile file) throws IOException {
        FileDto bean = new FileDto();
        if (file != null && !file.isEmpty()) {
            // 验证文件类型
            String originalFileName = file.getOriginalFilename();
            // 校验是否含有特殊字符(转小写便于忽略大小写比较)
            String lowerInput = originalFileName.toLowerCase();

            for (String pattern : BLOCKED_PATTERNS) {
                if (lowerInput.contains(pattern)) {
                    bean.setErrMessage("文件名包含非法字符：" + pattern);
                    return bean;
                }
            }
            // 校验文件大小
            SysDictData fileSizeLimit = selectDictDataByType("file_size_limit");
            // 转换为 MB（保留 2 位小数）
            double sizeInMB = file.getSize() / (1024.0 * 1024.0);
            if (sizeInMB > Double.parseDouble(fileSizeLimit.getDictValue())) {
                bean.setErrMessage("文件大小超出限制");
                return bean;
            }
            String fileExtension = originalFileName != null ? originalFileName.split("\\.")[1] : "";
            if (isImage(fileExtension)) {
                bean.setFileType("1");
            } else {
                bean.setFileType("2");
            }
            File targetDir = new File(UPLOAD_DIR);
            if (!targetDir.exists()) {
                targetDir.mkdirs();
            }
            String fileName = file.getOriginalFilename();
            String sourceFileName = System.currentTimeMillis() + "_" + file.getOriginalFilename();
            // 构建本地存储路径
            File uploadDir = new File(UPLOAD_DIR, "file");
            if (!uploadDir.exists()) {
                uploadDir.mkdirs();
            }

            File targetFile = new File(uploadDir, fileName);
            file.transferTo(targetFile);

            // 存储相对路径（统一使用 "/"，不使用 File.separator）
            String relativePath = "/file/" + fileName;
            bean.setFilePath(relativePath);
            bean.setFileName(fileName);
            bean.setSourceFileName(sourceFileName);
			bean.setFileSize(new BigDecimal(sizeInMB));
            bean.setSuffixName(fileExtension);
            return bean;
        } else {
            return bean;
        }

    }

    /**
     * 根据文件扩展名判断是否为图片
     *
     * @param fileExtension 文件扩展名（例如 "jpg", "png", "pdf"）
     * @return true 表示是图片，false 表示是普通文件
     */
    public static boolean isImage(String fileExtension) {
        if (fileExtension == null || fileExtension.trim().isEmpty()) {
            return false;
        }
        String ext = fileExtension.toLowerCase().trim();
        return IMAGE_EXTENSIONS.contains(ext);
    }

    public SysDictData selectDictDataByType(String dataType) {
        List<SysDictData> sysDictData = dictDataMapper.selectDictDataByType(dataType);
        return sysDictData.get(0);
    }
}
