package dev.m1sk9.lunaticChat.paper

import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager
import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelMembershipManager
import dev.m1sk9.lunaticChat.paper.chat.handler.ChannelMessageHandler
import dev.m1sk9.lunaticChat.paper.chat.handler.ChannelNotificationHandler
import dev.m1sk9.lunaticChat.paper.chat.handler.DirectMessageHandler
import dev.m1sk9.lunaticChat.paper.command.core.CommandRegistry
import dev.m1sk9.lunaticChat.paper.command.impl.ReplyCommand
import dev.m1sk9.lunaticChat.paper.command.impl.TellCommand
import dev.m1sk9.lunaticChat.paper.command.impl.lc.LunaticChatCommand
import dev.m1sk9.lunaticChat.paper.command.impl.lcv.VelocityStatusCommand
import dev.m1sk9.lunaticChat.paper.command.setting.SettingHandlerRegistry
import dev.m1sk9.lunaticChat.paper.command.setting.handler.ChannelMessageNoticeSettingHandler
import dev.m1sk9.lunaticChat.paper.command.setting.handler.DirectMessageNoticeSettingHandler
import dev.m1sk9.lunaticChat.paper.command.setting.handler.JapaneseConversionSettingHandler
import dev.m1sk9.lunaticChat.paper.common.UpdateCheckResult
import dev.m1sk9.lunaticChat.paper.common.UpdateChecker
import dev.m1sk9.lunaticChat.paper.config.ConfigManager
import dev.m1sk9.lunaticChat.paper.config.LunaticChatConfiguration
import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager
import dev.m1sk9.lunaticChat.paper.listener.EventListenerRegistry
import dev.m1sk9.lunaticChat.paper.velocity.VelocityConnectionManager
import io.ktor.client.HttpClient
import io.ktor.client.engine.cio.CIO
import kotlinx.coroutines.launch
import org.bukkit.event.Listener
import org.bukkit.plugin.java.JavaPlugin
import java.util.concurrent.atomic.AtomicBoolean

class LunaticChat :
    JavaPlugin(),
    Listener {
    lateinit var directMessageHandler: DirectMessageHandler
    lateinit var languageManager: LanguageManager
    var channelManager: ChannelManager? = null
    var channelMembershipManager: ChannelMembershipManager? = null
    var channelMessageHandler: ChannelMessageHandler? = null
    var channelNotificationHandler: ChannelNotificationHandler? = null
    var velocityConnectionManager: VelocityConnectionManager? = null

    private lateinit var services: ServiceContainer
    private lateinit var configuration: LunaticChatConfiguration
    private lateinit var serviceInitializer: ServiceInitializer
    private lateinit var pluginScope: PluginCoroutineScope
    private var updateChecker: UpdateChecker? = null

    private val updateAvailable = AtomicBoolean(false)

    override fun onEnable() {
        saveDefaultConfig()
        val configManager = ConfigManager()
        configuration = configManager.loadConfiguration(config)

        if (configuration.debug) {
            logger.warning("LunaticChat is running in debug mode.")
            logger.info("Debug: $configuration")
        }

        val httpClient = HttpClient(CIO)

        // Initialize plugin coroutine scope
        pluginScope = PluginCoroutineScope(this, logger)

        // Initialize all services
        serviceInitializer =
            ServiceInitializer(
                plugin = this,
                configuration = configuration,
                httpClient = httpClient,
                logger = logger,
            )
        services = serviceInitializer.initialize()

        // Set public API properties (for command access)
        directMessageHandler = services.directMessageHandler
        languageManager = services.languageManager
        channelManager = services.channelManager
        channelMembershipManager = services.channelMembershipManager
        channelMessageHandler = services.channelMessageHandler
        channelNotificationHandler = services.channelNotificationHandler
        velocityConnectionManager = services.velocityConnectionManager

        // Schedule periodic tasks
        serviceInitializer.schedulePeriodicTasks()

        // Register commands and listeners
        registerCommands()
        registerEventListeners()

        // Check for updates
        if (configuration.checkForUpdates) {
            initializeUpdateChecker(httpClient)
        }

        logger.info("LunaticChat enabled.")
    }

    override fun onDisable() {
        pluginScope.cancel()
        serviceInitializer.shutdown(services)
        logger.info("LunaticChat disabled.")
    }

    /**
     * Registers all commands based on enabled features.
     */
    private fun registerCommands() {
        val commandRegistry = CommandRegistry(this)
        val settingHandlerRegistry = SettingHandlerRegistry()

        // Always register DM notification setting
        settingHandlerRegistry.register(
            DirectMessageNoticeSettingHandler(
                services.playerSettingsManager,
                services.languageManager,
            ),
        )

        // Always register channel message notification setting if channel is enabled
        if (services.channelManager != null) {
            settingHandlerRegistry.register(
                ChannelMessageNoticeSettingHandler(
                    services.playerSettingsManager,
                    services.languageManager,
                ),
            )
        }

        // Conditionally register Japanese conversion setting
        if (services.romajiConverter != null) {
            settingHandlerRegistry.register(
                JapaneseConversionSettingHandler(
                    services.playerSettingsManager,
                    services.languageManager,
                ),
            )
        }

        // Register core commands
        commandRegistry.registerAll(
            TellCommand(
                this,
                services.directMessageHandler,
                services.languageManager,
                services.crossServerDirectMessageManager,
                services.remotePlayerRegistry,
                configuration.features.velocityIntegration.serverName,
            ),
            LunaticChatCommand(this, settingHandlerRegistry, services.languageManager, configuration),
        )

        // Conditionally register /reply command if quick replies are enabled
        if (configuration.features.quickReplies.enabled) {
            commandRegistry.registerAll(
                ReplyCommand(
                    this,
                    services.directMessageHandler,
                    services.languageManager,
                    services.crossServerDirectMessageManager,
                ),
            )
        }

        // Conditionally register /lcv command if Velocity integration is enabled
        services.velocityConnectionManager?.let { velocityManager ->
            commandRegistry.registerAll(
                VelocityStatusCommand(this, velocityManager, services.languageManager),
            )
        }

        commandRegistry.initialize()
    }

    /**
     * Registers all event listeners.
     */
    private fun registerEventListeners() {
        EventListenerRegistry.registerAll(this, services, configuration, updateAvailable)
    }

    /**
     * Initializes the update checker.
     * Uses plugin coroutine scope instead of runBlocking for non-blocking async execution.
     */
    private fun initializeUpdateChecker(httpClient: HttpClient) {
        updateChecker =
            UpdateChecker(
                currentVersion = pluginMeta.version,
                logger = logger,
                httpClient = httpClient,
            )
        pluginScope.scope.launch {
            checkUpdates()
        }
    }

    private suspend fun checkUpdates() {
        val result = updateChecker?.checkForUpdates()
        when (result) {
            is UpdateCheckResult.ExistUpdate -> {
                logger.info("A new version of LunaticChat is available!")
                logger.info("You can download the latest build from GitHub or Modrinth.")
                logger.info("   GitHub: https://github.com/m1sk9/LunaticChat/releases/latest")
                logger.info("   Modrinth: https://modrinth.com/plugin/lunaticchat/version/latest")
                updateAvailable.set(true)
            }
            is UpdateCheckResult.NotUpdate -> {
                logger.info("LunaticChat is up to date.")
            }
            // Include failed case for completeness
            else -> {
                logger.warning("Failed to check for updates.")
            }
        }
    }
}
