package de.viper.survivalplus.trade;

import de.viper.survivalplus.SurvivalPlus;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;

public class TradeSession implements Listener {

    private final SurvivalPlus plugin;
    private final TradeManager tradeManager;
    private final Player sender;
    private final Player receiver;

    // Wir benutzen nur EIN Inventar für beide (Size 54 = Double Chest)
    // Slots 0-17: Angebot von Sender (Editierbar für Sender)
    // Slots 18-35: Angebot von Receiver (Editierbar für Receiver)
    // Slots 36-44: Trennung / Status
    // Slot 45: Abbrechen
    // Slot 53: Bestätigen
    private final Inventory tradeInv;

    private boolean senderConfirmed = false;
    private boolean receiverConfirmed = false;
    private boolean active = true;

    public TradeSession(SurvivalPlus plugin, Player sender, Player receiver, TradeManager tradeManager) {
        this.plugin = plugin;
        this.tradeManager = tradeManager;
        this.sender = sender;
        this.receiver = receiver;

        String title = plugin.getLangConfig().getString("trade.inventory-title", "Handel")
                .replace("%player%", receiver.getName())
                .replace("%other%", sender.getName());
        
        // Wir nutzen null als Owner, damit es ein gemeinsames Inventar ist
        this.tradeInv = Bukkit.createInventory(null, 54, title);
        setupLayout();
    }

    private void setupLayout() {
        // Trennung zwischen den beiden Angeboten (Glas)
        ItemStack glass = new ItemStack(Material.GRAY_STAINED_GLASS_PANE);
        ItemMeta glassMeta = glass.getItemMeta();
        glassMeta.setDisplayName(" ");
        glass.setItemMeta(glassMeta);
        
        for(int i = 36; i < 45; i++) {
            tradeInv.setItem(i, glass);
        }

        // Buttons initialisieren
        updateStatusItem();
        updateButtons();
    }

    private void updateButtons() {
        // Abbrechen Button (Rot)
        ItemStack cancel = new ItemStack(Material.RED_CONCRETE);
        ItemMeta cancelMeta = cancel.getItemMeta();
        cancelMeta.setDisplayName(plugin.getLangConfig().getString("trade.cancel-button", "§cAbbrechen"));
        cancel.setItemMeta(cancelMeta);
        tradeInv.setItem(45, cancel);

        // Bestätigen Button
        Material confirmMat = Material.LIME_CONCRETE;
        String confirmName = "§aBestätigen";

        // Wenn beide bestätigt haben, ändert sich der Button
        if (senderConfirmed && receiverConfirmed) {
            confirmMat = Material.GOLD_BLOCK; // Signalisiert Tauschvorgang
            confirmName = "§6Handel läuft...";
        } else if (senderConfirmed) {
            confirmMat = Material.YELLOW_CONCRETE;
            confirmName = "§eWarte auf Partner...";
        } else if (receiverConfirmed) {
            confirmMat = Material.YELLOW_CONCRETE;
            confirmName = "§eWarte auf Partner...";
        }

        ItemStack confirm = new ItemStack(confirmMat);
        ItemMeta confirmMeta = confirm.getItemMeta();
        confirmMeta.setDisplayName(confirmName);
        confirm.setItemMeta(confirmMeta);
        tradeInv.setItem(53, confirm);
    }

    private void updateStatusItem() {
        // Slot 40 zeigt den Status an
        String statusText = "§eWarte auf Bestätigung...";
        
        if (senderConfirmed && !receiverConfirmed) {
            statusText = "§a" + sender.getName() + " §7hat bestätigt.";
        } else if (!senderConfirmed && receiverConfirmed) {
            statusText = "§a" + receiver.getName() + " §7hat bestätigt.";
        } else if (senderConfirmed && receiverConfirmed) {
            statusText = "§6Handel wird ausgeführt...";
        }

        ItemStack status = new ItemStack(Material.BOOK);
        ItemMeta statusMeta = status.getItemMeta();
        statusMeta.setDisplayName(statusText);
        status.setItemMeta(statusMeta);
        tradeInv.setItem(40, status);
    }

    public Player getSender() { return sender; }
    public Player getReceiver() { return receiver; }

    public void openInventory() {
        if (sender.isOnline()) sender.openInventory(tradeInv);
        if (receiver.isOnline()) receiver.openInventory(tradeInv);
    }

    public void closeInventory() {
        active = false;
        if (sender.isOnline() && sender.getOpenInventory().getTopInventory() == tradeInv) {
            sender.closeInventory();
        }
        if (receiver.isOnline() && receiver.getOpenInventory().getTopInventory() == tradeInv) {
            receiver.closeInventory();
        }
        HandlerList.unregisterAll(this);
    }

    private void returnItems() {
        // Gibt alle Items zurück, falls der Handel abgebrochen wurde
        for (int i = 0; i < 36; i++) {
            ItemStack item = tradeInv.getItem(i);
            if (item != null) {
                // Bestimmen, wem das Item gehört
                if (i < 18) {
                    if (sender.isOnline()) sender.getInventory().addItem(item);
                } else {
                    if (receiver.isOnline()) receiver.getInventory().addItem(item);
                }
                tradeInv.setItem(i, null); // Slot leeren
            }
        }
    }

    private void executeTrade() {
        // Tauschvorgang
        // 1. Sender Items zu Receiver
        for (int i = 0; i < 18; i++) {
            ItemStack item = tradeInv.getItem(i);
            if (item != null) {
                if (receiver.isOnline()) receiver.getInventory().addItem(item);
                tradeInv.setItem(i, null);
            }
        }

        // 2. Receiver Items zu Sender
        for (int i = 18; i < 36; i++) {
            ItemStack item = tradeInv.getItem(i);
            if (item != null) {
                if (sender.isOnline()) sender.getInventory().addItem(item);
                tradeInv.setItem(i, null);
            }
        }

        String success = plugin.getLangConfig().getString("trade.success", "§aHandel erfolgreich abgeschlossen!");
        if (sender.isOnline()) sender.sendMessage(success);
        if (receiver.isOnline()) receiver.sendMessage(success);

        closeInventory();
    }

    @EventHandler
    public void onInventoryClick(InventoryClickEvent e) {
        if (!active) return;
        if (!(e.getWhoClicked() instanceof Player p)) return;
        if (e.getClickedInventory() == null) return;

        // Nur Klicks im Trade-Inventar behandeln
        if (e.getClickedInventory().getSize() != 54 || !e.getClickedInventory().equals(tradeInv)) return;
        // Auch Klicks im Bottom Inventory erlauben, aber nicht logisch behandeln (Bukkit regelt das)

        if (p.getUniqueId().equals(sender.getUniqueId())) {
            handleSenderClick(e);
        } else if (p.getUniqueId().equals(receiver.getUniqueId())) {
            handleReceiverClick(e);
        }
    }

    private void handleSenderClick(InventoryClickEvent e) {
        int slot = e.getSlot();

        // Abbrechen
        if (slot == 45) {
            e.setCancelled(true);
            sender.sendMessage(plugin.getLangConfig().getString("trade.cancelled", "§cHandel abgebrochen."));
            if (receiver.isOnline()) receiver.sendMessage(plugin.getLangConfig().getString("trade.cancelled-partner", "§cHandel wurde abgebrochen."));
            tradeManager.endTrade(this);
            return;
        }

        // Bestätigen
        if (slot == 53) {
            e.setCancelled(true);
            if (receiverConfirmed) {
                executeTrade();
            } else {
                senderConfirmed = !senderConfirmed; // Toggle
                sender.sendMessage(senderConfirmed ? 
                    plugin.getLangConfig().getString("trade.confirmed", "§aBestätigt!") : 
                    "§cBestätigung zurückgezogen.");
                updateButtons();
                updateStatusItem();
            }
            return;
        }

        // Item-Bewegungen nur im eigenen Bereich (0-17) erlauben
        if (slot >= 0 && slot <= 17) {
            // Erlaubt
            // Wenn ein Item bewegt wird, Bestätigungen zurücksetzen
            if (e.getCurrentItem() != null || e.getCursor() != null) {
                if (senderConfirmed || receiverConfirmed) {
                    senderConfirmed = false;
                    receiverConfirmed = false;
                    updateButtons();
                    updateStatusItem();
                }
            }
            return;
        }

        // Alle anderen Slots sperren (Partner-Seite, Glas, Status)
        e.setCancelled(true);
    }

    private void handleReceiverClick(InventoryClickEvent e) {
        int slot = e.getSlot();

        // Abbrechen
        if (slot == 45) {
            e.setCancelled(true);
            receiver.sendMessage(plugin.getLangConfig().getString("trade.cancelled", "§cHandel abgebrochen."));
            if (sender.isOnline()) sender.sendMessage(plugin.getLangConfig().getString("trade.cancelled-partner", "§cHandel wurde abgebrochen."));
            tradeManager.endTrade(this);
            return;
        }

        // Bestätigen
        if (slot == 53) {
            e.setCancelled(true);
            if (senderConfirmed) {
                executeTrade();
            } else {
                receiverConfirmed = !receiverConfirmed; // Toggle
                receiver.sendMessage(receiverConfirmed ? 
                    plugin.getLangConfig().getString("trade.confirmed", "§aBestätigt!") : 
                    "§cBestätigung zurückgezogen.");
                updateButtons();
                updateStatusItem();
            }
            return;
        }

        // Item-Bewegungen nur im eigenen Bereich (18-35) erlauben
        if (slot >= 18 && slot <= 35) {
            // Erlaubt
            if (e.getCurrentItem() != null || e.getCursor() != null) {
                if (senderConfirmed || receiverConfirmed) {
                    senderConfirmed = false;
                    receiverConfirmed = false;
                    updateButtons();
                    updateStatusItem();
                }
            }
            return;
        }

        // Alle anderen Slots sperren
        e.setCancelled(true);
    }

    @EventHandler
    public void onInventoryClose(InventoryCloseEvent e) {
        if (!active) return;
        if (!(e.getPlayer() instanceof Player p)) return;
        
        // Wenn ein Spieler das Inventar schließt, wird der Handel abgebrochen
        // Wir prüfen, ob noch Items drin sind, um Duplikate zu vermeiden
        if (e.getInventory().equals(tradeInv)) {
            if (p.getUniqueId().equals(sender.getUniqueId()) || p.getUniqueId().equals(receiver.getUniqueId())) {
                // Verzögern, falls der Server den CloseEvent für beide fast gleichzeitig feuert
                Bukkit.getScheduler().runTaskLater(plugin, () -> {
                    if (active) { // Nur wenn nicht schon durch executeTrade geschlossen
                        returnItems();
                        if (p.getUniqueId().equals(sender.getUniqueId())) {
                             if (receiver.isOnline()) receiver.sendMessage("§cDer Partner hat den Handel abgebrochen.");
                        } else {
                             if (sender.isOnline()) sender.sendMessage("§cDer Partner hat den Handel abgebrochen.");
                        }
                        tradeManager.endTrade(this);
                    }
                }, 1L);
            }
        }
    }
}