package com.hdkj.lt.io.aop;

import com.hdkj.lt.utils.file.FileExtUtils;
import com.hdkj.lt.utils.file.FileUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.util.WebUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
@RefreshScope
public class FileTypeCheckAop {

    private static final Map<String, String> FILE_MAP = new HashMap<>();

    @Value("${lt.file.check.file-types}")
    private List<String> fileTypes;

    static {
        FILE_MAP.put("image/png", "png");
        FILE_MAP.put("image/jpeg", "jpg");
        FILE_MAP.put("image/gif", "gif");
        FILE_MAP.put("image/svg+xml", "svg");
        FILE_MAP.put("image/x-icon", "ico");
        FILE_MAP.put("image/bmp", "bmp");
        FILE_MAP.put("application/msword", "doc");
        FILE_MAP.put("application/vnd.openxmlformats-officedocument.wordprocessingml.document", "docx");
        FILE_MAP.put("application/vnd.ms-excel", "xls");
        FILE_MAP.put("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "xlsx");
        FILE_MAP.put("application/pdf", "pdf");
        FILE_MAP.put("application/xml", "xml");
        FILE_MAP.put("application/vnd.ms-powerpoint", "ppt");
        FILE_MAP.put("text/plain", "txt");
        FILE_MAP.put("audio/wav", "wav");
        FILE_MAP.put("audio/mpeg", "mp3");
        FILE_MAP.put("audio/x-mpeg", "mp3");
        FILE_MAP.put("audio/mp4", "m4a");
        FILE_MAP.put("application/octet-stream", "");
    }

    @Pointcut("execution(* com.jxdinfo.hussar.support.*.controller.AttachmentManagerController.*(..))")
    public void poincut() {
        //Do nothing because of X and Y.
    }

    @Before("poincut()")
    public void doBeforeGame(JoinPoint joinPoint) {
        try {
            Object[] args = joinPoint.getArgs();
            for (Object arg : args) {
                if (arg instanceof HttpServletRequest) {
                    HttpServletRequest request = (HttpServletRequest) arg;
                    MultipartHttpServletRequest multipartRequest =
                            WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class);
                    if (multipartRequest == null) {
                        continue;
                    }
                    check(multipartRequest);
                } else if (arg instanceof MultipartHttpServletRequest) {
                    check((MultipartHttpServletRequest) arg);
                } else if (arg instanceof MultipartFile) {
                    check((MultipartFile) arg);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    private void check(MultipartHttpServletRequest multipartRequest) throws IOException {
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile mf = entity.getValue();
            check(mf);
        }
    }

    public void check(MultipartFile mf) throws IOException {

        byte[] bytes = mf.getBytes();
        String suffix = "";
        try {
            File f = FileExtUtils.multipartFileToFile(mf);
            suffix = FileExtUtils.getFileType(f);
            FileUtils.delete(f);
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        String extend = FileExtUtils.getExtend(mf.getOriginalFilename(), suffix);
        log.info("文件后缀extend[{}]", extend);
        log.info("文件原文件类型[{}]", suffix);
        log.info("文件大小size[{}]", mf.getSize());
        if (StringUtils.isNotBlank(extend)) {
            boolean b = FileExtUtils.checkRealExtend(bytes, extend);
            if (!b && !StringUtils.equalsAny(extend, (CharSequence) fileTypes)) {
                throw new RuntimeException("文件格式错误");
            }
        }
    }


    public void checkFile(MultipartFile mf) throws IOException {
        byte[] bytes = mf.getBytes();
        String extend = FileExtUtils.getExtend(mf.getOriginalFilename());
        log.info("文件后缀extend[{}]", extend);
        log.info("文件大小size[{}]", mf.getSize());
        if (StringUtils.isNotBlank(extend)) {
            boolean b = FileExtUtils.checkRealExtend(bytes, extend);
            if (!b && !fileTypes.contains(extend.toLowerCase())) {
                throw new RuntimeException("文件格式错误");
            }
        }
    }

}
