package com.bitnix.dirtcryptostore.gui;

import com.bitnix.dirtcryptostore.DirtCryptoStorePlugin;
import com.bitnix.dirtcryptostore.model.PendingInvoice;
import com.bitnix.dirtcryptostore.model.Product;
import com.bitnix.dirtcryptostore.model.WalletConfig;
import com.bitnix.dirtcryptostore.util.ColorUtil;
import com.bitnix.dirtcryptostore.util.QrMapUtil;
import com.bitnix.dirtcryptostore.util.QrPlaceholderUtil;
import com.bitnix.dirtcryptostore.util.TimeUtil;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;

import java.util.ArrayList;
import java.util.List;

public class PaymentGui {

    private final DirtCryptoStorePlugin plugin;

    public PaymentGui(DirtCryptoStorePlugin plugin) {
        this.plugin = plugin;
    }

    public void open(Player player, PendingInvoice invoice) {
        String title = ColorUtil.color(plugin.getConfig().getString("gui.payment.title", "&8Crypto Payment"));
        int size = plugin.getConfig().getInt("gui.payment.size", 27);

        Inventory inventory = Bukkit.createInventory(null, size, title);

        applyStaticItems(inventory);
        applyDynamicItems(player, inventory, invoice);

        player.openInventory(inventory);
    }

    private void applyStaticItems(Inventory inventory) {
        ConfigurationSection itemsSection = plugin.getConfig().getConfigurationSection("gui.payment.items");
        if (itemsSection == null) {
            return;
        }

        for (String key : itemsSection.getKeys(false)) {
            ConfigurationSection section = itemsSection.getConfigurationSection(key);
            if (section == null || !section.getBoolean("enabled", true)) {
                continue;
            }

            if (key.equalsIgnoreCase("filler")) {
                ItemStack filler = createItem(
                        section.getString("material", "BLACK_STAINED_GLASS_PANE"),
                        section.getString("name", " "),
                        section.getStringList("lore"),
                        0,
                        false
                );

                for (int slot : section.getIntegerList("slots")) {
                    if (slot >= 0 && slot < inventory.getSize()) {
                        inventory.setItem(slot, filler);
                    }
                }
            }
        }
    }

    private void applyDynamicItems(Player player, Inventory inventory, PendingInvoice invoice) {
        ConfigurationSection itemsSection = plugin.getConfig().getConfigurationSection("gui.payment.items");
        if (itemsSection == null) {
            return;
        }

        Product product = plugin.getConfigManager().getProduct(invoice.getProductId());
        WalletConfig wallet = plugin.getConfigManager().getWallet(invoice.getWalletId());

        String productName = product == null ? invoice.getProductId() : product.getDisplayName();
        String walletName = wallet == null ? invoice.getWalletId() : wallet.getDisplayName();
        String amount = TimeUtil.formatBtcAmount(invoice.getAmountSats());
        String rawAmount = TimeUtil.formatBtcRaw(invoice.getAmountSats());
        String status = invoice.getStatus().name();
        String txid = invoice.getTxid() == null || invoice.getTxid().isEmpty() ? "N/A" : invoice.getTxid();
        String time = TimeUtil.formatRemaining(invoice.getRemainingMillis());
        String address = invoice.getWalletAddress();
        int requiredConfirmations = wallet == null
                ? plugin.getConfig().getInt("settings.payment.confirmations-required", 2)
                : wallet.getMinConfirmations();
        String bitcoinUri = QrPlaceholderUtil.buildBitcoinUri(invoice);

        placeDynamicItem(inventory, itemsSection, "product",
                replaceLore(itemsSection, "product", productName, walletName, amount, rawAmount, status, txid, time, address, invoice.getConfirmations(), requiredConfirmations, bitcoinUri));

        placeQrItem(player, inventory, itemsSection, invoice, productName, walletName, amount, rawAmount, status, txid, time, address, requiredConfirmations, bitcoinUri);

        placeDynamicItem(inventory, itemsSection, "status",
                replaceLore(itemsSection, "status", productName, walletName, amount, rawAmount, status, txid, time, address, invoice.getConfirmations(), requiredConfirmations, bitcoinUri));

        placeConfiguredButton(inventory, itemsSection, "back");
        placeConfiguredButton(inventory, itemsSection, "cancel");
        placeConfiguredButton(inventory, itemsSection, "refresh");
    }

    private void placeQrItem(Player player,
                             Inventory inventory,
                             ConfigurationSection itemsSection,
                             PendingInvoice invoice,
                             String productName,
                             String walletName,
                             String amount,
                             String rawAmount,
                             String status,
                             String txid,
                             String time,
                             String address,
                             int requiredConfirmations,
                             String bitcoinUri) {
        ConfigurationSection section = itemsSection.getConfigurationSection("qr");
        if (section == null || !section.getBoolean("enabled", true)) {
            return;
        }

        int slot = section.getInt("slot", -1);
        if (slot < 0 || slot >= inventory.getSize()) {
            return;
        }

        List<String> lore = replaceLore(itemsSection, "qr", productName, walletName, amount, rawAmount, status, txid, time, address, invoice.getConfirmations(), requiredConfirmations, bitcoinUri);

        ItemStack qrItem = QrMapUtil.createQrMapItem(
                plugin,
                player,
                bitcoinUri,
                ColorUtil.color(section.getString("name", "&aScan QR To Pay")),
                ColorUtil.color(lore),
                plugin.getConfig().getString("settings.qr.fallback-material-if-map-fails", "PAPER")
        );

        inventory.setItem(slot, qrItem);
    }

    private void placeDynamicItem(Inventory inventory, ConfigurationSection itemsSection, String key, List<String> lore) {
        ConfigurationSection section = itemsSection.getConfigurationSection(key);
        if (section == null || !section.getBoolean("enabled", true)) {
            return;
        }

        int slot = section.getInt("slot", -1);
        if (slot < 0 || slot >= inventory.getSize()) {
            return;
        }

        inventory.setItem(slot, createItem(
                section.getString("material", "PAPER"),
                section.getString("name", "&fItem"),
                lore,
                section.getInt("custom-model-data", 0),
                section.getBoolean("glow", false)
        ));
    }

    private void placeConfiguredButton(Inventory inventory, ConfigurationSection itemsSection, String key) {
        ConfigurationSection section = itemsSection.getConfigurationSection(key);
        if (section == null || !section.getBoolean("enabled", true)) {
            return;
        }

        int slot = section.getInt("slot", -1);
        if (slot < 0 || slot >= inventory.getSize()) {
            return;
        }

        inventory.setItem(slot, createItem(
                section.getString("material", "STONE"),
                section.getString("name", "&fButton"),
                section.getStringList("lore"),
                section.getInt("custom-model-data", 0),
                section.getBoolean("glow", false)
        ));
    }

    private List<String> replaceLore(ConfigurationSection itemsSection,
                                     String key,
                                     String product,
                                     String wallet,
                                     String amount,
                                     String rawAmount,
                                     String status,
                                     String txid,
                                     String time,
                                     String address,
                                     int currentConfirmations,
                                     int requiredConfirmations,
                                     String bitcoinUri) {
        ConfigurationSection section = itemsSection.getConfigurationSection(key);
        if (section == null) {
            return new ArrayList<>();
        }

        List<String> lore = new ArrayList<>();
        for (String line : section.getStringList("lore")) {
            lore.add(line
                    .replace("%product%", ColorUtil.color(product))
                    .replace("%wallet%", ColorUtil.color(wallet))
                    .replace("%amount%", amount)
                    .replace("%amount_raw%", rawAmount)
                    .replace("%amount_sats%", String.valueOf(parseSatsFromRaw(rawAmount)))
                    .replace("%status%", status)
                    .replace("%txid%", txid)
                    .replace("%time%", time)
                    .replace("%address%", address)
                    .replace("%bitcoin_uri%", bitcoinUri)
                    .replace("%current_confirmations%", String.valueOf(currentConfirmations))
                    .replace("%confirmations%", String.valueOf(requiredConfirmations)));
        }
        return lore;
    }

    private long parseSatsFromRaw(String rawAmount) {
        String[] split = rawAmount.split("\\.");
        if (split.length != 2) {
            return 0L;
        }

        try {
            long whole = Long.parseLong(split[0]);
            String fraction = split[1];
            while (fraction.length() < 8) {
                fraction += "0";
            }
            if (fraction.length() > 8) {
                fraction = fraction.substring(0, 8);
            }
            long frac = Long.parseLong(fraction);
            return (whole * 100_000_000L) + frac;
        } catch (NumberFormatException ex) {
            return 0L;
        }
    }

    private ItemStack createItem(String materialName, String name, List<String> lore, int customModelData, boolean glow) {
        Material material = Material.matchMaterial(materialName);
        if (material == null) {
            material = Material.STONE;
        }

        ItemStack item = new ItemStack(material);
        ItemMeta meta = item.getItemMeta();
        if (meta == null) {
            return item;
        }

        meta.setDisplayName(ColorUtil.color(name));
        meta.setLore(ColorUtil.color(lore));

        if (customModelData > 0) {
            meta.setCustomModelData(customModelData);
        }

        if (glow) {
            meta.addEnchant(Enchantment.LUCK_OF_THE_SEA, 1, true);
            meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
        }

        item.setItemMeta(meta);
        return item;
    }
}
