package com.bitnix.dirtcryptostore.command;

import com.bitnix.dirtcryptostore.DirtCryptoStorePlugin;
import com.bitnix.dirtcryptostore.gui.StoreGui;
import com.bitnix.dirtcryptostore.model.BlockchainPaymentMatch;
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.MessageUtil;
import com.bitnix.dirtcryptostore.util.TimeUtil;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;

public class CryptoStoreCommand implements CommandExecutor, TabCompleter {

    private final DirtCryptoStorePlugin plugin;

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

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        if (args.length > 0) {
            String sub = args[0].toLowerCase(Locale.ROOT);

            if (sub.equals("reload")) {
                if (!sender.hasPermission("dirtcryptostore.admin")) {
                    MessageUtil.send(plugin, sender, "messages.no-permission", "&cYou do not have permission.");
                    return true;
                }

                plugin.reloadPlugin();
                MessageUtil.send(plugin, sender, "messages.reloaded", "&aDirtCryptoStore reloaded.");
                return true;
            }

            if (sub.equals("status")) {
                if (!(sender instanceof Player player)) {
                    MessageUtil.send(plugin, sender, "messages.player-only", "&cOnly players can use this command.");
                    return true;
                }

                PendingInvoice invoice = plugin.getInvoiceManager().getPendingInvoice(player.getUniqueId());
                if (invoice == null) {
                    MessageUtil.send(plugin, player, "messages.no-pending-payment", "&cYou do not have a pending payment.");
                    return true;
                }

                sendInvoiceStatus(sender, invoice);
                return true;
            }

            if (sub.equals("review")) {
                if (!sender.hasPermission("dirtcryptostore.admin")) {
                    MessageUtil.send(plugin, sender, "messages.no-permission", "&cYou do not have permission.");
                    return true;
                }

                int shown = 0;
                Collection<PendingInvoice> all = plugin.getInvoiceManager().getAllInvoices();
                sender.sendMessage(ColorUtil.color("&6--- DirtCryptoStore Review Queue ---"));
                for (PendingInvoice invoice : all) {
                    if (invoice.getStatus() != PendingInvoice.Status.UNDER_REVIEW) {
                        continue;
                    }

                    shown++;
                    sender.sendMessage(ColorUtil.color("&eInvoice: &f" + invoice.getInvoiceId()));
                    sender.sendMessage(ColorUtil.color("&7Player: &f" + invoice.getPlayerName()));
                    sender.sendMessage(ColorUtil.color("&7Product: &f" + invoice.getProductId()));
                    sender.sendMessage(ColorUtil.color("&7Amount: &f" + TimeUtil.formatBtcAmount(invoice.getAmountSats())));
                    sender.sendMessage(ColorUtil.color("&7TXID: &f" + (invoice.getTxid().isEmpty() ? "N/A" : invoice.getTxid())));
                    sender.sendMessage(ColorUtil.color("&7Notes: &f" + invoice.getNotes()));
                    sender.sendMessage(ColorUtil.color("&7Use: &f/cryptostore forceconfirm " + invoice.getInvoiceId()));
                    sender.sendMessage(ColorUtil.color("&7Use: &f/cryptostore cancelinvoice " + invoice.getInvoiceId()));
                }

                if (shown == 0) {
                    sender.sendMessage(ColorUtil.color("&aNo invoices are currently under review."));
                }
                return true;
            }

            if (sub.equals("forceconfirm")) {
                if (!sender.hasPermission("dirtcryptostore.admin")) {
                    MessageUtil.send(plugin, sender, "messages.no-permission", "&cYou do not have permission.");
                    return true;
                }

                if (args.length < 2) {
                    sender.sendMessage(ColorUtil.color("&cUsage: /cryptostore forceconfirm <invoiceId>"));
                    return true;
                }

                PendingInvoice invoice = plugin.getInvoiceManager().getInvoiceById(args[1]);
                if (invoice == null) {
                    sender.sendMessage(ColorUtil.color("&cInvoice not found."));
                    return true;
                }

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

                if (product == null) {
                    sender.sendMessage(ColorUtil.color("&cProduct config missing for that invoice."));
                    return true;
                }

                BlockchainPaymentMatch match = new BlockchainPaymentMatch(
                        true,
                        invoice.getTxid().isEmpty() ? "MANUAL_REVIEW" : invoice.getTxid(),
                        Math.max(invoice.getConfirmations(), wallet == null ? 2 : wallet.getMinConfirmations()),
                        0
                );

                plugin.getPaymentWatcher().forceFulfillFromAdmin(invoice, match);

                sender.sendMessage(ColorUtil.color("&aInvoice force-confirmed: &f" + invoice.getInvoiceId()));
                return true;
            }

            if (sub.equals("cancelinvoice")) {
                if (!sender.hasPermission("dirtcryptostore.admin")) {
                    MessageUtil.send(plugin, sender, "messages.no-permission", "&cYou do not have permission.");
                    return true;
                }

                if (args.length < 2) {
                    sender.sendMessage(ColorUtil.color("&cUsage: /cryptostore cancelinvoice <invoiceId>"));
                    return true;
                }

                PendingInvoice invoice = plugin.getInvoiceManager().getInvoiceById(args[1]);
                if (invoice == null) {
                    sender.sendMessage(ColorUtil.color("&cInvoice not found."));
                    return true;
                }

                plugin.getInvoiceManager().expireInvoice(invoice, "Cancelled by admin.");
                sender.sendMessage(ColorUtil.color("&aInvoice cancelled: &f" + invoice.getInvoiceId()));

                Player player = Bukkit.getPlayer(invoice.getPlayerUuid());
                if (player != null) {
                    MessageUtil.send(plugin, player, "messages.invoice-cancelled", "&eYour pending payment was cancelled.");
                }
                return true;
            }
        }

        if (!(sender instanceof Player player)) {
            MessageUtil.send(plugin, sender, "messages.player-only", "&cOnly players can use this command.");
            return true;
        }

        if (!player.hasPermission("dirtcryptostore.use")) {
            MessageUtil.send(plugin, player, "messages.no-permission", "&cYou do not have permission.");
            return true;
        }

        MessageUtil.send(plugin, player, "messages.opening-store", "&aOpening crypto store...");
        new StoreGui(plugin).open(player);
        return true;
    }

    private void sendInvoiceStatus(CommandSender sender, PendingInvoice invoice) {
        String product = invoice.getProductId();
        String amount = TimeUtil.formatBtcAmount(invoice.getAmountSats());
        String status = invoice.getStatus().name();
        String txid = invoice.getTxid().isEmpty() ? "N/A" : invoice.getTxid();
        String time = TimeUtil.formatRemaining(invoice.getRemainingMillis());

        MessageUtil.send(plugin, sender, "messages.product-line", "&7Product: &f%product%", "%product%", product);
        MessageUtil.send(plugin, sender, "messages.amount-line", "&7Amount: &f%amount%", "%amount%", amount);
        MessageUtil.send(plugin, sender, "messages.txid-line", "&7TXID: &f%txid%", "%txid%", txid);
        sender.sendMessage(ColorUtil.color("&7Status: &f" + status));
        sender.sendMessage(ColorUtil.color("&7Expires in: &f" + time));
        sender.sendMessage(ColorUtil.color("&7Notes: &f" + invoice.getNotes()));
    }

    @Override
    public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
        if (args.length == 1) {
            List<String> suggestions = new ArrayList<>();
            suggestions.add("status");

            if (sender.hasPermission("dirtcryptostore.admin")) {
                suggestions.add("reload");
                suggestions.add("review");
                suggestions.add("forceconfirm");
                suggestions.add("cancelinvoice");
            }

            String input = args[0].toLowerCase(Locale.ROOT);
            suggestions.removeIf(s -> !s.toLowerCase(Locale.ROOT).startsWith(input));
            Collections.sort(suggestions);
            return suggestions;
        }

        if (args.length == 2 && sender.hasPermission("dirtcryptostore.admin")) {
            String sub = args[0].toLowerCase(Locale.ROOT);
            if (sub.equals("forceconfirm") || sub.equals("cancelinvoice")) {
                List<String> suggestions = new ArrayList<>();
                for (PendingInvoice invoice : plugin.getInvoiceManager().getAllInvoices()) {
                    suggestions.add(invoice.getInvoiceId());
                }
                String input = args[1].toLowerCase(Locale.ROOT);
                suggestions.removeIf(s -> !s.toLowerCase(Locale.ROOT).startsWith(input));
                Collections.sort(suggestions);
                return suggestions;
            }
        }

        return Collections.emptyList();
    }
}
