package top.imwork.window.silos.service.oss;

// FileUploadService.java
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.web.multipart.MultipartFile;
import top.imwork.commons.core.pojo.FileUploadRequest;
import top.imwork.commons.core.pojo.FileUploadResponse;
import top.imwork.commons.core.service.FileUploadService;
import top.imwork.window.silos.utils.FileUtils;
import top.imwork.window.silos.utils.SecurityUtils;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Slf4j
@Service
public class FileUploadServiceImpl implements FileUploadService {

    @Value("${upload.path}")
    private String uploadPath;

    @Value("${upload.file.upload-dir}")
    private String uploadDir;

    private static final DateTimeFormatter DATE_FORMATTER =
            DateTimeFormatter.ofPattern("yyyy/MM/dd");

    public FileUploadResponse uploadFile(MultipartFile file) throws IOException {
        // 生成安全文件名
        String originalFilename = file.getOriginalFilename();
        String fileExtension = FileUtils.getFileExtension(originalFilename);
        String safeFilename = generateSafeFilename(originalFilename);

        // 创建日期目录
        String dateDir = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
        String fullPath = uploadPath + dateDir + "/";

        // 确保目录存在
        Path directory = Paths.get(fullPath);
        Files.createDirectories(directory);

        // 保存文件
        Path filePath = directory.resolve(safeFilename);
        Files.copy(file.getInputStream(), filePath);

        // 生成文件URL
        String fileUrl = "/uploads/" + dateDir + "/" + safeFilename;

        // 二次安全检查（文件内容检查）
        if (!SecurityUtils.isFileContentSafe(filePath.toFile())) {
            // 删除危险文件
            Files.deleteIfExists(filePath);
            throw new SecurityException("文件内容包含危险代码");
        }

        // 返回文件信息
        return FileUploadResponse.builder()
                .fileName(originalFilename)
                .filePath(filePath.toString())
                .fileUrl(fileUrl)
                .fileType(file.getContentType())
                .fileSize(file.getSize())
                .fileHash(FileUtils.calculateFileHash(filePath.toFile()))
                .build();
    }

    /**
     * 生成安全文件名
     * @param originalFilename 原始文件名
     * @return 安全文件名
     */
    private String generateSafeFilename(String originalFilename) {
        String extension = FileUtils.getFileExtension(originalFilename);
        String baseName = originalFilename.substring(0, originalFilename.lastIndexOf('.'));

        // 清理文件名中的非法字符
        baseName = baseName.replaceAll("[^a-zA-Z0-9\u4e00-\u9fa5_-]", "");

        // 生成唯一ID
        String uniqueId = UUID.randomUUID().toString().substring(0, 8);

        // 组合文件名
        return baseName + "_" + uniqueId + "_" + System.currentTimeMillis() + extension;
    }

    @Override
    public FileUploadResponse uploadSingleFile(MultipartFile file, String businessType, Long userId, String description) {
        FileUploadRequest request = new FileUploadRequest();
        request.setFile(file);
        request.setBusinessType(businessType);
        request.setUserId(userId);
        request.setDescription(description);
        return upload(request);
    }

    @Override
    public FileUploadResponse uploadMultipleFiles(List<MultipartFile> files, String businessType, Long userId, String description) {
        FileUploadRequest request = new FileUploadRequest();
        request.setFiles(files);
        request.setBusinessType(businessType);
        request.setUserId(userId);
        request.setDescription(description);
        return upload(request);
    }

    @Override
    public FileUploadResponse upload(FileUploadRequest request){
        FileUploadResponse response = new FileUploadResponse();

        //单一文件
        if(!request.getFile().isEmpty()){
            MultipartFile file = request.getFile();
            // 1.生成安全文件名
            String originalFilename = file.getOriginalFilename();
            String fileExtension = FileUtils.getFileExtension(originalFilename);
            String safeFilename = generateSafeFilename(originalFilename);
            // 2.创建日期目录
            String dateDir = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
            String fullPath = uploadPath + dateDir + "/";
            // 3.确保目录存在
            Path directory = Paths.get(fullPath);
            try {
                Files.createDirectories(directory);
                // 4.保存文件
                Path filePath = directory.resolve(safeFilename);
                Files.copy(file.getInputStream(), filePath);
                // 5.生成文件URL
                String fileUrl = "/uploads/" + dateDir + "/" + safeFilename;
                // 6.二次安全检查（文件内容检查）
                if (!SecurityUtils.isFileContentSafe(filePath.toFile())) {
                    // 删除危险文件
                    Files.deleteIfExists(filePath);
                    throw new SecurityException("文件内容包含危险代码");
                }
                // 返回文件信息
                return FileUploadResponse.builder()
                        .fileName(originalFilename)
                        .filePath(filePath.toString())
                        .fileUrl(fileUrl)
                        .fileType(file.getContentType())
                        .fileSize(file.getSize())
                        .fileHash(FileUtils.calculateFileHash(filePath.toFile()))
                        .build();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        //多文件
        else if(!request.getFiles().isEmpty()){
            List<MultipartFile> filesToUpload = getFilesFromRequest(request);
            if (filesToUpload.isEmpty()) {
                response.setSuccess(false);
                response.setMessage("未接收到任何文件");
                return response;
            }
            List<FileUploadResponse.FileInfo> fileInfos = new ArrayList<>();
            for (MultipartFile file : filesToUpload) {
                FileUploadResponse.FileInfo fileInfo = uploadSingleFileInternal(
                        file,
                        request.getBusinessType(),
                        request.getUserId(),
                        request.getOverwrite()
                );
                fileInfos.add(fileInfo);
            }
            // 检查上传结果
            long successCount = fileInfos.stream()
                    .filter(FileUploadResponse.FileInfo::getUploadSuccess)
                    .count();

            response.setFileInfos(fileInfos);
            if (successCount == filesToUpload.size()) {
                response.setSuccess(true);
                response.setMessage("所有文件上传成功");
            } else if (successCount > 0) {
                response.setSuccess(true);
                response.setMessage("部分文件上传成功，成功数：" + successCount + "，总数：" + filesToUpload.size());
            } else {
                response.setSuccess(false);
                response.setMessage("所有文件上传失败");
            }
            return response;
        }else{

            return response;
        }
    }

    /**
     * 读取表单中的文件
     * @param request 表单数据
     * @return 文件列表
     */
    private List<MultipartFile> getFilesFromRequest(FileUploadRequest request) {
        List<MultipartFile> files = new ArrayList<>();

        // 优先使用files（多文件）
        if (request.getFiles() != null && !request.getFiles().isEmpty()) {
            files.addAll(request.getFiles());
        }
        // 其次使用file（单文件）
        else if (request.getFile() != null && !request.getFile().isEmpty()) {
            files.add(request.getFile());
        }

        return files;
    }

    private FileUploadResponse.FileInfo uploadSingleFileInternal(MultipartFile file,
                                                                 String businessType,
                                                                 Long userId,
                                                                 Boolean overwrite) {
        FileUploadResponse.FileInfo fileInfo = new FileUploadResponse.FileInfo();
        fileInfo.setOriginalFilename(file.getOriginalFilename());
        fileInfo.setFileSize(file.getSize());

        try {
            // 验证文件
            validateFile(file);

            // 生成存储文件名
            String storedFilename = generateStoredFilename(file.getOriginalFilename());
            fileInfo.setStoredFilename(storedFilename);

            // 获取文件类型
            String contentType = file.getContentType();
            fileInfo.setFileType(contentType);

            // 计算文件MD5
            String md5 = DigestUtils.md5DigestAsHex(file.getInputStream());
            fileInfo.setMd5(md5);

            // 构建存储路径
            String relativePath = buildRelativePath(businessType, storedFilename);
            String fullPath = uploadDir + File.separator + relativePath;
            fileInfo.setFilePath(relativePath);

            // 创建目录
            Path path = Paths.get(fullPath);
            Files.createDirectories(path.getParent());

            // 检查文件是否已存在
            if (Files.exists(path) && !Boolean.TRUE.equals(overwrite)) {
                fileInfo.setUploadSuccess(false);
                fileInfo.setErrorMessage("文件已存在，如需覆盖请设置overwrite=true");
                return fileInfo;
            }

            // 保存文件
            file.transferTo(path.toFile());

            // 构建访问URL（根据实际需求调整）
            String fileUrl = "/files/" + relativePath.replace("\\", "/");
            fileInfo.setFileUrl(fileUrl);
            fileInfo.setUploadSuccess(true);

            log.info("文件上传成功：{} -> {}", file.getOriginalFilename(), fullPath);

        } catch (IOException e) {
            log.error("文件保存失败", e);
            fileInfo.setUploadSuccess(false);
            fileInfo.setErrorMessage("文件保存失败：" + e.getMessage());
        } catch (Exception e) {
            log.error("文件处理失败", e);
            fileInfo.setUploadSuccess(false);
            fileInfo.setErrorMessage(e.getMessage());
        }

        return fileInfo;
    }

    private void validateFile(MultipartFile file) {
        if (file.isEmpty()) {
            throw new IllegalArgumentException("文件为空");
        }

        // 检查文件大小（这里再次检查，确保安全）
        if (file.getSize() > 10 * 1024 * 1024) { // 10MB
            throw new IllegalArgumentException("文件大小不能超过10MB");
        }

        // 检查文件类型（根据业务需求添加）
        String originalFilename = file.getOriginalFilename();
        if (originalFilename != null) {
            String extension = getFileExtension(originalFilename).toLowerCase();
            List<String> allowedExtensions = List.of("jpg", "jpeg", "png", "gif", "pdf", "doc", "docx", "txt");
            if (!allowedExtensions.contains(extension)) {
                throw new IllegalArgumentException("不支持的文件类型：" + extension);
            }
        }
    }

    private String generateStoredFilename(String originalFilename) {
        String extension = getFileExtension(originalFilename);
        String uuid = UUID.randomUUID().toString().replace("-", "");
        return uuid + (extension.isEmpty() ? "" : "." + extension);
    }

    private String buildRelativePath(String businessType, String storedFilename) {
        String datePath = LocalDateTime.now().format(DATE_FORMATTER);

        if (businessType == null || businessType.trim().isEmpty()) {
            businessType = "common";
        }

        return businessType + File.separator + datePath + File.separator + storedFilename;
    }

    private String getFileExtension(String filename) {
        if (filename == null || !filename.contains(".")) {
            return "";
        }
        return filename.substring(filename.lastIndexOf(".") + 1);
    }
}