/**
 * @Author: Kane Wang <wangkane@qq.com>
 * @Date: 2025-10-16 09:46:42
 * @LastEditors: Kane Wang
 * @LastModified: 2026-02-06 19:08:46
 * @FilePath: src/main/java/com/cpic/xim/utils/files/SaveUploadFile.java
 * @Description:
 *
 *               Copyright (c) 2025 by Kane All rights reserved
 */
package com.cpic.xim.utils.files;

import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.HashMap;
import java.util.Vector;

import org.springframework.web.multipart.MultipartFile;

import com.cpic.xim.utils.files.exceptions.MoveUploadedFileException;
import com.cpic.xim.utils.files.exceptions.ProcessUploadedFileException;

public class SaveUploadFile
{
    /**
     * 
     * @param files
     * @param tempFilePath
     * @return
     * @throws ProcessUploadedFileException
     */
    public static HashMap<String, String> saveUploadFile(
            MultipartFile[] files,
            String tempFilePath
    )
      throws ProcessUploadedFileException
    {
        HashMap<String, String> savedFiles = new HashMap<>();
        // File                    dir        = new File( tempFilePath );
        String fileName = "";
        String fullPath;

        if ( !(tempFilePath.endsWith( "/" ) || tempFilePath.endsWith( "\\" )) )
        {
            fullPath = tempFilePath + "/";
        }
        else
        {
            fullPath = tempFilePath;
        }

        try
        {
            for ( MultipartFile file : files )
            {
                // 空文件跳过
                if ( file.isEmpty() )
                {
                    continue;
                }

                // 文件名前加上时间戳，避免覆盖
                Long milliSecond = LocalDateTime.now().toInstant( ZoneOffset.of( "+8" ) ).toEpochMilli();

                fileName = String.valueOf( milliSecond ) + " - " + file.getOriginalFilename();
                File destFile = new File( tempFilePath, fileName );

                file.transferTo( destFile );

                savedFiles.put( fileName, fullPath + fileName );
            }
        }
        catch ( IOException error )
        {
            throw new ProcessUploadedFileException( "临时目录" + tempFilePath + "保存文件" + fileName + "失败!" );
        }

        return savedFiles;
    }

    /**
     * 将files参数中上传的文件，保存到tempFilePath指定的路径，文件名加上毫秒数避免重复。
     * 
     * @param files
     * @param absoluteFilePath
     * @return 返回UploadedFile对象数组
     * @throws ProcessUploadedFileException
     */
    public static Vector<UploadedFile> saveUploadFiles(
            MultipartFile[] files,
            String absoluteFilePath,
            String relativeFilePath
    )
      throws ProcessUploadedFileException
    {
        Vector<UploadedFile> savedFiles   = new Vector<>();
        UploadedFile         uploadedFile = null;
        // File                    dir        = new File( tempFilePath );
        String fileName = "";
        String fullPath = null;

        if ( !(absoluteFilePath.endsWith( "/" ) || absoluteFilePath.endsWith( "\\" )) )
        {
            fullPath = absoluteFilePath + "/";
        }
        else
        {
            fullPath = absoluteFilePath;
        }

        try
        {
            for ( MultipartFile file : files )
            {
                // 空文件跳过
                if ( file.isEmpty() )
                {
                    continue;
                }

                // 文件名前加上时间戳，避免覆盖
                Long milliSecond = LocalDateTime.now().toInstant( ZoneOffset.of( "+8" ) ).toEpochMilli();

                fileName = String.valueOf( milliSecond ) + "-" + file.getOriginalFilename();
                File destFile = new File( fullPath, fileName );

                file.transferTo( destFile );

                uploadedFile = new UploadedFile( file.getOriginalFilename(), fileName, fullPath, relativeFilePath );

                savedFiles.add( uploadedFile );
            }
        }
        catch ( IOException error )
        {
            throw new ProcessUploadedFileException( "临时目录" + absoluteFilePath + "保存文件" + fileName + "失败!" );
        }

        return savedFiles;
    }

    /**
     * 
     * @param originFilePath 文件路径
     * @param newFilePath    新文件存放路径
     * @throws MoveUploadedFileException
     */
    public static void MoveUploadedFile(
            String originFilePath,
            String newFilePath
    )
      throws MoveUploadedFileException
    {
        // 防御性验证
        File originFile = new File( originFilePath );
        File dest       = new File( newFilePath );

        // 文件如果不存在就抛出异常
        if ( originFile.exists() == false )
        {
            throw new MoveUploadedFileException( "文件不存在！" );
        }

        // 目的路径有同名文件
        if ( dest.exists() == true )
        {
            throw new MoveUploadedFileException( "目的路径已存在同名文件！" );
        }

        // 不知道具体原因
        if ( originFile.renameTo( dest ) == false )
        {
            throw new MoveUploadedFileException( "移动文件失败！" );
        }
    }

    public static String encodeFileName( String originalFileName )
    {
        StringBuilder encodedFileName = new StringBuilder( originalFileName.length() * 3 );
        char[]        charArray       = originalFileName.toCharArray();

        for ( char c : charArray )
        {
            switch ( c )
            {
                case '%':
                    encodedFileName.append( PERCENT );
                    break;
                case ' ':
                    encodedFileName.append( SPACING );
                    break;
                case '+':
                    encodedFileName.append( PLUS );
                    break;
                case '/':
                    encodedFileName.append( FORWARD_SLASH );
                    break;
                case '?':
                    encodedFileName.append( QUESTION_MASK );
                    break;
                case '&':
                    encodedFileName.append( AMPERSAND );
                    break;
                case '#':
                    encodedFileName.append( SHARP );
                    break;
                case '=':
                    encodedFileName.append( PLUS );
                    break;
                default:
                    encodedFileName.append( c );
            }
        }

        return encodedFileName.toString();
    }

    static final String SHARP         = "%23";
    static final String PLUS          = "%2B";
    static final String FORWARD_SLASH = "%2F";
    static final String QUESTION_MASK = "%3F";
    static final String SPACING       = "%20";
    static final String EQUAL         = "%3D";
    static final String PERCENT       = "%25";
    static final String AMPERSAND     = "%26";
}
