package com.jeeplus.assess.invoice.utils.OMS;


import cn.hutool.extra.spring.SpringUtil;
import com.jeeplus.sys.feign.IWorkAttachmentApi;
import com.jeeplus.utils.StringUtils;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import static com.jeeplus.assess.invoice.config.FinanceOmsConfig.*;

public class FileHandlingUtil {

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


    /**
     * 将远程URL文件下载到指定系统目录，并支持自定义重命名（内置异常处理，无返回类）
     * 基础路径规则：
     * - Windows：D:/attachment-file/
     * - Linux/Mac：/attachment-file/
     * @param remoteFileUrl  远程文件的URL地址（必填）
     * @param newFileName    重命名后的文件名（支持3种传法）：
     *                       1. 传完整文件名（如"invoice_20260127_123456.pdf"）→ 直接使用
     *                       2. 传前缀（如"invoice_123456"）→ 自动补原后缀
     *                       3. 传null/空 → 自动生成UUID+原后缀
     * @return String 成功返回本地完整路径，失败返回null
     */
    public static String downloadFileToSpecifiedPath(String remoteFileUrl, String newFileName) {
        // ===================== 1. 前置参数校验 =====================
        if (remoteFileUrl == null || remoteFileUrl.trim().isEmpty()) {
            log.error("远程文件URL不能为空");
            return null;
        }

        // ===================== 2. 内部判定系统基础路径 =====================
        String basePath;
        if (System.getProperty("os.name").toLowerCase().contains("win")) {
            basePath = "D:/attachment-file/";
        } else {
            basePath = "/attachment-file/";
        }
        if (!basePath.endsWith(File.separator)) {
            basePath += File.separator;
        }

        // ===================== 3. 处理重命名逻辑 =====================
        String originalSuffix = getFileSuffixFromUrl(remoteFileUrl);
        String finalFileName;

        if (newFileName == null || newFileName.trim().isEmpty()) {
            finalFileName = UUID.randomUUID().toString() + originalSuffix;
        } else if (newFileName.contains(".")) {
            finalFileName = newFileName.trim();
        } else {
            finalFileName = newFileName.trim() + originalSuffix;
        }

        // 拼接完整路径
        String fullLocalPath = basePath + finalFileName;
        File localFile = new File(fullLocalPath);

        // ===================== 4. 核心下载逻辑（内置try-catch） =====================
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(30, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .build();

        Request request = new Request.Builder().url(remoteFileUrl).build();

        try {
            // 自动创建基础目录
            File parentDir = localFile.getParentFile();
            if (!parentDir.exists()) {
                boolean mkdirsSuccess = parentDir.mkdirs();
                if (!mkdirsSuccess) {
                    log.error("创建基础目录失败：{}", parentDir.getAbsolutePath());
                    return null;
                }
                log.info("系统基础目录创建成功：{}", parentDir.getAbsolutePath());
            }

            // 发起请求下载文件
            try (Response response = okHttpClient.newCall(request).execute();
                 InputStream inputStream = response.body().byteStream();
                 FileOutputStream outputStream = new FileOutputStream(localFile)) {

                if (!response.isSuccessful()) {
                    log.error("下载文件失败，URL：{}，响应码：{}", remoteFileUrl, response.code());
                    // 清理临时文件
                    if (localFile.exists()) localFile.delete();
                    return null;
                }

                // 写入文件
                byte[] buffer = new byte[1024 * 8];
                int len;
                while ((len = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, len);
                }

                log.info("文件下载并完成重命名！远程URL：{}，本地保存路径：{}", remoteFileUrl, fullLocalPath);
                // 下载成功，返回本地路径
                return fullLocalPath;

            }
        } catch (IOException e) {
            // 捕获所有IO异常，记录日志后返回null
            log.error("文件下载失败：{}，原因：{}", remoteFileUrl, e.getMessage(), e);
            // 清理临时文件
            if (localFile.exists()) localFile.delete();
            return null;
        }
    }

    /**
     * 辅助方法：从URL提取文件后缀
     */
    private static String getFileSuffixFromUrl(String url) {
        if (url == null || !url.contains(".")) {
            return ".bin";
        }
        String suffix = url.substring(url.lastIndexOf("."));
        if (suffix.contains("?") || suffix.contains("#")) {
            suffix = suffix.substring(0, suffix.indexOf("?"));
        }
        return suffix;
    }





    private static String datePath(){

        Calendar date = Calendar.getInstance();
        String year = String.valueOf(date.get(Calendar.YEAR));
        //String month = String.valueOf(date.get(Calendar.MONTH)+1);
        //String day = String.valueOf(date.get(Calendar.DAY_OF_MONTH));
        //String path = "/"+year+"/"+month+"/"+day;
        String path = "/"+year;
        return path;
    }


    /**
     * 本地文件上传到阿里云OSS（文件大小用File.length()获取，返回Map包含OSS路径+文件大小）
     * @param filePath 本地文件的完整路径（必填，如：D:/attachment-file/KP-2026-0054.pdf）
     * @param fileStorageLocation 文件存储位置（自定义子目录）
     * @return Map<String, Object> 结果说明：
     *         - success：boolean，上传是否成功
     *         - ossFilePath：String，成功时为OSS完整存储路径，失败时为null
     *         - fileSize：Long，成功时为文件大小（字节，通过File.length()获取），失败时为0
     *         - errorMsg：String，失败时为错误信息，成功时为null
     */
    public static Map<String, Object> fileUpload(String filePath, String fileStorageLocation,String uploadPrefix) {
        // 初始化返回Map
        Map<String, Object> resultMap = new HashMap<>(4);
        resultMap.put("success", false); // 默认失败
        resultMap.put("ossFilePath", null);
        resultMap.put("fileSize", 0L);
        resultMap.put("errorMsg", null);

        // ========== 1. 基础参数校验 ==========
        if (StringUtils.isBlank(filePath)) {
            String errorMsg = "文件上传失败：文件路径不能为空";
            log.error(errorMsg);
            resultMap.put("errorMsg", errorMsg);
            return resultMap;
        }
        File localFile = new File(filePath);
        if (!localFile.exists()) {
            String errorMsg = "文件上传失败：文件不存在，路径：" + filePath;
            log.error(errorMsg);
            resultMap.put("errorMsg", errorMsg);
            return resultMap;
        }
        if (!localFile.isFile()) {
            String errorMsg = "文件上传失败：路径不是有效文件，路径：" + filePath;
            log.error(errorMsg);
            resultMap.put("errorMsg", errorMsg);
            return resultMap;
        }

        // ========== 核心：文件大小直接用File.length()（即file.size）获取 ==========
        long fileSize = localFile.length(); // 等价于你说的file.size，返回字节数
        log.info("获取本地文件信息：文件名={}，文件大小（file.size）={} 字节", localFile.getName(), fileSize);

        // 获取本地文件原文件名（用于uploadFileSignatureOSS第三个参数）
        String originalFileName = localFile.getName();
        log.info("获取本地文件原文件名：{}", originalFileName);

        InputStream fileInputStream = null;
        try {
            // ========== 2. 读取文件流 ==========
            fileInputStream = new FileInputStream(localFile);
            MultipartFile multipartFile = new MockMultipartFile(
                    "file",
                    originalFileName,
                    null,
                    fileInputStream
            );
            if (multipartFile.isEmpty()) {
                String errorMsg = "文件上传失败：文件流为空，本地路径：" + filePath;
                log.error(errorMsg);
                resultMap.put("errorMsg", errorMsg);
                return resultMap;
            }

            // ========== 3. 拼接OSS存储目录 ==========
            String baseDir = directory.replaceFirst("/", "");
            String realPath = baseDir + "/OMS_invoice" +"/"+ uploadPrefix + datePath() + "/" + fileStorageLocation + "/";
            if (!realPath.endsWith("/")) {
                realPath += "/";
            }

            // ========== 4. 调用原有uploadFileSignatureOSS方法，第三个参数传原文件名 ==========
            SpringUtil.getBean ( IWorkAttachmentApi.class ).uploadFileSignatureOSS(localFile.getPath(), realPath, originalFileName);

            // ========== 5. 上传成功后删除本地文件 ==========
            boolean deleteSuccess = localFile.delete();
            if (deleteSuccess) {
                log.info("本地文件删除成功！路径：{}", filePath);
            } else {
                log.warn("本地文件删除失败（文件可能已被占用）！路径：{}", filePath);
                // 删除失败不影响返回结果，仅告警
            }

            // ========== 6. 上传成功：更新Map结果（包含file.size获取的文件大小） ==========
            String ossFullFilePath = realPath + originalFileName;
            resultMap.put("success", true);
            resultMap.put("ossFilePath", ossFullFilePath);
            resultMap.put("fileSize", fileSize); // 存入file.size获取的字节数
            resultMap.put("errorMsg", null);
            log.info("文件上传OSS完成！本地路径：{}，OSS路径：{}，文件大小：{} 字节",
                    filePath, ossFullFilePath, fileSize);

        } catch (IOException e) {
            String errorMsg = "文件上传OSS失败：本地路径=" + filePath + "，异常原因=" + e.getMessage();
            log.error(errorMsg, e);
            resultMap.put("errorMsg", errorMsg);
        } finally {
            // ========== 7. 释放资源 ==========
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    log.error("关闭本地文件流失败", e);
                }
            }
        }

        return resultMap;
    }

}
