<?php
namespace Components\Resources\Controllers;

use Components\ConfigStore;
use Components\Support\Htmx;

class ModuleConfigController extends BaseController
{
    /**
     * Handle save/read for module configuration.
     * Returns HTML string and sets appropriate HTTP status codes when needed.
     */
    public static function handle(): string
    {
        $module = (string) self::getParam('module', '', 'key');

        if ($module === '') {
            http_response_code(400);
            return '<div class="text-sm text-red-600">Missing module key</div>';
        }

        // Return mode & UI flags
        $returnMode = self::determineReturnMode();
        [$drawerFlag, $autoCloseRaw, $autoCloseEnabled] = self::resolveDrawerAndAutoClose();

        // Custom logic: status toggle, module removal and UI open state
        $statusToggled = self::handleStatusToggleForModule($module);
        $moduleRemoved = self::handleRemoveForModule($module);
        $panelId = \Components\Support\Htmx::resolvePanelId(null, $drawerFlag);
        if ($moduleRemoved) {
            return self::renderModuleRemoved($module, $drawerFlag, $panelId);
        }
        $uiOpen = self::handleUiOpenForModule($module, $returnMode);
        if ($uiOpen !== null) { return $uiOpen; }

        $viewModeHandled = self::handleViewMode();
        if ($viewModeHandled !== null) { return $viewModeHandled; }

        $performanceTimeframeHandled = self::handlePerformanceTimeframe();
        if ($performanceTimeframeHandled !== null) { return $performanceTimeframeHandled; }

        // Engine + keys
        $engine = self::getEngineForModule($module);
        [$keysParam, $allowedSet] = self::getKeysAndAllowedSet($engine);

        // Posted fields
        $postAll = \Components\Common\Request::all('post');
        $hasPostedFields = self::hasPostedFields($postAll);
        $returnMode = self::finalizeReturnModeForStatus($returnMode, $hasPostedFields);

        $saveSucceeded = false;
        if ($hasPostedFields) {
            $existing = ConfigStore::getModuleConfig($module);
            $normalized = $engine->normalizeSubmittedValues($postAll);
            $validatePayload = array_merge($existing, $postAll);
            $validatePayload['__mode'] = 'edit';
            $errors = $engine->validate($validatePayload);
            if (is_array($allowedSet) && !empty($allowedSet)) {
                $normalized = array_intersect_key($normalized, $allowedSet);
                $errors = array_intersect_key($errors, $allowedSet);
            }
            if (!empty($errors)) {
                // Render edit form with errors
                return self::renderConfigEditPage($module, $keysParam);
            }

            // Checkbox/toggle semantics and persistence
            $isFullForm = !is_array($allowedSet) || empty($allowedSet);
            if ($keysParam !== '') { $isFullForm = false; }
            $normalized = self::applyCheckboxSemantics($engine, $normalized, $isFullForm, $allowedSet);

            $toPersist = $isFullForm ? array_merge($existing, $normalized) : $normalized;
            ConfigStore::setModuleConfig($module, $toPersist, !$isFullForm);
            // Only mark module as configured when a FULL configuration form (no keys/subset) was saved successfully.
            if ($isFullForm) {
                ConfigStore::setConfigured($module);
            }
            \mailbeez_pro::invalidateFlowCacheStatic($module);
            // Emit refresh events for consumers (module cards, DOI flow, etc.).
            // This is especially important for key-subset edits (e.g. coupon id) where the UI would
            // otherwise not know it should redraw the flow.
            try {
                Htmx::trigger('module_config:updated', ['id' => (string)$module]);
                Htmx::trigger($module . ':expandable:refresh');
                Htmx::flushTriggers();
            } catch (\Throwable $e) {
                // ignore header errors
            }
            \Components\Data\DataRegistry::reset();
            $saveSucceeded = true;
        }

        // Response rendering
        if (($saveSucceeded || $statusToggled) && $returnMode === 'module_card') {
            $response = self::renderModuleCard($module, $saveSucceeded, $autoCloseEnabled, $panelId);
//            try { \Components\Support\Htmx::flushTriggers(); } catch (\Throwable $e) { /* ignore */ }
            return $response;
        }

        // Default: configuration view
        $response = self::renderConfigurationView($module, $keysParam, $saveSucceeded, $autoCloseEnabled, $panelId);
//        try { \Components\Support\Htmx::flushTriggers(); } catch (\Throwable $e) { /* ignore */ }
        return $response;
    }


    /** Handle status toggle if requested. Returns true when status was toggled. */
    protected static function handleStatusToggleForModule(string $module): bool
    {
        if (\mh_request('status_toggle', null) !== null) {
            $on = \mh_post('status', null) !== null;
            if ($on && !ConfigStore::isConfigured($module)) {
                return false;
            }
            if (!$on) {
                ConfigStore::setConfigured($module);
            }
            \Components\ConfigStore::setModuleStatus($module, $on);
            \mailbeez_pro::invalidateFlowCacheStatic($module);
            \Components\Support\Htmx::trigger($module . ':expandable:refresh');
            \Components\Data\DataRegistry::reset();
            return true;
        }
        return false;
    }

    /** Persist UI open state; returns '' (empty string) when 204 open_state response should be returned, otherwise null. */
    protected static function handleUiOpenForModule(string $module, string $returnMode): ?string
    {
        if (\mh_post('ui_open', null) !== null) {
            $isOpen = \mh_post('ui_open', '', 'string') !== '';
            \Components\ConfigStore::setUiOpenState($module, $isOpen);
            if ($returnMode === 'open_state') {
                http_response_code(204);
                return '';
            }
        }
        return null;
    }

    /** Persist view mode; returns '' (empty string) when 204 response should be returned, otherwise null. */
    protected static function handleViewMode(): ?string
    {
        if (\mh_post('view_mode', null) !== null) {
            $context = (string) self::getParam('context', '', 'string');
            $mode = (string) \mh_post('view_mode', '', 'string');
            if ($context !== '' && $mode !== '') {
                \Components\ConfigStore::setViewMode($context, $mode);
                http_response_code(204);
                return '';
            }
        }
        return null;
    }

    protected static function handlePerformanceTimeframe(): ?string
    {
        if (\mh_post('performance_timeframe', null) !== null) {
            $context = (string) self::getParam('context', '', 'string');
            $timeframe = (string) \mh_post('performance_timeframe', '', 'string');
            if ($context !== '' && $timeframe !== '') {
                \Components\ConfigStore::setPerformanceTimeframe($context, $timeframe);
                http_response_code(204);
                return '';
            }
        }
        return null;
    }

    /** Render edit page for module with optional keys param. */
    protected static function renderConfigEditPage(string $module, string $keysParam): string
    {
        $_GET['module'] = $module;
        $_GET['mode'] = 'edit';
        self::persistCommonParamsToGet();
        if ($keysParam !== '') { $_GET['keys'] = $keysParam; }
        ob_start();
        include BEEZUI_ROOT . '/pages/module_configuration.php';
        return ob_get_clean();
    }

    /** Render configuration view page and optional auto-close + OOB module_card. */
    protected static function renderConfigurationView(string $module, string $keysParam, bool $saveSucceeded, bool $autoCloseEnabled, string $panelId = 'config-modal'): string
    {
        $_SERVER['REQUEST_METHOD'] = 'GET';
        $_GET['module'] = $module;

        $isInline = (\Components\Support\Htmx::resolvePanelId('') === '');
        $_GET['mode'] = $isInline ? 'edit' : 'view';

        self::persistCommonParamsToGet();
        if ($keysParam !== '') { $_GET['keys'] = $keysParam; }
        ob_start();
        include BEEZUI_ROOT . '/pages/module_configuration.php';
        if ($saveSucceeded && $autoCloseEnabled) {
            ?>
            <div style="min-height: 240px"></div>
            <?php \Components\Support\Htmx::parentClose($panelId); ?>
            <?php
        }
        if ($saveSucceeded && \mh_post('return', null, 'string') === 'module_card') {
            $all = \Components\ModuleLoader::all();
            $m = $all[$module] ?? null;
            if ($m) {
                $oobSwap = 'outerHTML';
                include BEEZUI_ROOT . '/pages/components/trigger_module.php';
            }
        }
        return ob_get_clean();
    }

    /** Render module card for trigger list and optionally auto-close script. */
    protected static function renderModuleCard(string $module, bool $saveSucceeded, bool $autoCloseEnabled, string $panelId = 'config-modal'): string
    {
        $all = \Components\ModuleLoader::all();
        $m = $all[$module] ?? null;
        if (!$m) {
            http_response_code(404);
            return '<div class="text-sm text-red-600">Unknown module: ' . \Components\Base::h($module) . '</div>';
        }
        $oobSwap = 'outerHTML';
        ob_start();
        include BEEZUI_ROOT . '/pages/components/trigger_module.php';
        if ($saveSucceeded && $autoCloseEnabled) {
            ?>
            <div style="min-height: 240px"></div>
            <?php \Components\Support\Htmx::parentClose($panelId); ?>
            <?php
        }
        return ob_get_clean();
    }
    /** Handle module removal if requested. Returns true when module was removed. */
    protected static function handleRemoveForModule(string $module): bool
    {
        if (\mh_request('remove', null) !== null) {
            $exists = function_exists('mh_class_exists') ? \mh_class_exists($module) : class_exists($module);
            if ($exists) {
                $m = new $module();
                if (method_exists($m, 'remove')) {
                    $m->remove();
                }
            } else {
                // Try to include it if it's a standard module
                if (defined('MH_DIR_MODULE') && file_exists(MH_DIR_MODULE . $module . '.php')) {
                    include_once(MH_DIR_MODULE . $module . '.php');
                    if (class_exists($module)) {
                        $m = new $module();
                        if (method_exists($m, 'remove')) {
                            $m->remove();
                        }
                    }
                }
            }
            // Clear BeezUI configured marker for this module on uninstall
            try { \Components\ConfigStore::clearConfigured($module); } catch (\Throwable $e) { /* ignore */ }
            try {
                \Components\ModuleLoader::forceRefresh();
            } catch (\Throwable $e) {
                \Components\Data\DataRegistry::reset();
            }
            return true;
        }
        return false;
    }

    /** Render module removed script. */
    protected static function renderModuleRemoved(string $module, int $drawerFlag, string $panelId): string
    {
        \Components\Support\Htmx::trigger('trigger:refresh');
        \Components\Support\Htmx::flushTriggers();
        ob_start();
        \Components\Support\Htmx::parentClose('confirm-modal');
        \Components\Support\Htmx::parentClose($panelId);
        return ob_get_clean();
    }
}
