package com.njcn.filesync.config;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashMap;
import java.util.Map;

/**
 * Description:
 * Date: 2025/10/16  下午 2:58【需求编号】文件同步状态管理
 *
 * @author clam
 * @version V1.0.0
 */
public class FileSyncState {
    private static final ObjectMapper objectMapper = new ObjectMapper();
    private String stateFilePath;
    private Map<String, FileMetadata> fileStates;

    public static class FileMetadata implements Serializable {
        private long size;
        private long lastModified;
        private String checksum;

        public FileMetadata() {}

        public FileMetadata(long size, long lastModified, String checksum) {
            this.size = size;
            this.lastModified = lastModified;
            this.checksum = checksum;
        }

        // Getters and Setters
        public long getSize() { return size; }
        public void setSize(long size) { this.size = size; }

        public long getLastModified() { return lastModified; }
        public void setLastModified(long lastModified) { this.lastModified = lastModified; }

        public String getChecksum() { return checksum; }
        public void setChecksum(String checksum) { this.checksum = checksum; }
    }

    public FileSyncState(String stateFilePath) {
        this.stateFilePath = stateFilePath;
        this.fileStates = new HashMap<>();
        loadState();
    }

    @SuppressWarnings("unchecked")
    private void loadState() {
        File stateFile = new File(stateFilePath);
        if (stateFile.exists()) {
            try {
                fileStates =objectMapper.readValue(stateFile,  new TypeReference<Map<String, FileMetadata>>() {});
            } catch (IOException e) {
                System.err.println("Failed to load sync state: " + e.getMessage());
                fileStates = new HashMap<>();
            }
        }
    }

    public void saveState() {
        try {
            objectMapper.writerWithDefaultPrettyPrinter()
                    .writeValue(new File(stateFilePath), fileStates);
        } catch (IOException e) {
            System.err.println("Failed to save sync state: " + e.getMessage());
        }
    }

    public boolean isFileChanged(String filePath, FileMetadata currentMetadata) {
        FileMetadata previousMetadata = fileStates.get(filePath);

        if (previousMetadata == null) {
            return true; // 新文件
        }

        // 检查文件大小和修改时间
        if (previousMetadata.getSize() != currentMetadata.getSize() ||
                previousMetadata.getLastModified() != currentMetadata.getLastModified()) {
            return true;
        }

        // 如果时间相同但需要更精确的比较，可以检查校验和
        if (currentMetadata.getChecksum() != null &&
                !currentMetadata.getChecksum().equals(previousMetadata.getChecksum())) {
            return true;
        }

        return false;
    }

    public void updateFileState(String filePath, FileMetadata metadata) {
        fileStates.put(filePath, metadata);
    }

    public FileMetadata getFileMetadata(String filePath) throws IOException {
        Path path = Paths.get(filePath);
        BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);

        // 计算简单的校验和（对于大文件，可以只计算部分校验和）
        String checksum = calculateSimpleChecksum(path.toFile());

        return new FileMetadata(
                attrs.size(),
                attrs.lastModifiedTime().toMillis(),
                checksum
        );
    }

    private String calculateSimpleChecksum(File file) {
        // 简化的校验和计算：文件大小 + 最后修改时间
        // 对于生产环境，建议使用MD5或SHA256
        return file.length() + "-" + file.lastModified();
    }
}
