
package org.to.telegramfinalproject.Client;

import org.json.JSONObject;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

public final class DownloadsIndex {
    private final UUID accountId;
    private final Path indexFile;
    private final Map<UUID, Entry> map = new ConcurrentHashMap<>();

    public DownloadsIndex(UUID accountId) {
        this.accountId = accountId;
        this.indexFile = resolveIndexPath(accountId.toString());
        load();
    }


    private static Path resolveIndexPath(String accountId) {
        String os = System.getProperty("os.name", "").toLowerCase();
        String home = System.getProperty("user.home");

        Path dir;
        if (os.contains("win")) {
            String appData = System.getenv("APPDATA");
            dir = (appData != null)
                    ? Paths.get(appData, "TeleSock")
                    : Paths.get(home, "AppData", "Roaming", "TeleSock");
        } else {
            dir = Paths.get(home, ".telesock");
        }
        try { Files.createDirectories(dir); } catch (IOException ignored) {}
        return dir.resolve("downloads-index-" + accountId + ".json");
    }

    private synchronized void load() {
        map.clear();
        try {
            if (!Files.exists(indexFile)) return;
            String json = Files.readString(indexFile, StandardCharsets.UTF_8);
            if (json == null || json.isBlank()) return;

            JSONObject root  = new JSONObject(json);
            JSONObject items = root.optJSONObject("items");
            if (items == null) return;

            for (String key : items.keySet()) {
                JSONObject e = items.getJSONObject(key);
                map.put(UUID.fromString(key), new Entry(
                        e.getString("path"),
                        e.optLong("size", 0L),
                        e.optLong("ts", System.currentTimeMillis())
                ));
            }
        } catch (Exception e) {
            System.err.println("⚠️ DownloadsIndex load failed: " + e.getMessage());
        }
    }

    private synchronized void save() throws IOException {
        JSONObject items = new JSONObject();
        for (Map.Entry<UUID, Entry> it : map.entrySet()) {
            JSONObject e = new JSONObject();
            e.put("path", it.getValue().path);
            e.put("size", it.getValue().size);
            e.put("ts",   it.getValue().ts);
            items.put(it.getKey().toString(), e);
        }
        byte[] data = new JSONObject().put("items", items).toString(2).getBytes(StandardCharsets.UTF_8);

        Path tmp = indexFile.resolveSibling(indexFile.getFileName() + ".tmp");
        Files.write(tmp, data);
        try {
            Files.move(tmp, indexFile, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE);
        } catch (AtomicMoveNotSupportedException ex) {
            Files.move(tmp, indexFile, StandardCopyOption.REPLACE_EXISTING);
        }
    }

    public void saveQuietly() {
        try { save(); } catch (Exception ignored) {}
    }

    public Path find(UUID mediaKey) {
        Entry e = map.get(mediaKey);
        if (e == null) return null;
        Path p = Paths.get(e.path);
        if (Files.exists(p)) return p;
        map.remove(mediaKey);
        saveQuietly();
        return null;
    }

    public void put(UUID mediaKey, Path path, long size) {
        map.put(mediaKey, new Entry(path.toString(), size, System.currentTimeMillis()));
        saveQuietly();
    }

    public void remove(UUID mediaKey) {
        map.remove(mediaKey);
        saveQuietly();
    }

    private static final class Entry {
        final String path; final long size; final long ts;
        Entry(String path, long size, long ts) {
            this.path = path; this.size = size; this.ts = ts;
        }
    }
}
