package tech.easyflow.publicapi.service;

import org.springframework.stereotype.Service;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import tech.easyflow.common.web.exceptions.BusinessException;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Public Workflow multipart Part 与开始节点文件参数的映射器。
 */
@Service
public class WorkflowApiMultipartParameterMapper {

    /** API 请求元数据 Part 名。 */
    public static final String METADATA_PART_NAME = "metadata";
    /** 工作流文件参数 Part 前缀。 */
    public static final String FILE_PART_PREFIX = "files.";

    /**
     * 将 API multipart 文件 Part 映射为开始节点文件参数。
     *
     * <p>{@code metadata} 只属于 API 信封，不参与工作流变量映射；
     * {@code files.<参数名>} 去除前缀后才作为开始节点参数名。</p>
     *
     * @param rawFileParts Servlet 解析出的原始文件 Part
     * @return 以开始节点文件参数名分组的文件
     * @throws BusinessException Part 未使用规定命名空间或参数名为空时抛出
     */
    public Map<String, List<MultipartFile>> map(
            MultiValueMap<String, MultipartFile> rawFileParts) {
        if (rawFileParts == null || rawFileParts.isEmpty()) {
            return Map.of();
        }
        Map<String, List<MultipartFile>> mapped = new LinkedHashMap<>();
        for (Map.Entry<String, List<MultipartFile>> entry :
                rawFileParts.entrySet()) {
            String partName = entry.getKey();
            if (METADATA_PART_NAME.equals(partName)) {
                continue;
            }
            if (!StringUtils.hasText(partName)
                    || !partName.startsWith(FILE_PART_PREFIX)) {
                throw new BusinessException(
                        400,
                        40016,
                        "文件 Part 必须使用 files.<开始节点文件参数名>");
            }
            String parameterName =
                    partName.substring(FILE_PART_PREFIX.length());
            if (!StringUtils.hasText(parameterName)
                    || !parameterName.equals(parameterName.trim())) {
                throw new BusinessException(
                        400,
                        40016,
                        "文件 Part 中的开始节点文件参数名无效");
            }
            mapped.put(
                    parameterName,
                    entry.getValue() == null
                            ? List.of()
                            : new ArrayList<>(entry.getValue()));
        }
        return mapped;
    }
}
