package de.mviper.spigot;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;

import net.milkbowl.vault.economy.Economy;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

public class IngameShopSpigot extends JavaPlugin implements Listener {

    private static Economy econ = null;
    private String wpBase; 
    private String wpUrlPending;
    private String wpUrlExecute;
    private String wpUrlComplete;
    private String wpUrlCancel; // NEU
    
    private Gson gson = new Gson();
    private boolean debug = false;
    private BukkitTask task;

    private String currency = "Coins";
    private String targetServer = "survival";

    private Map<Integer, OrderData> orderCache = new HashMap<>();
    private Map<UUID, Integer> activeOrderIds = new HashMap<>();

    @Override
    public void onEnable() {
        if (!setupEconomy()) {
            getLogger().severe("Kein Economy-Plugin (Vault) gefunden! Shop deaktiviert.");
            getServer().getPluginManager().disablePlugin(this);
            return;
        }

        saveDefaultConfig();
        reloadConfig();
        
        String domain = getConfig().getString("wordpress-url", "http://localhost/Windelgeschichten.org");
        if (domain.endsWith("/")) {
            domain = domain.substring(0, domain.length() - 1);
        }
        wpBase = domain + "/wp-json/wis/v1";
        
        wpUrlPending = wpBase + "/pending_orders";
        wpUrlExecute = wpBase + "/execute_order";
        wpUrlComplete = wpBase + "/complete_order";
        wpUrlCancel = wpBase + "/cancel_order"; // NEU
        
        this.targetServer = getConfig().getString("server-name", "survival").toLowerCase();
        this.currency = getConfig().getString("currency-name", "Coins");
        
        int intervalSeconds = getConfig().getInt("check-interval", 10);
        long pollInterval = intervalSeconds * 20L; 
        debug = getConfig().getBoolean("debug-mode", false);
        
        getServer().getPluginManager().registerEvents(this, this);
        startPolling(pollInterval);
        
        getLogger().info("=== IngameShopSpigot v6.2 (Cancel Logic) CONFIG ===");
        getLogger().info("Domain: " + domain);
        getLogger().info("Target Server: " + this.targetServer);
        getLogger().info("Currency: " + this.currency);
    }

    private boolean setupEconomy() {
        RegisteredServiceProvider<Economy> rsp = getServer().getServicesManager().getRegistration(Economy.class);
        if (rsp == null) return false;
        econ = rsp.getProvider();
        return econ != null;
    }

    private void startPolling(long intervalTicks) {
        this.task = new BukkitRunnable() {
            @Override
            public void run() {
                new BukkitRunnable() {
                    @Override
                    public void run() {
                        for (Player p : Bukkit.getOnlinePlayers()) {
                            try {
                                String urlString = wpUrlPending + "?player=" + p.getName();
                                URL url = new URL(urlString);
                                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                                conn.setRequestMethod("GET");
                                conn.setRequestProperty("Content-Type", "application/json");
                                conn.setConnectTimeout(5000);
                                conn.setReadTimeout(5000);

                                if (conn.getResponseCode() == 200) {
                                    BufferedReader reader = new BufferedReader(
                                        new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)
                                    );
                                    StringBuilder response = new StringBuilder();
                                    String line;
                                    while ((line = reader.readLine()) != null) {
                                        response.append(line);
                                    }
                                    reader.close();

                                    JsonObject json = JsonParser.parseString(response.toString()).getAsJsonObject();
                                    JsonArray orders = json.getAsJsonArray("orders");

                                    if (orders != null && orders.size() > 0) {
                                        for (int i = 0; i < orders.size(); i++) {
                                            JsonObject order = orders.get(i).getAsJsonObject();
                                            
                                            int id = order.get("id").getAsInt();
                                            String orderServer = order.has("server") ? order.get("server").getAsString().toLowerCase() : "";
                                            
                                            if (!orderServer.equals(targetServer)) {
                                                if (debug) getLogger().info("Order #" + id + " ist für Server '" + orderServer + "'. Ignoriere.");
                                                continue;
                                            }

                                            String jsonResponse = order.has("response") ? order.get("response").getAsString() : "[]";
                                            String itemTitle = order.get("item_title").getAsString();
                                            double price = order.get("price").getAsDouble();
                                            String status = order.get("status").getAsString();
                                            
                                            if ("pending".equals(status)) {
                                                OrderData data = new OrderData(id, "multi_item", itemTitle, price, 1, jsonResponse);
                                                orderCache.put(id, data);
                                                activeOrderIds.put(p.getUniqueId(), id);
                                                
                                                Bukkit.getScheduler().runTask(IngameShopSpigot.this, () -> {
                                                    openConfirmGUI(p, id, itemTitle, price);
                                                });
                                            }
                                        }
                                    }
                                }
                            } catch (Exception e) {
                                if (debug) Bukkit.getLogger().log(Level.WARNING, "Polling Fehler", e);
                            }
                        }
                    }
                }.runTaskAsynchronously(IngameShopSpigot.this);
            }
        }.runTaskTimer(this, 20L, intervalTicks);
    }

    private void openConfirmGUI(Player player, int orderId, String itemTitle, double price) {
        Inventory gui = Bukkit.createInventory(null, 27, "§eKauf bestätigen?");

        ItemStack info = new ItemStack(Material.WRITTEN_BOOK);
        ItemMeta infoMeta = info.getItemMeta();
        infoMeta.setDisplayName(ChatColor.GOLD + itemTitle);
        infoMeta.setLore(java.util.Arrays.asList(
            ChatColor.WHITE + "Preis: " + price + " " + currency
        ));
        info.setItemMeta(infoMeta);

        ItemStack yes = new ItemStack(Material.LIME_WOOL);
        ItemMeta yesMeta = yes.getItemMeta();
        yesMeta.setDisplayName(ChatColor.GREEN + "§lJA, kaufen!");
        yes.setItemMeta(yesMeta);
        
        ItemStack no = new ItemStack(Material.RED_WOOL);
        ItemMeta noMeta = no.getItemMeta();
        noMeta.setDisplayName(ChatColor.RED + "§lNEIN, abbrechen");
        no.setItemMeta(noMeta);

        ItemStack pane = new ItemStack(Material.BLACK_STAINED_GLASS_PANE);
        ItemMeta paneMeta = pane.getItemMeta();
        paneMeta.setDisplayName(" ");
        pane.setItemMeta(paneMeta);

        for (int i = 0; i < 27; i++) gui.setItem(i, pane);
        gui.setItem(13, info);
        gui.setItem(11, yes);
        gui.setItem(15, no);

        player.openInventory(gui);
    }

    @EventHandler
    public void onInventoryClick(InventoryClickEvent event) {
        if (!event.getView().getTitle().contains("Kauf bestätigen?")) return;
        event.setCancelled(true);
        if (!(event.getWhoClicked() instanceof Player)) return;
        
        Player p = (Player) event.getWhoClicked();
        int slot = event.getRawSlot();
        
        if (slot == 11) { // JA
            Integer orderId = activeOrderIds.get(p.getUniqueId());
            if (orderId != null) {
                processOrder(p, orderId);
                p.closeInventory();
                activeOrderIds.remove(p.getUniqueId());
            } else {
                p.sendMessage(ChatColor.RED + "❌ Fehler: Kauf abgelaufen.");
                p.closeInventory();
            }
        } else if (slot == 15) { // NEIN
            Integer orderId = activeOrderIds.get(p.getUniqueId());
            if (orderId != null) {
                cancelOrder(p, orderId); // NEU
                p.closeInventory();
                activeOrderIds.remove(p.getUniqueId());
            }
        }
    }

    private void processOrder(Player player, int orderId) {
        OrderData data = orderCache.get(orderId);
        if (data == null) {
            player.sendMessage(ChatColor.RED + "❌ Fehler: Daten nicht gefunden.");
            return;
        }

        new BukkitRunnable() {
            @Override
            public void run() {
                try {
                    String jsonInputString = "{\"id\":\"" + orderId + "\"}";
                    URL url = new URL(wpUrlExecute);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setRequestMethod("POST");
                    conn.setRequestProperty("Content-Type", "application/json");
                    conn.setDoOutput(true);
                    
                    try(OutputStream os = conn.getOutputStream()) {
                        byte[] input = jsonInputString.getBytes("utf-8");
                        os.write(input, 0, input.length);
                    }
                    
                    int responseCode = conn.getResponseCode();
                    if (responseCode == 200) {
                        Bukkit.getScheduler().runTask(IngameShopSpigot.this, () -> executeShopLogic(player, data, orderId));
                    } else {
                        if (debug) getLogger().warning("Execute Order API Code: " + responseCode);
                        Bukkit.getScheduler().runTask(IngameShopSpigot.this, () -> {
                            player.sendMessage(ChatColor.RED + "❌ Server-Fehler beim Starten des Kaufs.");
                        });
                    }
                } catch (Exception e) {
                    getLogger().log(Level.SEVERE, "Fehler bei /execute_order", e);
                    Bukkit.getScheduler().runTask(IngameShopSpigot.this, () -> {
                        player.sendMessage(ChatColor.RED + "❌ Interner Fehler beim Kauf.");
                    });
                }
            }
        }.runTaskAsynchronously(this);
    }

    // ===========================================================
    // NEU: ABBRECHEN LOGIC
    // ===========================================================
    private void cancelOrder(Player player, int orderId) {
        new BukkitRunnable() {
            @Override
            public void run() {
                try {
                    String jsonInputString = "{\"id\":\"" + orderId + "\"}";
                    URL url = new URL(wpUrlCancel);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setRequestMethod("POST");
                    conn.setRequestProperty("Content-Type", "application/json");
                    conn.setDoOutput(true);
                    
                    try(OutputStream os = conn.getOutputStream()) {
                        byte[] input = jsonInputString.getBytes("utf-8");
                        os.write(input, 0, input.length);
                    }
                    
                    int responseCode = conn.getResponseCode();
                    
                    if (responseCode == 200) {
                        orderCache.remove(orderId);
                        player.sendMessage(ChatColor.YELLOW + "❌ Kauf abgebrochen.");
                        if (debug) getLogger().info("✅ Order #" + orderId + " successfully cancelled");
                    } else {
                        if (debug) getLogger().warning("⚠️ Cancel Order API returned code: " + responseCode);
                        player.sendMessage(ChatColor.RED + "❌ Fehler beim Abbrechen des Kaufs.");
                        // Fallback: Cache leeren damit es nicht als Loop erscheint
                        orderCache.remove(orderId);
                        activeOrderIds.remove(player.getUniqueId());
                    }
                } catch (Exception e) {
                    getLogger().log(Level.WARNING, "Fehler bei /cancel_order", e);
                    // Fallback: Cache leeren
                    orderCache.remove(orderId);
                    activeOrderIds.remove(player.getUniqueId());
                    player.sendMessage(ChatColor.YELLOW + "❌ Kauf abgebrochen (lokale Bestätigung).");
                }
            }
        }.runTaskAsynchronously(this);
    }

    private void executeShopLogic(Player player, OrderData data, int orderId) {
        try {
            if (econ.getBalance(player) < data.price) {
                player.sendMessage(ChatColor.RED + "❌ Du hast nicht genug Geld! (Benötigt: " + data.price + " " + currency + ")");
                // Wenn der Kauf fehlschagt (Geld), sollte die Bestellung abgebrochen werden
                cancelOrder(player, orderId);
                return;
            }
            
            econ.withdrawPlayer(player, data.price);
            player.sendMessage(ChatColor.GREEN + "💰 " + data.price + " " + currency + " abgezogen.");
            
            try {
                JsonElement root = gson.fromJson(data.jsonPayload, JsonElement.class);
                JsonArray items;
                
                if (root.isJsonObject()) {
                    items = root.getAsJsonObject().getAsJsonArray("items");
                } else {
                    items = root.getAsJsonArray();
                }
                
                int totalItemsGiven = 0;
                
                for (JsonElement e : items) {
                    JsonObject itemObj = e.getAsJsonObject();
                    String itemId = itemObj.get("id").getAsString();
                    int amount = itemObj.get("amount").getAsInt();
                    
                    ItemStack item = parseItem(itemId);
                    if (item != null) {
                        int remaining = amount;
                        while (remaining > 0) {
                            int stackSize = Math.min(remaining, item.getMaxStackSize());
                            ItemStack stack = item.clone();
                            stack.setAmount(stackSize);
                            
                            if (player.getInventory().firstEmpty() == -1) {
                                player.getWorld().dropItemNaturally(player.getLocation(), stack);
                            } else {
                                player.getInventory().addItem(stack);
                            }
                            remaining -= stackSize;
                        }
                        totalItemsGiven++;
                    } else {
                        player.sendMessage(ChatColor.RED + "❌ Item '" + itemId + "' konnte nicht gefunden werden.");
                    }
                }
                
                if (totalItemsGiven > 0) {
                    player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1.0F, 1.0F);
                    player.sendMessage(ChatColor.GREEN + "✅ Kauf erfolgreich abgeschlossen!");
                }
                
                markOrderCompleted(orderId);
                orderCache.remove(orderId);
                
            } catch (Exception e) {
                getLogger().log(Level.SEVERE, "Fehler beim Verarbeiten der JSON-Items", e);
                player.sendMessage(ChatColor.RED + "❌ Fehler beim Verteilen der Items. Bitte Admin kontaktieren.");
                markOrderCompleted(orderId);
            }
            
        } catch (Exception e) {
            getLogger().log(Level.SEVERE, "Fehler bei Shop-Logik", e);
            player.sendMessage(ChatColor.RED + "❌ Interner Fehler.");
        }
    }

    private void markOrderCompleted(int orderId) {
        new BukkitRunnable() {
            @Override
            public void run() {
                try {
                    String jsonInputString = "{\"id\":\"" + orderId + "\"}";
                    
                    if (debug) getLogger().info("🔄 Marking order #" + orderId + " as completed...");
                    
                    URL url = new URL(wpUrlComplete);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setRequestMethod("POST");
                    conn.setRequestProperty("Content-Type", "application/json");
                    conn.setDoOutput(true);
                    
                    try(OutputStream os = conn.getOutputStream()) {
                        byte[] input = jsonInputString.getBytes("utf-8");
                        os.write(input, 0, input.length);
                    }
                    
                    int responseCode = conn.getResponseCode();
                    
                    if (debug) {
                        if (responseCode == 200) {
                            getLogger().info("✅ Order #" + orderId + " successfully marked as completed");
                        } else {
                            getLogger().warning("⚠️ Complete Order API returned code: " + responseCode);
                        }
                    }
                } catch (Exception e) {
                    getLogger().log(Level.WARNING, "Complete Order Error for #" + orderId, e);
                }
            }
        }.runTaskAsynchronously(this);
    }

    private ItemStack parseItem(String itemId) {
        try {
            String cleanId = itemId.toUpperCase().trim().replace("MINECRAFT:", "").replace("MC:", "");
            String materialName = numericIdToMaterial(cleanId);
            if (materialName == null) materialName = cleanId;
            
            if (materialName.equalsIgnoreCase("VIP") || materialName.startsWith("VIP")) {
                return null;
            }
            
            Material material = Material.matchMaterial(materialName);
            if (material != null && material.isItem()) {
                return new ItemStack(material,1);
            }
            return null;
        } catch (Exception e) {
            getLogger().log(Level.WARNING, "parseItem Fehler: " + itemId, e);
            return null;
        }
    }
    
    private String numericIdToMaterial(String id) {
        if (!id.matches("\\d+")) return null;
        switch (id) {
            case "352": return "BONE_MEAL";
            case "264": return "EMERALD";
            case "388": return "EMERALD_BLOCK";
            case "357": return "GOLDEN_APPLE";
            case "322": return "GOLDEN_CARROT";
            case "348": return "GOLD_INGOT";
            case "133": return "EMERALD_ORE";
            case "41": return "GOLD_ORE";
            case "14": return "GOLD_BLOCK";
            case "289": return "COOKIE";
            case "1": return "STONE";
            case "5": return "PLANKS"; 
            case "17": return "OAK_LOG";
            case "260": return "BONE_BLOCK";
            case "287": return "TOTEM_OF_UNDYING";
            default: return null;
        }
    }

    private static class OrderData {
        int id;
        String itemId;
        String itemTitle;
        double price;
        int quantity;
        String jsonPayload;
        
        OrderData(int id, String itemId, String itemTitle, double price, int quantity, String jsonPayload) {
            this.id = id;
            this.itemId = itemId;
            this.itemTitle = itemTitle;
            this.price = price;
            this.quantity = quantity;
            this.jsonPayload = jsonPayload;
        }
    }

    @Override
    public void onDisable() {
        if (task != null) {
            task.cancel();
        }
        getLogger().info("IngameShopSpigot gestoppt");
    }
}