package eu.mrneznamy.mrultimatelibrary.utils;

import eu.mrneznamy.mrultimatelibrary.scheduler.MrLibScheduler;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;

import eu.mrneznamy.mrultimatelibrary.utils.MrLibConsoleSayer;

public class MrLibUpdater {

    private final JavaPlugin plugin;
    private final String modrinthSlug;
    private final File pluginFile;

    public MrLibUpdater(JavaPlugin plugin, String modrinthSlug) {
        this.plugin = plugin;
        this.modrinthSlug = modrinthSlug;
        this.pluginFile = getPluginFile();
    }

    public void checkAndUpdate() {
        if (!plugin.getConfig().getBoolean("settings.auto-update.enabled", false)) {
            return;
        }

        MrLibScheduler.runTaskAsynchronously(plugin, () -> {
            try {
                String currentVersion = plugin.getDescription().getVersion();
                String[] versionData = fetchLatestVersionData();
                
                if (versionData == null) {
                    return;
                }
                
                String latestVersion = versionData[0];
                String downloadUrl = versionData[1];
                
                if (!isNewerVersion(latestVersion, currentVersion)) {
                    MrLibConsoleSayer.MrSay_Info("Plugin is up to date!");
                    return;
                }
                
                MrLibConsoleSayer.MrSay_Info("╔════════════════════════════════════════╗");
                MrLibConsoleSayer.MrSay_Info("║  Downloading new version...            ║");
                MrLibConsoleSayer.MrSay_Info("║  " + currentVersion + " → " + latestVersion + "                    ║");
                MrLibConsoleSayer.MrSay_Info("╚════════════════════════════════════════╝");
                
                if (downloadUpdate(downloadUrl)) {
                    
                    deleteOldJar();
                    
                    MrLibScheduler.runTask(plugin, () -> {
                        MrLibConsoleSayer.MrSay_Success("╔════════════════════════════════════════╗");
                        MrLibConsoleSayer.MrSay_Success("║  Update downloaded successfully!       ║");
                        MrLibConsoleSayer.MrSay_Success("║  Old plugin deleted                    ║");
                        MrLibConsoleSayer.MrSay_Success("║  Restart server to apply changes       ║");
                        MrLibConsoleSayer.MrSay_Success("╚════════════════════════════════════════╝");
                    });
                } else {
                    MrLibConsoleSayer.MrSay_Error("Failed to download update!");
                }
                
            } catch (Exception e) {
                MrLibConsoleSayer.MrSay_Error("Auto-update failed: " + e.getMessage());
            }
        });
    }

    private String[] fetchLatestVersionData() {
        try {
            HttpURLConnection conn = (HttpURLConnection) new URL(
                "https://api.modrinth.com/v2/project/" + modrinthSlug + "/version"
            ).openConnection();
            
            conn.setRequestProperty("User-Agent", "MrUltimateLibrary-Updater");
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);
            
            BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            StringBuilder response = new StringBuilder();
            String line;
            
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
            reader.close();
            
            String json = response.toString();
            
            
            String version = json.split("\"version_number\":\"")[1].split("\"")[0];
            
            
            String url = json.split("\"url\":\"")[1].split("\"")[0];
            
            return new String[]{version, url};
            
        } catch (Exception e) {
            MrLibConsoleSayer.MrSay_Error("Failed to fetch version data: " + e.getMessage());
            return null;
        }
    }

    private boolean downloadUpdate(String downloadUrl) {
        try {
            URL url = new URL(downloadUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestProperty("User-Agent", "MrUltimateLibrary-Updater");
            
            ReadableByteChannel rbc = Channels.newChannel(conn.getInputStream());
            File updateFolder = new File(plugin.getDataFolder().getParentFile(), "update");
            
            if (!updateFolder.exists()) {
                updateFolder.mkdir();
            }
            
            File outputFile = new File(updateFolder, pluginFile.getName());
            FileOutputStream fos = new FileOutputStream(outputFile);
            
            fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
            fos.close();
            rbc.close();
            
            MrLibConsoleSayer.MrSay_Info("Downloaded to: " + outputFile.getPath());
            return true;
            
        } catch (Exception e) {
            MrLibConsoleSayer.MrSay_Error("Download failed: " + e.getMessage());
            return false;
        }
    }

    private boolean isNewerVersion(String newVersion, String currentVersion) {
        try {
            String[] newParts = newVersion.replaceAll("[^0-9.]", "").split("\\.");
            String[] currentParts = currentVersion.replaceAll("[^0-9.]", "").split("\\.");
            
            int maxLength = Math.max(newParts.length, currentParts.length);
            
            for (int i = 0; i < maxLength; i++) {
                int newPart = i < newParts.length ? Integer.parseInt(newParts[i]) : 0;
                int currentPart = i < currentParts.length ? Integer.parseInt(currentParts[i]) : 0;
                
                if (newPart > currentPart) return true;
                if (newPart < currentPart) return false;
            }
            
            return false;
        } catch (Exception e) {
            return !newVersion.equals(currentVersion);
        }
    }

    private void deleteOldJar() {
        try {
            if (pluginFile != null && pluginFile.exists()) {
                
                if (pluginFile.delete()) {
                    MrLibConsoleSayer.MrSay_Info("Old plugin file deleted: " + pluginFile.getName());
                } else {
                    
                    pluginFile.deleteOnExit();
                    MrLibConsoleSayer.MrSay_Warning("Old plugin marked for deletion on restart");
                }
            }
        } catch (Exception e) {
            MrLibConsoleSayer.MrSay_Error("Failed to delete old plugin: " + e.getMessage());
        }
    }

    private File getPluginFile() {
        try {
            return new File(plugin.getClass().getProtectionDomain().getCodeSource().getLocation().toURI());
        } catch (Exception e) {
            return new File("plugins", plugin.getName() + ".jar");
        }
    }
}
