package com.dne.ems.service;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

/**
 * 通用服务，用于将数据以JSON文件形式存储和读取。
 * 提供线程安全的读写操作。
 */
@Service
public class JsonStorageService {

    private static final Logger log = LoggerFactory.getLogger(JsonStorageService.class);
    private final ObjectMapper objectMapper;
    private final Path storagePath;
    private final ConcurrentHashMap<String, Lock> fileLocks = new ConcurrentHashMap<>();

    /**
     * 构造函数，初始化ObjectMapper和存储路径。
     */
    public JsonStorageService() {
        this.objectMapper = new ObjectMapper();
        // 支持Java 8日期时间类型
        this.objectMapper.registerModule(new JavaTimeModule());
        // 禁用将日期写为时间戳（即数字），而是使用ISO-8601字符串格式
        this.objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        // 格式化输出JSON
        this.objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
        
        try {
            // 将数据库文件存放在项目的 'json-db' 目录下
            File dbDir = new File("json-db");
            if (!dbDir.exists()) {
                dbDir.mkdirs();
            }
            this.storagePath = dbDir.toPath();
            log.info("JSON storage path initialized at: {}", storagePath.toAbsolutePath());
        } catch (Exception e) {
            log.error("Failed to initialize JSON storage directory.", e);
            throw new RuntimeException("Could not initialize JSON storage directory", e);
        }
    }

    /**
     * 从指定的JSON文件读取数据列表。
     *
     * @param filename 文件名 (例如 "grids.json")
     * @param typeReference Jackson用于反序列化的类型引用
     * @param <T> 列表中的对象类型
     * @return 如果文件存在且非空，则返回数据列表；否则返回空列表。
     */
    public <T> List<T> readData(String filename, TypeReference<List<T>> typeReference) {
        Lock lock = fileLocks.computeIfAbsent(filename, k -> new ReentrantLock());
        lock.lock();
        try {
            Path filePath = storagePath.resolve(filename);
            if (!Files.exists(filePath) || Files.size(filePath) == 0) {
                log.warn("File {} not found or is empty. Returning empty list.", filename);
                return Collections.emptyList();
            }
            return objectMapper.readValue(filePath.toFile(), typeReference);
        } catch (IOException e) {
            log.error("Failed to read data from {}", filename, e);
            return Collections.emptyList();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 将数据列表写入指定的JSON文件。
     *
     * @param filename 文件名 (例如 "grids.json")
     * @param data 要写入的数据列表
     * @param <T> 列表中的对象类型
     */
    public <T> void writeData(String filename, List<T> data) {
        Lock lock = fileLocks.computeIfAbsent(filename, k -> new ReentrantLock());
        lock.lock();
        try {
            Path filePath = storagePath.resolve(filename);
            objectMapper.writeValue(filePath.toFile(), data);
            log.info("Successfully wrote {} records to {}", data.size(), filename);
        } catch (IOException e) {
            log.error("Failed to write data to {}", filename, e);
        } finally {
            lock.unlock();
        }
    }
} 