package de.iani.treasurechest.commands;

import de.iani.cubesideutils.bukkit.commands.SubCommand;
import de.iani.cubesideutils.bukkit.commands.exceptions.DisallowsCommandBlockException;
import de.iani.cubesideutils.bukkit.commands.exceptions.IllegalSyntaxException;
import de.iani.cubesideutils.bukkit.commands.exceptions.InternalCommandException;
import de.iani.cubesideutils.bukkit.commands.exceptions.NoPermissionException;
import de.iani.cubesideutils.bukkit.commands.exceptions.RequiresPlayerException;
import de.iani.cubesideutils.bukkit.items.ItemStacks;
import de.iani.cubesideutils.bukkit.updater.DataUpdater;
import de.iani.cubesideutils.commands.ArgsParser;
import de.iani.treasurechest.Permissions;
import de.iani.treasurechest.TreasureChest;
import de.iani.treasurechest.database.DatabaseTreasureChestItem;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.logging.Level;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable;

public class UpdateAllCommand extends SubCommand {
    private TreasureChest plugin;

    public UpdateAllCommand(TreasureChest plugin) {
        this.plugin = plugin;
    }

    @Override
    public String getRequiredPermission() {
        return Permissions.UPDATEALL;
    }

    @Override
    public boolean requiresPlayer() {
        return false;
    }

    @Override
    public String getUsage() {
        return "CONFIRM|FORCEALL";
    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) throws DisallowsCommandBlockException, RequiresPlayerException, NoPermissionException, IllegalSyntaxException, InternalCommandException {
        if (args.remaining() != 1) {
            plugin.sendMessage(sender, commandString + getUsage(), true);
            return true;
        }
        String arg = args.getNext("");
        if (!arg.equals("CONFIRM") && !arg.equals("FORCEALL")) {
            plugin.sendMessage(sender, commandString + getUsage(), true);
            return true;
        }
        boolean forceAll = arg.equals("FORCEALL");
        ArrayList<DatabaseTreasureChestItem> allHeads;
        try {
            sender.sendMessage(Component.text("Lade Schatztruheninhalte!", NamedTextColor.DARK_RED));
            allHeads = plugin.getDatabase().getAllItems();
            sender.sendMessage(Component.text("Laden abgeschlossen (" + allHeads.size() + ") - Beginne Update!", NamedTextColor.DARK_RED));
        } catch (SQLException e) {
            sender.sendMessage("Exception while loading");
            plugin.getLogger().log(Level.SEVERE, "Exception while loading", e);
            return true;
        }
        new BukkitRunnable() {
            int total = allHeads.size();
            int checked = 0;
            int converted = 0;

            @Override
            public void run() {
                for (int k = 0; k < 100; k++) {
                    if (checked >= total) {
                        sender.sendMessage(Component.text("Update: " + checked + "/" + total + " (" + converted + " updated)", NamedTextColor.DARK_RED));
                        sender.sendMessage(Component.text("Update abgeschlossen!", NamedTextColor.DARK_RED));
                        this.cancel();
                        return;
                    }
                    DatabaseTreasureChestItem i = allHeads.get(checked);
                    checked++;

                    boolean changed = false;

                    ItemStack oldStack = i.getDisplayItem();
                    ItemStack newStack = ItemStacks.prepareForSerialization(DataUpdater.updateItemStack(ItemStacks.restoreAfterDeserialization(oldStack)));
                    if (!Objects.equals(newStack, oldStack)) {
                        i.setDisplayItem(newStack);
                        changed = true;
                    }

                    ItemStack[] priceItems = i.getPriceItems();
                    if (priceItems != null) {
                        for (int j = 0; j < priceItems.length; j++) {
                            oldStack = priceItems[j];
                            newStack = ItemStacks.prepareForSerialization(DataUpdater.updateItemStack(ItemStacks.restoreAfterDeserialization(oldStack)));
                            if (!Objects.equals(newStack, oldStack)) {
                                priceItems[j] = newStack;
                                changed = true;
                            }
                        }
                    }
                    if (forceAll || changed) {
                        try {
                            plugin.getDatabase().updateItem(i);
                        } catch (SQLException e) {
                            sender.sendMessage("Exception while updating: " + i.getId());
                            plugin.getLogger().log(Level.SEVERE, "Exception while updating: " + i.getId(), e);
                        }
                        converted++;
                    }
                    if (checked % 100 == 0) {
                        sender.sendMessage(Component.text("Update: " + checked + "/" + total + " (" + converted + " updated)", NamedTextColor.DARK_RED));
                    }
                }
            }
        }.runTaskTimer(plugin, 1, 1);
        return true;
    }

    @Override
    public Collection<String> onTabComplete(CommandSender sender, Command command, String alias, ArgsParser args) {
        return List.of();
    }
}
