package com.bonus.file.controller;

import cn.hutool.core.util.ObjectUtil;
import com.bonus.common.core.constant.HttpStatus;
import com.bonus.common.core.utils.Base64Utils;
import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.file.entity.Base64File;
import com.bonus.file.entity.Base64ToMultipartFile;
import com.bonus.file.service.ISysFileService;
import com.bonus.system.api.domain.SysFile;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.util.Base64;
import java.util.UUID;

/**
 * 文件请求处理
 *
 * @author bonus
 */
@RestController
@Api("服务文件存储")
public class SysFileController {
    private static final Logger log = LoggerFactory.getLogger(SysFileController.class);

    private final ISysFileService sysFileService;

    @Autowired
    public SysFileController(ISysFileService fileService) {
        this.sysFileService = fileService;
    }

    /**
     * 单文件上传
     *
     * @param file 单个文件
     * @return 文件信息，包括文件名和文件路径
     */
    @PostMapping("upload")
    @ApiOperation("上传本地文件到服务器")
    public AjaxResult upload(MultipartFile file) {
        try {
            // 上传并返回访问地址
            if (ObjectUtil.isEmpty(file)) {
                return AjaxResult.error("上传文件不能为空");
            }
            SysFile sysFile = sysFileService.uploadFile(file);
            return AjaxResult.success(sysFile);
        } catch (Exception e) {
            log.error("上传文件失败", e);
            return AjaxResult.error(e.getMessage());
        }
    }


    /**
     * 单文件上传（支持Base64格式）
     *
     * @param base64File Base64编码的文件内容
     * @param fileName   文件名（可选）
     * @param fileType   文件类型（如image/png，可选）
     * @return 文件信息，包括文件名和文件路径
     */
    @PostMapping("uploadBase64")
    @ApiOperation("上传Base64文件到服务器")
    public AjaxResult uploadBase64(@RequestBody Base64File entity) {
        try {
            // 验证Base64数据是否为空
            if (StringUtils.isEmpty(entity.getBase64File())) {
                return AjaxResult.error("上传文件内容不能为空");
            }

            // 处理可能包含的data URI前缀（如"data:image/png;base64,"）
            String base64Data;
            if (entity.getBase64File().startsWith("data:")) {
                // 提取真正的base64内容
                String[] parts = entity.getBase64File().split(",");
                if (parts.length < 2) {
                    return AjaxResult.error("Base64格式不正确");
                }
                base64Data = parts[1];

                // 如果没传fileType，尝试从data URI中提取
                if (entity.getFileType() == null && parts[0].contains(":")) {
                    entity.setFileType(parts[0].split(":")[1].split(";")[0]);
                }
            } else {
                base64Data = entity.getBase64File();
            }

            // 解码Base64
            byte[] fileBytes = Base64.getDecoder().decode(base64Data);

            // 如果没传文件名，生成一个随机文件名
            if (StringUtils.isEmpty(entity.getFileName())) {
                entity.setFileName(UUID.randomUUID().toString());
                // 如果知道文件类型，添加合适的扩展名
                if (entity.getFileType() != null) {
                    String extension = "";
                    if (entity.getFileType().equals("image/png")) {
                        extension = ".png";
                    } else if (entity.getFileType().equals("image/jpeg")) {
                        extension = ".jpg";
                    } else if (entity.getFileType().equals("application/pdf")) {
                        extension = ".pdf";
                    }
                    entity.setFileName(entity.getFileName() + extension);
                }
            }

            // 创建临时MultipartFile对象
            MultipartFile multipartFile = new Base64ToMultipartFile(fileBytes, entity.getFileName(), entity.getFileType());
            // 调用原有的上传逻辑
            SysFile sysFile = sysFileService.uploadFile(multipartFile);
            return AjaxResult.success(sysFile);
        } catch (IllegalArgumentException e) {
            log.error("Base64解码失败", e);
            return AjaxResult.error("Base64格式不正确");
        } catch (Exception e) {
            log.error("上传文件失败", e);
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 多文件上传
     *
     * @param files 多个文件流
     * @return 文件信息
     */
    @PostMapping("/uploadFiles")
    public AjaxResult uploadFile(MultipartFile[] files) {
        try {
            if (ObjectUtil.isEmpty(files)) {
                return AjaxResult.error("上传文件不能为空");
            }
            return AjaxResult.success(sysFileService.uploadFiles(files));
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 文件下载
     *
     * @param response           请求响应
     * @param objectKey，除mongodb 存fileid之外，其他均存上传文件的网络路径
     */
    @GetMapping("/download")
    public void downloadFile(HttpServletResponse response, @RequestParam String objectKey) throws IOException {
        try {
            String fileUrl = Base64Utils.decodeUrl(URLDecoder.decode(objectKey));
            sysFileService.downloadFile(response, fileUrl);
        } catch (Exception e) {
            log.error("downloadFile error:{}", e.getMessage());
            response.setStatus(HttpStatus.ERROR);
            // 设置响应的 Content-Type 为文本
            response.setContentType("application/json;charset=UTF-8");
            // 将错误信息写入响应体
            PrintWriter writer = response.getWriter();
            writer.write("{\"error\": \"File download failed: " + e.getMessage() + "\"}");
            writer.flush();
            writer.close();
        }
    }

    /**
     * 文件删除
     * 从各个存储平台删除文件
     *
     * @param objectKey * @param objectKey，除mongodb 存fileid之外，其他均存上传文件的网络路径
     */
    @PostMapping("/deleteFile")
    public AjaxResult deleteFile(@RequestParam("objectKey") String objectKey) {
        try {
            String fileUrl = Base64Utils.decodeUrl(URLDecoder.decode(objectKey));
            sysFileService.deleteFile(fileUrl);
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
        return AjaxResult.success("删除文件成功");
    }

    /**
     * 单文件上传到指定文件夹
     *
     * @param file 单个文件
     * @return 文件信息，包括文件名和文件路径
     */
    @PostMapping("uploadToFolder")
    @ApiOperation("上传本地文件到服务器")
    public AjaxResult upload(MultipartFile file, String folderName) {
        return AjaxResult.success("单文件上传成功");

    }

    /**
     * 创建文件夹
     *
     * @param folderPath 文件夹路径（例如 "folder1/subfolder/"）
     * @return 文件夹网络路径
     */
    @PostMapping("/createFolder")
    @ApiOperation("创建文件夹")
    public AjaxResult createFolder(@RequestParam("folderName") String folderPath) {
        sysFileService.createFolder(folderPath);
        return AjaxResult.success("创建文件夹");
    }

    /**
     * list 指定目录下所有文件信息（文件名，文件大小，上传时间，是否目录），包括子文件夹
     *
     * @param folderPath 要获取文件夹和文件的父文件夹路径（例如 "folder1/"）
     * @return 文件夹网络路径
     */
    @GetMapping("/listFiles")
    public AjaxResult listFiles(@RequestParam("folderName") String folderPath) {
        return AjaxResult.success(sysFileService.getFilesAndSubfolders(folderPath));
    }


    /**
     * 文件夹删除
     * 从各个存储平台删除文件
     *
     * @param folderPath 文件夹路径（例如 "folder1/subfolder/"）
     * @return 文件夹网络路径
     */
    @PostMapping("/deleteFolder")
    public AjaxResult deleteFolder(@RequestParam("folderName") String folderPath) {
        sysFileService.deleteFolder(folderPath);
        return AjaxResult.success("文件夹删除成功");
    }


    /*@PostMapping("/uploadResume")
    public AjaxResult uploadResume(@RequestParam("md5") String md5, @RequestParam("chunkIndex") Integer chunkIndex, @RequestParam("file") MultipartFile file, @RequestParam("totalChunks") Integer totalChunks, @RequestParam("filename") String filename) {
        try {
            if (ObjectUtil.isEmpty(file)) {
                return AjaxResult.error("上传文件不能为空");
            }
            return AjaxResult.success(sysFileService.uploadResume(md5, chunkIndex, file, totalChunks, filename));
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }*/

}