package cz.kamma.llamarunner;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

/**
 * Profile management using JSON file in user's home directory.
 */
public class ProfileManager {

    private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
    private final ConfigLocation configLocation;

    public ProfileManager() {
        this(new ConfigLocation());
    }

    public ProfileManager(ConfigLocation configLocation) {
        this.configLocation = configLocation;
    }

    /**
     * Saves profile to JSON file.
     */
    public void saveProfile(String name, ModelConfig config) throws IOException {
        configLocation.ensureDirectoryExists();
        Map<String, ModelConfig> profiles = loadAllProfiles();
        profiles.put(name, config);

        try (FileWriter writer = new FileWriter(configLocation.getProfilesJsonFile())) {
            GSON.toJson(profiles, writer);
        }
    }

    /**
     * Loads profile from JSON file.
     */
    public ModelConfig loadProfile(String name) throws IOException {
        Map<String, ModelConfig> profiles = loadAllProfiles();
        ModelConfig config = profiles.get(name);
        if (config == null) {
            throw new IOException("Profile does not exist: " + name);
        }
        return config;
    }

    /**
     * Deletes profile from JSON file.
     */
    public void deleteProfile(String name) throws IOException {
        Map<String, ModelConfig> profiles = loadAllProfiles();
        if (!profiles.containsKey(name)) {
            throw new IOException("Profile does not exist: " + name);
        }
        profiles.remove(name);

        try (FileWriter writer = new FileWriter(configLocation.getProfilesJsonFile())) {
            GSON.toJson(profiles, writer);
        }
    }

    /**
     * Returns the path to the profiles file.
     */
    public String getProfilesFilePath() {
        return configLocation.getProfilesJsonFilePath();
    }

    /**
     * Returns the list of profile names.
     */
    public List<String> listProfiles() throws IOException {
        Map<String, ModelConfig> profiles = loadAllProfiles();
        return profiles != null ? new ArrayList<>(profiles.keySet()) : new ArrayList<>();
    }

    /**
     * Checks if profile exists.
     */
    public boolean profileExists(String name) {
        try {
            Map<String, ModelConfig> profiles = loadAllProfiles();
            return profiles.containsKey(name);
        } catch (IOException e) {
            return false;
        }
    }

    /**
     * Renames a profile from oldName to newName.
     */
    public void renameProfile(String oldName, String newName) throws IOException {
        Map<String, ModelConfig> profiles = loadAllProfiles();
        if (!profiles.containsKey(oldName)) {
            throw new IOException("Profile does not exist: " + oldName);
        }
        if (oldName.equals(newName)) {
            throw new IOException("Old and new names must be different.");
        }
        if (profiles.containsKey(newName)) {
            throw new IOException("Profile already exists: " + newName);
        }

        ModelConfig config = profiles.remove(oldName);
        profiles.put(newName, config);

        try (FileWriter writer = new FileWriter(configLocation.getProfilesJsonFile())) {
            GSON.toJson(profiles, writer);
        }
    }

    /**
     * Loads all profiles from JSON file.
     */
    private Map<String, ModelConfig> loadAllProfiles() throws IOException {
        if (!configLocation.getProfilesJsonFile().exists()) {
            return new HashMap<>();
        }

        try (FileReader reader = new FileReader(configLocation.getProfilesJsonFile())) {
            java.lang.reflect.Type mapType = new TypeToken<Map<String, ModelConfig>>() {}.getType();
            Map<String, ModelConfig> profiles = GSON.fromJson(reader, mapType);
            return profiles != null ? profiles : new HashMap<>();
        } catch (Exception e) {
            return new HashMap<>();
        }
    }
}
