package com.yourname.premiumah.config;

import com.yourname.premiumah.model.SortMode;
import com.yourname.premiumah.util.MaterialUtil;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;

public final class ConfigManager {
    private final JavaPlugin plugin;
    private FileConfiguration config;
    private Set<Material> restrictedMaterials = Set.of();
    private List<LimitPermission> limitPermissions = List.of();
    private List<Integer> listingSlots = List.of();

    public ConfigManager(JavaPlugin plugin) {
        this.plugin = plugin;
    }

    public void reload() {
        plugin.saveDefaultConfig();
        plugin.reloadConfig();
        this.config = plugin.getConfig();
        this.restrictedMaterials = loadRestrictedMaterials();
        this.limitPermissions = loadLimitPermissions();
        this.listingSlots = loadListingSlots();
    }

    public FileConfiguration raw() {
        return config;
    }

    public boolean debug() {
        return config.getBoolean("settings.debug", false);
    }

    public String prefix() {
        return config.getString("settings.command-prefix", "<#c79542>Dirt Auctions <#6b7280>»");
    }

    public boolean economyEnabled() {
        return config.getBoolean("economy.enabled", true);
    }

    public boolean requireEconomy() {
        return config.getBoolean("economy.require-economy", true);
    }

    public boolean allowSellerSelfPurchase() {
        return config.getBoolean("settings.allow-seller-self-purchase", false);
    }

    public boolean requireInventorySpaceToBuy() {
        return config.getBoolean("settings.require-inventory-space-to-buy", false);
    }

    public boolean claimFullInventoryPurchases() {
        return config.getString("claims.buyer-full-inventory-action", "CLAIM").equalsIgnoreCase("CLAIM");
    }

    public boolean instantSellerPayment() {
        String action = config.getString("claims.seller-payment-action", "INSTANT");
        return config.getBoolean("economy.instant-seller-payment", true) && !"CLAIM".equalsIgnoreCase(action);
    }

    public int chatPriceTimeoutSeconds() {
        return Math.max(5, config.getInt("settings.chat-price-timeout-seconds", 45));
    }

    public long clickDebounceMillis() {
        return Math.max(0L, config.getLong("settings.click-debounce-millis", 350L));
    }

    public long listingExpireCheckTicks() {
        long seconds = Math.max(10L, config.getLong("settings.listing-expire-check-seconds", 60L));
        return seconds * 20L;
    }

    public SortMode defaultSort() {
        return SortMode.fromString(config.getString("settings.default-sort", "NEWEST"), SortMode.NEWEST);
    }

    public long defaultListingDurationMillis() {
        long seconds = Math.max(60L, config.getLong("listings.default-duration-seconds", 604800L));
        return seconds * 1000L;
    }

    public boolean allowCancelActiveListings() {
        return config.getBoolean("listings.allow-cancel-active-listings", true);
    }

    public boolean reclaimAdminRemovedItems() {
        return config.getBoolean("listings.reclaim-admin-removed-items", true);
    }

    public double minPrice() {
        return Math.max(0.0D, config.getDouble("economy.price.min", 1.0D));
    }

    public double maxPrice() {
        return Math.max(minPrice(), config.getDouble("economy.price.max", 1_000_000_000.0D));
    }

    public boolean listingFeeEnabled() {
        return config.getBoolean("economy.listing-fee.enabled", false);
    }

    public double listingFee() {
        return Math.max(0.0D, config.getDouble("economy.listing-fee.amount", 0.0D));
    }

    public boolean salesTaxEnabled() {
        return config.getBoolean("economy.sales-tax.enabled", false);
    }

    public double salesTaxPercent() {
        return Math.max(0.0D, Math.min(100.0D, config.getDouble("economy.sales-tax.percent", 0.0D)));
    }

    public boolean soundsEnabled() {
        return config.getBoolean("sounds.enabled", true);
    }

    public String soundName(String key) {
        return config.getString("sounds." + key, "");
    }

    public int guiSize(String key) {
        int requested = config.getInt("gui.size." + key, 54);
        int clamped = Math.max(9, Math.min(54, requested));
        return clamped - (clamped % 9);
    }

    public String guiTitle(String key) {
        return config.getString("gui.titles." + key, key);
    }

    public boolean fillerEnabled() {
        return config.getBoolean("gui.filler.enabled", true);
    }

    public Material fillerMaterial() {
        return MaterialUtil.parse(config.getString("gui.filler.material", "BLACK_STAINED_GLASS_PANE"))
                .orElse(Material.BLACK_STAINED_GLASS_PANE);
    }

    public String fillerName() {
        return config.getString("gui.filler.name", " ");
    }

    public List<Integer> listingSlots() {
        return listingSlots;
    }

    public ButtonConfig button(String key) {
        String path = "gui.buttons." + key;
        Material material = MaterialUtil.parse(config.getString(path + ".material", "STONE")).orElse(Material.STONE);
        String name = config.getString(path + ".name", key);
        List<String> lore = config.getStringList(path + ".lore");
        return new ButtonConfig(material, name, lore);
    }

    public List<String> guiLore(String key) {
        return config.getStringList("gui-lore." + key);
    }

    public int listingLimit(Player player) {
        int limit = Math.max(0, config.getInt("listing-limits.default", 5));
        for (LimitPermission permission : limitPermissions) {
            if (player.hasPermission(permission.permission())) {
                limit = Math.max(limit, permission.amount());
            }
        }
        return limit;
    }

    public boolean isItemAllowed(Player player, Material material) {
        if (player.hasPermission("premiumah.bypass.restrictions")) {
            return true;
        }
        String mode = config.getString("item-restrictions.mode", "BLACKLIST").toUpperCase(Locale.ROOT);
        if ("WHITELIST".equals(mode)) {
            return restrictedMaterials.contains(material);
        }
        return !restrictedMaterials.contains(material);
    }

    private Set<Material> loadRestrictedMaterials() {
        Set<Material> materials = new HashSet<>();
        for (String entry : config.getStringList("item-restrictions.materials")) {
            MaterialUtil.parse(entry).ifPresent(materials::add);
        }
        return Collections.unmodifiableSet(materials);
    }

    private List<LimitPermission> loadLimitPermissions() {
        List<LimitPermission> permissions = new ArrayList<>();
        for (var map : config.getMapList("listing-limits.permissions")) {
            Object permission = map.get("permission");
            Object amount = map.get("amount");
            if (permission instanceof String permissionString && amount instanceof Number number) {
                permissions.add(new LimitPermission(permissionString, Math.max(0, number.intValue())));
            }
        }
        return List.copyOf(permissions);
    }

    private List<Integer> loadListingSlots() {
        List<Integer> slots = new ArrayList<>();
        for (int slot : config.getIntegerList("gui.listing-slots")) {
            if (slot >= 0 && slot < 54) {
                slots.add(slot);
            }
        }
        if (slots.isEmpty()) {
            for (int slot = 10; slot <= 34; slot++) {
                int column = slot % 9;
                if (column > 0 && column < 8) {
                    slots.add(slot);
                }
            }
        }
        return List.copyOf(slots);
    }

    public ConfigurationSection section(String path) {
        return config.getConfigurationSection(path);
    }
}
