package tech.easyflow.ai.documentimport.task;

import org.springframework.web.multipart.MultipartFile;
import tech.easyflow.common.filestorage.FileStorageService;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 文档导入测试使用的内存文件存储。
 */
final class InMemoryFileStorageService implements FileStorageService {

    private final AtomicInteger sequence = new AtomicInteger();
    private final Map<String, byte[]> files = new LinkedHashMap<String, byte[]>();
    private String failingDeletePath;
    private int remainingDeleteFailures;

    /**
     * 保存到默认测试目录。
     *
     * @param file 上传文件
     * @return 测试路径
     */
    @Override
    public String save(MultipartFile file) {
        return save(file, "default");
    }

    /**
     * 保存到指定测试目录。
     *
     * @param file 上传文件
     * @param prePath 测试目录
     * @return 测试路径
     */
    @Override
    public String save(MultipartFile file, String prePath) {
        try {
            String path = prePath + "/" + sequence.incrementAndGet()
                + "-" + file.getOriginalFilename();
            files.put(path, file.getBytes());
            return path;
        } catch (IOException error) {
            throw new IllegalStateException("测试文件保存失败", error);
        }
    }

    /**
     * 删除测试对象。
     *
     * @param path 测试路径
     */
    @Override
    public void delete(String path) {
        if (remainingDeleteFailures > 0
            && path != null
            && path.equals(failingDeletePath)) {
            remainingDeleteFailures--;
            throw new IllegalStateException(
                "模拟删除失败: " + path);
        }
        files.remove(path);
    }

    /**
     * 打开测试对象。
     *
     * @param path 测试路径
     * @return 输入流
     * @throws IOException 对象不存在
     */
    @Override
    public InputStream readStream(String path) throws IOException {
        byte[] bytes = files.get(path);
        if (bytes == null) {
            throw new IOException("测试对象不存在: " + path);
        }
        return new ByteArrayInputStream(bytes);
    }

    /**
     * 返回测试对象大小。
     *
     * @param path 测试路径
     * @return 字节数
     */
    @Override
    public long getFileSize(String path) {
        byte[] bytes = files.get(path);
        return bytes == null ? -1L : bytes.length;
    }

    /**
     * 直接放入一个源文件。
     *
     * @param path 测试路径
     * @param bytes 文件内容
     */
    void put(String path, byte[] bytes) {
        files.put(path, bytes);
    }

    /**
     * 返回当前对象数量。
     *
     * @return 对象数量
     */
    int size() {
        return files.size();
    }

    /**
     * 判断测试对象是否存在。
     *
     * @param path 测试路径
     * @return 是否存在
     */
    boolean contains(String path) {
        return files.containsKey(path);
    }

    /**
     * 返回当前全部测试路径快照。
     *
     * @return 路径集合
     */
    Set<String> paths() {
        return new LinkedHashSet<String>(files.keySet());
    }

    /**
     * 配置指定路径接下来若干次删除失败。
     *
     * @param path 测试路径
     * @param failureCount 失败次数
     */
    void failDelete(String path, int failureCount) {
        failingDeletePath = path;
        remainingDeleteFailures = Math.max(0, failureCount);
    }
}
