package net.viper.status.modules.verify;

import net.viper.status.StatusAPI;
import net.md_5.bungee.api.ChatColor;
import net.viper.status.StatusAPI;
import net.md_5.bungee.api.CommandSender;
import net.viper.status.StatusAPI;
import net.md_5.bungee.api.ProxyServer;
import net.viper.status.StatusAPI;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.viper.status.StatusAPI;
import net.md_5.bungee.api.plugin.Command;
import net.viper.status.StatusAPI;
import net.md_5.bungee.api.plugin.Plugin;
import net.viper.status.module.Module;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * VerifyModule: Multi-Server Support.
 *
 * Fix #7: Servernamen werden jetzt case-insensitiv verglichen.
 * Keys in serverConfigs werden beim Laden auf lowercase normalisiert
 * und die Suche erfolgt ebenfalls lowercase.
 */
public class VerifyModule implements Module {

    private String wpVerifyUrl;
    // Keys sind lowercase normalisiert f\u00fcr case-insensitiven Vergleich
    private final Map<String, ServerConfig> serverConfigs = new HashMap<>();

    @Override
    public String getName() { return "VerifyModule"; }

    @Override
    public void onEnable(Plugin plugin) {
        loadConfig(plugin);
        ProxyServer.getInstance().getPluginManager().registerCommand(plugin, new VerifyCommand());
        plugin.getLogger().fine("VerifyModule aktiviert. " + serverConfigs.size() + " Server-Konfigurationen geladen.");
    }

    @Override
    public void onDisable(Plugin plugin) {}

    private void loadConfig(Plugin plugin) {
        String fileName = "verify.properties";
        File configFile = new File(plugin.getDataFolder(), fileName);
        Properties props = new Properties();

        if (!configFile.exists()) {
            plugin.getDataFolder().mkdirs();
            try (InputStream in = plugin.getResourceAsStream(fileName);
                 OutputStream out = new FileOutputStream(configFile)) {
                if (in == null) { plugin.getLogger().warning("Standard-config '" + fileName + "' nicht in JAR."); return; }
                byte[] buffer = new byte[1024]; int length;
                while ((length = in.read(buffer)) > 0) out.write(buffer, 0, length);
                StatusAPI.debugLog(plugin, "Konfigurationsdatei '" + fileName + "' erstellt.");
            } catch (Exception e) { plugin.getLogger().severe("Fehler beim Erstellen der Config: " + e.getMessage()); return; }
        }

        try (InputStream in = new FileInputStream(configFile)) {
            props.load(in);
        } catch (IOException e) { e.printStackTrace(); return; }

        this.wpVerifyUrl = props.getProperty("wp_verify_url", "https://deine-wp-domain.tld");

        // FIX #7: Keys beim Laden auf lowercase normalisieren
        this.serverConfigs.clear();
        for (String key : props.stringPropertyNames()) {
            if (key.startsWith("server.")) {
                String[] parts = key.split("\\.");
                if (parts.length == 3) {
                    // Servername lowercase → case-insensitiver Lookup
                    String serverName = parts[1].toLowerCase();
                    String type = parts[2];
                    ServerConfig config = serverConfigs.computeIfAbsent(serverName, k -> new ServerConfig());
                    if ("id".equalsIgnoreCase(type)) {
                        try { config.serverId = Integer.parseInt(props.getProperty(key)); }
                        catch (NumberFormatException e) { plugin.getLogger().warning("Ung\u00fcltige Server ID f\u00fcr " + serverName); }
                    } else if ("secret".equalsIgnoreCase(type)) {
                        config.sharedSecret = props.getProperty(key);
                    }
                }
            }
        }
    }

    private static class ServerConfig {
        int serverId = 0;
        String sharedSecret = "";
    }

    private class VerifyCommand extends Command {
        public VerifyCommand() { super("verify"); }

        @Override
        public void execute(CommandSender sender, String[] args) {
            if (!(sender instanceof ProxiedPlayer)) { sender.sendMessage(ChatColor.RED + "Nur Spieler k\u00f6nnen diesen Befehl benutzen."); return; }
            ProxiedPlayer p = (ProxiedPlayer) sender;
            if (args.length != 1) { p.sendMessage(ChatColor.YELLOW + "Benutzung: /verify <token>"); return; }

            // FIX #7: Servername lowercase f\u00fcr case-insensitiven Lookup
            String serverName = p.getServer().getInfo().getName().toLowerCase();
            ServerConfig config = serverConfigs.get(serverName);

            if (config == null || config.serverId == 0 || config.sharedSecret.isEmpty()) {
                p.sendMessage(ChatColor.RED + "✗ Dieser Server ist nicht in der Verify-Konfiguration hinterlegt.");
                p.sendMessage(ChatColor.GRAY + "Aktueller Servername: " + ChatColor.WHITE + p.getServer().getInfo().getName());
                p.sendMessage(ChatColor.GRAY + "Bitte kontaktiere einen Admin.");
                return;
            }

            String token      = args[0].trim();
            String playerName = p.getName();

            HttpURLConnection conn = null;
            try {
                Charset utf8 = Charset.forName("UTF-8");
                String signature = hmacSHA256(playerName + token, config.sharedSecret, utf8);
                String payload   = "{\"player\":\"" + escapeJson(playerName)
                        + "\",\"token\":\"" + escapeJson(token)
                        + "\",\"server_id\":" + config.serverId
                        + ",\"signature\":\"" + signature + "\"}";

                URL url = new URL(wpVerifyUrl + "/wp-json/mc-gallery/v1/verify");
                conn = (HttpURLConnection) url.openConnection();
                conn.setConnectTimeout(5000);
                conn.setReadTimeout(7000);
                conn.setDoOutput(true);
                conn.setRequestMethod("POST");
                conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");
                try (OutputStream os = conn.getOutputStream()) { os.write(payload.getBytes(utf8)); }

                int code = conn.getResponseCode();
                String resp = code >= 200 && code < 300
                        ? streamToString(conn.getInputStream(), utf8)
                        : streamToString(conn.getErrorStream(), utf8);

                if (resp != null && !resp.isEmpty() && resp.trim().startsWith("{")) {
                    boolean isSuccess = resp.contains("\"success\":true");
                    String message = "Ein unbekannter Fehler ist aufgetreten.";
                    int keyIndex = resp.indexOf("\"message\":\"");
                    if (keyIndex != -1) {
                        int startIndex = keyIndex + 11;
                        int endIndex = resp.indexOf("\"", startIndex);
                        if (endIndex != -1) message = resp.substring(startIndex, endIndex);
                    }
                    if (isSuccess) {
                        p.sendMessage(ChatColor.GREEN + "✓ " + message);
                        p.sendMessage(ChatColor.GRAY + "Du kannst nun Bilder hochladen!");
                    } else {
                        p.sendMessage(ChatColor.RED + "✗ " + message);
                    }
                } else {
                    p.sendMessage(ChatColor.RED + "✗ Fehler beim Verbinden mit der Webseite (Code: " + code + ")");
                }
            } catch (Exception ex) {
                p.sendMessage(ChatColor.RED + "✗ Ein interner Fehler ist aufgetreten.");
                ProxyServer.getInstance().getLogger().warning("Verify error: " + ex.getMessage());
                ex.printStackTrace();
            } finally {
                if (conn != null) conn.disconnect();
            }
        }
    }

    private static String hmacSHA256(String data, String key, Charset charset) throws Exception {
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(key.getBytes(charset), "HmacSHA256"));
        byte[] raw = mac.doFinal(data.getBytes(charset));
        StringBuilder sb = new StringBuilder();
        for (byte b : raw) sb.append(String.format("%02x", b));
        return sb.toString();
    }

    private static String streamToString(InputStream in, Charset charset) throws IOException {
        if (in == null) return "";
        try (BufferedReader br = new BufferedReader(new InputStreamReader(in, charset))) {
            StringBuilder sb = new StringBuilder(); String line;
            while ((line = br.readLine()) != null) sb.append(line);
            return sb.toString();
        }
    }

    private static String escapeJson(String s) {
        return s.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n").replace("\r", "\\r");
    }
}
