package com.xueyi.file.controller;


import cn.hutool.core.text.CharSequenceUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSONArray;
import com.xueyi.common.core.constant.basic.SecurityConstants;
import com.xueyi.common.core.utils.core.IdUtil;
import com.xueyi.common.core.utils.file.FileTypeUtil;
import com.xueyi.common.core.utils.file.FileUtil;
import com.xueyi.common.core.utils.file.MimeTypeUtil;
import com.xueyi.common.core.web.result.AjaxResult;
import com.xueyi.common.core.web.result.R;
import com.xueyi.common.redis.utils.RedisUtil;
import com.xueyi.file.api.domain.DigitalmanLogFile;
import com.xueyi.file.api.domain.SysFile;
import com.xueyi.file.api.feign.RemoteFileManageService;
import com.xueyi.file.config.MinioConfig;
import com.xueyi.file.service.ISysFileService;
import com.xueyi.file.service.MinioSysFileServiceImpl;
import com.xueyi.file.utils.PdfToImageUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * 文件请求处理
 *
 * @author xueyi
 */
@RestController
public class SysFileController {

    private static final Logger log = LoggerFactory.getLogger(SysFileController.class);

    @Autowired
    private ISysFileService sysFileService;

    @Autowired
    private RemoteFileManageService remoteFileManageService;

    @Autowired
    private MinioConfig minioConfig;

    @Autowired
    private MinioSysFileServiceImpl minioSysFileService;

    /**
     * 文件上传 | 内部调用
     */
    @PostMapping("/inner/upload")
    public R<SysFile> uploadInner(MultipartFile file, String extension, String fileUuid) {
        try {
            log.info("文件上传开始：名：{}, 类型：{}, uuid：{}" , file.getName(), extension, fileUuid);
            // 上传并返回访问地址
            String url = sysFileService.uploadExactFile(file, extension);
            SysFile sysFile = new SysFile();
            sysFile.setUrl(url);
            log.info("文件大小：{}",  file.getSize());
            sysFile.setSize(file.getSize());
            sysFile.setName(FileUtil.getName(url));
            sysFile.setNick(sysFile.getName());
            remoteFileManageService.saveFileLog(sysFile, SecurityConstants.INNER);

            JSONArray ja = new JSONArray();
            Long size = sysFile.getSize();

            JSONObject jo = new JSONObject();
            jo.put("url", url);
            jo.put("size", size);
            ja.add(jo);

            RedisUtil.setVal("saas:upload:result:"+fileUuid, ja.toJSONString());
            RedisUtil.setVal("saas:upload:filename:"+fileUuid, file.getOriginalFilename());
            if (CharSequenceUtil.equalsAnyIgnoreCase(extension, MimeTypeUtil.IMAGE_EXTENSION)) {
                RedisUtil.setVal("saas:upload:fileType:"+fileUuid, 1);
            }
            if (CharSequenceUtil.equalsAnyIgnoreCase(extension, MimeTypeUtil.VIDEO_EXTENSION)) {
                RedisUtil.setVal("saas:upload:fileType:"+fileUuid, 2);
            }
            return R.ok(sysFile);
        } catch (Exception e) {
            log.error("上传文件失败", e);
            return R.fail(e.getMessage());
        }
    }

    @PostMapping("/inner/uploadNoAsync")
    public R<SysFile> uploadNoAsyncInner(MultipartFile file, String extension, String fileUuid) {
        try {
            log.info("文件上传开始：名：{}, 类型：{}, uuid：{}" , file.getName(), extension, fileUuid);
            // 上传并返回访问地址
            String url = sysFileService.uploadExactFile(file, extension);
            SysFile sysFile = new SysFile();
            sysFile.setUrl(url);
            log.info("文件大小：{}",  file.getSize());
            sysFile.setSize(file.getSize());
            sysFile.setName(FileUtil.getName(url));
            sysFile.setNick(sysFile.getName());
            remoteFileManageService.saveFileLog(sysFile, SecurityConstants.INNER);

            JSONArray ja = new JSONArray();
            Long size = sysFile.getSize();

            JSONObject jo = new JSONObject();
            jo.put("url", url);
            jo.put("size", size);
            ja.add(jo);

            RedisUtil.setVal("saas:upload:result:"+fileUuid, ja.toJSONString());
            RedisUtil.setVal("saas:upload:filename:"+fileUuid, file.getOriginalFilename());
            if (CharSequenceUtil.equalsAnyIgnoreCase(extension, MimeTypeUtil.IMAGE_EXTENSION)) {
                RedisUtil.setVal("saas:upload:fileType:"+fileUuid, 1);
            }
            if (CharSequenceUtil.equalsAnyIgnoreCase(extension, MimeTypeUtil.VIDEO_EXTENSION)) {
                RedisUtil.setVal("saas:upload:fileType:"+fileUuid, 2);
            }
            return R.ok(sysFile);
        } catch (Exception e) {
            log.error("上传文件失败", e);
            return R.fail(e.getMessage());
        }
    }

    @PostMapping("/inner/uploadFace")
    public R<SysFile> uploadFaceInner(MultipartFile file) {
        try {
            log.info("文件上传开始：{}" , file.getName());
            log.info("文件大小：{}" , file.getSize());
            // 上传并返回访问地址
            String url = sysFileService.uploadFile(file);
            SysFile sysFile = new SysFile();
            sysFile.setUrl(url);
            sysFile.setSize(file.getSize());
            sysFile.setName(FileUtil.getName(url));
            sysFile.setNick(sysFile.getName());
            remoteFileManageService.saveFileLog(sysFile, SecurityConstants.INNER);
            return R.ok(sysFile);
        } catch (Exception e) {
            log.error("上传文件失败", e);
            return R.fail(e.getMessage());
        }
    }


    @PostMapping("/inner/upload-temp")
    public R<SysFile> uploadTempInner(MultipartFile file) {
        try {
            log.info("文件上传开始：{}" , file.getName());
            // 上传并返回访问地址
            String url = sysFileService.uploadTempFile(file);
            SysFile sysFile = new SysFile();
            sysFile.setUrl(url);
            sysFile.setSize(file.getSize());
            sysFile.setName(FileUtil.getName(url));
            sysFile.setNick(sysFile.getName());
            remoteFileManageService.saveFileLog(sysFile, SecurityConstants.INNER);
            return R.ok(sysFile);
        } catch (Exception e) {
            log.error("上传文件失败", e);
            return R.fail(e.getMessage());
        }
    }


    /**
     * 文件上传 | 内部调用
     */
    @PostMapping("/inner/uploadpdf")
    public R<List<SysFile>> uploadPdfInner(MultipartFile file, String fileUuid) {
        try {
            Long startTs =  System.currentTimeMillis();
            log.info("文件上传开始：{}; start ts:{}", file.getName(), startTs);
            // pdf文件转成图片集合
            List<File> fileList = PdfToImageUtil.pdfToTransformationList(file);
            Long  pdfTs =  System.currentTimeMillis();
            log.info("PDF转换图片完成， 用时：{} ms",(pdfTs-startTs));
            List<SysFile> results = new ArrayList<>();
            int num = 1;
            log.info("开始上传图片。。。");
            // 循环上传并返回日志集合
            for (File f : fileList) {
                //将file的文件名重命名为file文件名+两位数的num
                log.info("上传第 {} 张图片开始。。。",num);
                String fileName = f.getName();
                String suffix = fileName.substring(fileName.lastIndexOf("."));
                String name = fileName.substring(0, fileName.lastIndexOf("."));
                String newName = name + String.format("%02d", num++) + suffix;
                // 上传并返回访问地址
                String url = sysFileService.uploadFile(newName, f);
                SysFile sysFile = new SysFile();
                sysFile.setUrl(url);
                sysFile.setSize(f.length());
                sysFile.setName(FileUtil.getName(url));
                sysFile.setNick(sysFile.getName());
                remoteFileManageService.saveFileLog(sysFile, SecurityConstants.INNER);
                results.add(sysFile);
                log.info("上传第 {} 张图片完成。。。",(num-1));
            };
            long endTs = System.currentTimeMillis();
            log.info("上传图片结束。。。，图片上传用时：{} ms，总用时：{} ms", (endTs-pdfTs), (endTs-startTs));

            JSONArray ja = new JSONArray();
            for (SysFile sf : results) {
                String url = sf.getUrl();
                Long size = sf.getSize();

                JSONObject jo = new JSONObject();
                jo.put("url", url);
                jo.put("size", size);
                ja.add(jo);
            }

            RedisUtil.setVal("saas:upload:result:"+fileUuid, ja.toJSONString());
            RedisUtil.setVal("saas:upload:filename:"+fileUuid, file.getOriginalFilename());
            RedisUtil.setVal("saas:upload:fileType:"+fileUuid, 1);
            return R.ok(results);
        } catch (Exception e) {
            log.error("上传文件失败", e);
            return R.fail(e.getMessage());
        }
    }



    /**
     * 删除文件 | 内部调用
     */
    @DeleteMapping(value = "/inner/delete/{url}")
    public R<Boolean> deleteInner(@PathVariable String url) {
        try {
            Boolean result = sysFileService.deleteFile(url);
            return R.ok(result);
        } catch (Exception e) {
            log.error("文件删除失败", e);
            return R.fail(e.getMessage());
        }
    }
    /**
     * 文件上传请求
     */
    @PostMapping("/api/getLogUploadPath")
    public AjaxResult getLogUploadPath(@RequestBody DigitalmanLogFile file) {
        // 根据当前时间，获取路径
        LocalDate currentDate = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
        String path = currentDate.format(formatter);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("hosts",minioConfig.getUrl());
        jsonObject.put("bucket",minioConfig.getBucketName());
        jsonObject.put("filepath","/" + file.getDevId() + "/" + path);
        jsonObject.put("uuid", IdUtil.simpleUUID());
        return AjaxResult.success(jsonObject);
    }

    /**
     * 文件上传请求
     */
    @PostMapping("/upload")
    public AjaxResult upload(MultipartFile file) {
        R<SysFile> R = uploadInner(file, FileTypeUtil.getExtension(file), IdUtil.randomUUID());
        return R.isOk()
                ? AjaxResult.success("上传成功！", R.getData().getUrl())
                : AjaxResult.error("上传失败！");
    }
    /**
     * 文件上传请求
     */
    @PostMapping("/uploadpdf")
    public AjaxResult uploadPdf(MultipartFile file) {
        R<List<SysFile>> R = uploadPdfInner(file, IdUtil.randomUUID());
        return R.isOk()
                ? AjaxResult.success("上传成功！", R.getData())
                : AjaxResult.error("上传失败！");
    }
}