package fr.luc.gamingcore;

import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.protection.regions.RegionContainer;
import fr.luc.bettermccommands.BetterMcCommands;
import fr.luc.gamingcore.command.GuildCommands;
import fr.luc.gamingcore.database.DatabaseManager;
import fr.luc.gamingcore.database.GuildRepository;
import fr.luc.gamingcore.economy.ChunkPriceCalculator;
import fr.luc.gamingcore.economy.EconomyManager;
import fr.luc.gamingcore.listener.TerritoryProtectionListener;
import fr.luc.gamingcore.manager.GuildManager;
import fr.luc.gamingcore.util.MessageManager;
import fr.luc.gamingcore.util.TextUtil;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;

/**
 * Classe principale et point d'entrée du plugin GamingCore (Système de Guilde).
 */
public final class Main extends JavaPlugin {

    private static Main instance;

    private Economy economy;
    private RegionContainer regionContainer;

    private MessageManager messageManager;
    private DatabaseManager databaseManager;
    private GuildRepository guildRepository;
    private EconomyManager economyManager;
    private fr.luc.gamingcore.worldguard.WorldGuardManager worldGuardManager;
    private GuildManager guildManager;
    private BetterMcCommands betterMcCommands;

    /**
     * Méthode appelée lors de l'activation du plugin par le serveur Minecraft.
     */
    @Override
    public void onEnable() {
        instance = this;
        saveDefaultConfig();

        // 1. Initialiser le gestionnaire de messages (messages.yml)
        this.messageManager = new MessageManager(this);
        this.messageManager.reload();

        // 2. Initialiser les hooks externes
        setupWorldGuard();
        setupEconomy();

        // 3. Initialiser le gestionnaire WorldGuard
        this.worldGuardManager = new fr.luc.gamingcore.worldguard.WorldGuardManager(this);

        // 4. Initialiser la couche de données SQLite
        this.databaseManager = new DatabaseManager(this);
        this.databaseManager.initialize();
        this.guildRepository = new GuildRepository(this, databaseManager);

        // 5. Initialiser la couche économique
        this.economyManager = new EconomyManager(this);

        // 6. Initialiser le service métier GuildManager et charger les données
        this.guildManager = new GuildManager(this, guildRepository, economyManager, worldGuardManager);
        loadConfigSettings();
        this.guildManager.loadData();

        // 7. Initialiser le framework betterMcCommands et enregistrer les commandes
        this.betterMcCommands = BetterMcCommands.create(this);
        new GuildCommands(this, guildManager).register();

        // 8. Enregistrer les écouteurs d'événements
        PluginManager pm = getServer().getPluginManager();
        pm.registerEvents(new TerritoryProtectionListener(this), this);
        pm.registerEvents(new fr.luc.gamingcore.listener.GuildChatListener(this), this);

        getLogger().info("GamingCore (Système de Guilde - Cœur Métier & Commandes) a ete active avec succes !");
    }

    /**
     * Méthode appelée lors de la désactivation du plugin.
     */
    @Override
    public void onDisable() {
        if (betterMcCommands != null) {
            betterMcCommands.unregisterAll();
        }
        if (guildManager != null) {
            guildManager.shutdown();
        }
        if (databaseManager != null) {
            databaseManager.close();
        }

        getLogger().info("GamingCore a ete desactive !");
    }

    /**
     * Recharge à chaud tous les fichiers de configuration (config.yml et messages.yml)
     * et réapplique les paramètres économiques aux calculateurs.
     */
    public synchronized void reloadPlugin() {
        reloadConfig();
        if (messageManager != null) {
            messageManager.reload();
        }
        loadConfigSettings();
        getLogger().info("Configuration et messages recharges avec succes !");
    }

    /**
     * Charge et applique les paramètres de configuration dans les différents gestionnaires.
     */
    private void loadConfigSettings() {
        if (guildManager == null) return;

        double basePrice = getConfig().getDouble("economy.chunk_pricing.base_price", 1000.0);
        double growthRate = getConfig().getDouble("economy.chunk_pricing.growth_rate", 0.08);
        double alpha = getConfig().getDouble("economy.chunk_pricing.alpha", 0.95);
        double linearStep = getConfig().getDouble("economy.chunk_pricing.linear_step", 150.0);
        double kBase = getConfig().getDouble("economy.chunk_pricing.k_base", 0.05);
        double kSize = getConfig().getDouble("economy.chunk_pricing.k_size", 0.03);
        double delta = getConfig().getDouble("economy.chunk_pricing.delta", 1.15);
        long recentWindowMillis = getConfig().getLong("economy.chunk_pricing.recent_window_hours", 24) * 3600_000L;

        ChunkPriceCalculator calc = guildManager.getPriceCalculator();
        calc.setBasePrice(basePrice);
        calc.setGrowthRate(growthRate);
        calc.setAlpha(alpha);
        calc.setLinearStep(linearStep);
        calc.setKBase(kBase);
        calc.setKSize(kSize);
        calc.setDelta(delta);
        calc.setRecentWindowMillis(recentWindowMillis);
    }

    /**
     * Initialise la connexion vers l'API WorldGuard 7 si disponible.
     */
    private void setupWorldGuard() {
        try {
            this.regionContainer = WorldGuard.getInstance().getPlatform().getRegionContainer();
            getLogger().info("Connexion avec WorldGuard 7 etablie avec succes !");
        } catch (Throwable t) {
            getLogger().warning("WorldGuard non disponible ou erreur d'initialisation : " + t.getMessage());
        }
    }

    /**
     * Enregistre le fournisseur d'économie Vault.
     */
    private void setupEconomy() {
        if (getServer().getPluginManager().getPlugin("Vault") == null) {
            getLogger().warning("Vault n'a pas ete detecte ! Les fonctionnalites payantes seront desactivees.");
            return;
        }

        RegisteredServiceProvider<Economy> rsp = getServer().getServicesManager().getRegistration(Economy.class);
        if (rsp == null) {
            getLogger().warning("Aucun provider d'economie trouve via Vault (ex: EssentialsX, TheNewEconomy) !");
            return;
        }

        this.economy = rsp.getProvider();
        getLogger().info("Connexion avec l'economie Vault (" + economy.getName() + ") etablie avec succes !");
    }

    /**
     * Obtient l'instance Singleton de la classe principale.
     *
     * @return L'instance unique de Main.
     */
    public static Main getInstance() {
        return instance;
    }

    /**
     * Obtient le gestionnaire de messages.
     *
     * @return L'instance MessageManager.
     */
    public MessageManager getMessageManager() {
        return messageManager;
    }

    /**
     * Obtient le fournisseur d'économie Vault.
     *
     * @return L'instance Economy.
     */
    public Economy getEconomy() {
        return economy;
    }

    /**
     * Indique si un service d'économie est actif.
     *
     * @return true si economy != null.
     */
    public boolean hasEconomy() {
        return economy != null;
    }

    /**
     * Obtient le conteneur de régions WorldGuard.
     *
     * @return L'instance RegionContainer.
     */
    public RegionContainer getRegionContainer() {
        return regionContainer;
    }

    /**
     * Obtient le gestionnaire de base de données.
     *
     * @return L'instance DatabaseManager.
     */
    public DatabaseManager getDatabaseManager() {
        return databaseManager;
    }

    /**
     * Obtient le gestionnaire WorldGuard.
     *
     * @return L'instance WorldGuardManager.
     */
    public fr.luc.gamingcore.worldguard.WorldGuardManager getWorldGuardManager() {
        return worldGuardManager;
    }

    /**
     * Obtient le référentiel de persistance des guildes.
     *
     * @return L'instance GuildRepository.
     */
    public GuildRepository getGuildRepository() {
        return guildRepository;
    }

    /**
     * Obtient le gestionnaire d'économie interne.
     *
     * @return L'instance EconomyManager.
     */
    public EconomyManager getEconomyManager() {
        return economyManager;
    }

    /**
     * Obtient le service métier central de gestion des guildes.
     *
     * @return L'instance GuildManager.
     */
    public GuildManager getGuildManager() {
        return guildManager;
    }

    /**
     * Obtient l'instance du framework betterMcCommands.
     *
     * @return L'instance BetterMcCommands.
     */
    public BetterMcCommands getBetterMcCommands() {
        return betterMcCommands;
    }
}
