<?php
declare(strict_types=1);

if (!defined('ABSPATH')) {
    exit;
}

if (!function_exists('ekesto_ca_edition_conflict_guard_basenames')) {
    /**
     * Return the fixed Lite/Pro plugin basenames.
     *
     * @return array<string,string>
     */
    function ekesto_ca_edition_conflict_guard_basenames(): array
    {
        return [
            'lite' => 'cache-autopilot/cache-autopilot.php',
            'pro' => 'cache-autopilot-pro/cache-autopilot.php',
        ];
    }
}

if (!function_exists('ekesto_ca_edition_conflict_guard_current_basename')) {
    /**
     * Resolve the current artifact basename without relying on Composer.
     *
     * @param string $pluginFile Absolute plugin file path.
     * @return string
     */
    function ekesto_ca_edition_conflict_guard_current_basename(string $pluginFile): string
    {
        return basename(dirname($pluginFile)) . '/' . basename($pluginFile);
    }
}

if (!function_exists('ekesto_ca_edition_conflict_guard_current_edition')) {
    /**
     * Resolve the current artifact edition from its fixed basename.
     *
     * @param string $pluginFile Absolute plugin file path.
     * @return string
     */
    function ekesto_ca_edition_conflict_guard_current_edition(string $pluginFile): string
    {
        $current = ekesto_ca_edition_conflict_guard_current_basename($pluginFile);

        foreach (ekesto_ca_edition_conflict_guard_basenames() as $edition => $basename) {
            if ($current === $basename) {
                return $edition;
            }
        }

        return '';
    }
}

if (!function_exists('ekesto_ca_edition_conflict_guard_ensure_plugin_functions')) {
    /**
     * Load plugin-state helpers when early bootstrap has not loaded them yet.
     *
     * @return void
     */
    function ekesto_ca_edition_conflict_guard_ensure_plugin_functions(): void
    {
        if (
            function_exists('deactivate_plugins')
            && function_exists('is_plugin_active')
            && function_exists('is_plugin_active_for_network')
        ) {
            return;
        }

        $pluginIncludes = ABSPATH . 'wp-admin/includes/plugin.php';
        if (is_file($pluginIncludes)) {
            require_once $pluginIncludes;
        }
    }
}

if (!function_exists('ekesto_ca_edition_conflict_guard_active_state')) {
    /**
     * Return whether a plugin basename is site-active and/or network-active.
     *
     * @param string $basename Plugin basename.
     * @return array{site:bool,network:bool}
     */
    function ekesto_ca_edition_conflict_guard_active_state(string $basename): array
    {
        ekesto_ca_edition_conflict_guard_ensure_plugin_functions();

        $siteActive = false;
        $networkActive = false;

        if (function_exists('get_option')) {
            $activePlugins = get_option('active_plugins', []);
            $siteActive = is_array($activePlugins) && in_array($basename, $activePlugins, true);
        }

        if (function_exists('get_site_option')) {
            $networkPlugins = get_site_option('active_sitewide_plugins', []);
            $networkActive = is_array($networkPlugins) && isset($networkPlugins[$basename]);
        }

        return [
            'site' => $siteActive,
            'network' => $networkActive,
        ];
    }
}

if (!function_exists('ekesto_ca_edition_conflict_guard_is_active')) {
    /**
     * Return whether a plugin basename is active in any supported scope.
     *
     * @param string $basename Plugin basename.
     * @return bool
     */
    function ekesto_ca_edition_conflict_guard_is_active(string $basename): bool
    {
        $state = ekesto_ca_edition_conflict_guard_active_state($basename);

        return $state['site'] || $state['network'];
    }
}

if (!function_exists('ekesto_ca_edition_conflict_guard_deactivate')) {
    /**
     * Silently deactivate a plugin basename without firing shared lifecycle hooks.
     *
     * @param string    $basename    Plugin basename.
     * @param bool|null $networkWide Network activation scope when known.
     * @return void
     */
    function ekesto_ca_edition_conflict_guard_deactivate(string $basename, ?bool $networkWide = null): void
    {
        ekesto_ca_edition_conflict_guard_ensure_plugin_functions();

        if (!function_exists('deactivate_plugins')) {
            return;
        }

        if ($networkWide !== null) {
            deactivate_plugins($basename, true, $networkWide);
            return;
        }

        $state = ekesto_ca_edition_conflict_guard_active_state($basename);

        if ($state['network']) {
            deactivate_plugins($basename, true, true);
        }

        if ($state['site']) {
            deactivate_plugins($basename, true, false);
        }
    }
}

if (!function_exists('ekesto_ca_edition_conflict_guard_notice_option')) {
    /**
     * Return the conflict notice option key.
     *
     * @return string
     */
    function ekesto_ca_edition_conflict_guard_notice_option(): string
    {
        return 'ekesto_ca_edition_conflict_notices';
    }
}

if (!function_exists('ekesto_ca_edition_conflict_guard_store_notice')) {
    /**
     * Store an informational conflict notice for the next admin page load.
     *
     * @param string $code Stable notice code.
     * @param string $message Notice message.
     * @return void
     */
    function ekesto_ca_edition_conflict_guard_store_notice(string $code, string $message): void
    {
        if (!function_exists('get_site_option') || !function_exists('update_site_option')) {
            return;
        }

        $option = ekesto_ca_edition_conflict_guard_notice_option();
        $notices = get_site_option($option, []);
        $notices = is_array($notices) ? $notices : [];
        $notices[$code] = $message;

        update_site_option($option, $notices);
    }
}

if (!function_exists('ekesto_ca_edition_conflict_guard_render_notices')) {
    /**
     * Render and clear stored conflict notices.
     *
     * @return void
     */
    function ekesto_ca_edition_conflict_guard_render_notices(): void
    {
        if (!function_exists('get_site_option') || !function_exists('delete_site_option')) {
            return;
        }

        if (!ekesto_ca_edition_conflict_guard_is_allowed_notice_screen()) {
            return;
        }

        $option = ekesto_ca_edition_conflict_guard_notice_option();
        $notices = get_site_option($option, []);
        if (!is_array($notices) || $notices === []) {
            return;
        }

        delete_site_option($option);

        $allowed_notice_html = array(
            'strong' => array(),
            'br' => array(),
        );

        foreach ($notices as $code => $message) {
            if (!is_string($message) || $message === '') {
                continue;
            }

            echo '<div class="notice notice-error is-dismissible"><p>'
                . wp_kses(
                    ekesto_ca_edition_conflict_guard_render_notice_message((string) $code, $message),
                    $allowed_notice_html
                )
                . '</p></div>';
        }
    }
}

if (!function_exists('ekesto_ca_edition_conflict_guard_render_notice_message')) {
    /**
     * Render a stored notice message with safe inline formatting.
     *
     * @param string $code    Stable notice code.
     * @param string $message Stored notice message.
     * @return string
     */
    function ekesto_ca_edition_conflict_guard_render_notice_message(string $code, string $message): string
    {
        if ($code === 'edition_activation_blocked') {
            return '<strong>' . esc_html__('Cache Autopilot:', 'cache-autopilot') . '</strong> '
                . esc_html__('The Free and PRO versions cannot be active at the same time.', 'cache-autopilot')
                . '<br>'
                . esc_html__('The version you tried to activate was not activated. Deactivate the active version first, then try again.', 'cache-autopilot');
        }

        return esc_html($message);
    }
}

if (!function_exists('ekesto_ca_edition_conflict_guard_is_allowed_notice_screen')) {
    /**
     * Return whether the current screen may show Cache Autopilot notices.
     *
     * @return bool
     */
    function ekesto_ca_edition_conflict_guard_is_allowed_notice_screen(): bool
    {
        return function_exists('ekesto_ca_admin_notice_screen_is_allowed')
            && ekesto_ca_admin_notice_screen_is_allowed();
    }
}

if (!function_exists('ekesto_ca_edition_conflict_guard_register_notice_renderer')) {
    /**
     * Register admin notice rendering when hooks are available.
     *
     * @return void
     */
    function ekesto_ca_edition_conflict_guard_register_notice_renderer(): void
    {
        if (!function_exists('add_action')) {
            return;
        }

        add_action('admin_notices', 'ekesto_ca_edition_conflict_guard_render_notices');
        add_action('network_admin_notices', 'ekesto_ca_edition_conflict_guard_render_notices');
    }
}

if (!function_exists('ekesto_ca_edition_conflict_guard_register_activation_self_deactivation')) {
    /**
     * Deactivate only this edition after WordPress completes its activation write.
     *
     * @param string $currentBasename Current plugin basename.
     * @return void
     */
    function ekesto_ca_edition_conflict_guard_register_activation_self_deactivation(string $currentBasename): void
    {
        if (!function_exists('add_action')) {
            return;
        }

        add_action(
            'activated_plugin',
            static function (string $plugin, bool $networkWide) use ($currentBasename): void {
                if ($plugin !== $currentBasename) {
                    return;
                }

                ekesto_ca_edition_conflict_guard_deactivate($currentBasename, $networkWide);
            },
            10,
            2
        );
    }
}

if (!function_exists('ekesto_ca_edition_conflict_guard_conflict_notice_message')) {
    /**
     * Return the shared Lite/PRO activation conflict notice.
     *
     * @return string
     */
    function ekesto_ca_edition_conflict_guard_conflict_notice_message(): string
    {
        return "Cache Autopilot: The Free and PRO versions cannot be active at the same time.\nThe version you tried to activate was not activated. Deactivate the active version first, then try again.";
    }
}

if (!function_exists('ekesto_ca_edition_conflict_guard_request_action')) {
    /**
     * Return the current admin request action.
     *
     * @return string
     */
    function ekesto_ca_edition_conflict_guard_request_action(): string
    {
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only activation action classification before WordPress performs the activation flow.
        $action = isset($_REQUEST['action']) ? sanitize_key(wp_unslash($_REQUEST['action'])) : '';

        // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Read-only activation action classification before WordPress performs the activation flow.
        if ((!is_string($action) || $action === '' || $action === '-1') && isset($_REQUEST['action2'])) {
            $action = sanitize_key(wp_unslash($_REQUEST['action2']));
        }
        // phpcs:enable WordPress.Security.NonceVerification.Recommended

        if (!is_string($action) || $action === '' || $action === '-1') {
            return '';
        }

        if (function_exists('sanitize_key')) {
            return sanitize_key($action);
        }

        return strtolower((string) preg_replace('/[^a-z0-9_\-]/i', '', $action));
    }
}

if (!function_exists('ekesto_ca_edition_conflict_guard_is_activation_request')) {
    /**
     * Return whether the current request is activating a plugin.
     *
     * @return bool
     */
    function ekesto_ca_edition_conflict_guard_is_activation_request(): bool
    {
        return in_array(ekesto_ca_edition_conflict_guard_request_action(), ['activate', 'activate-selected'], true);
    }
}

if (!function_exists('ekesto_ca_edition_conflict_guard_has_active_sibling')) {
    /**
     * Return whether the opposite Lite/Pro artifact is active.
     *
     * @param string $pluginFile Absolute plugin file path.
     * @return bool
     */
    function ekesto_ca_edition_conflict_guard_has_active_sibling(string $pluginFile): bool
    {
        $edition = ekesto_ca_edition_conflict_guard_current_edition($pluginFile);
        $basenames = ekesto_ca_edition_conflict_guard_basenames();

        if ($edition === 'lite') {
            return ekesto_ca_edition_conflict_guard_is_active($basenames['pro']);
        }

        if ($edition === 'pro') {
            return ekesto_ca_edition_conflict_guard_is_active($basenames['lite']);
        }

        return false;
    }
}

if (!function_exists('ekesto_ca_edition_conflict_guard_run')) {
    /**
     * Enforce Lite/Pro runtime exclusivity before Composer autoload.
     *
     * @param string $pluginFile Absolute plugin file path.
     * @return bool True when the current plugin should stop booting.
     */
    function ekesto_ca_edition_conflict_guard_run(string $pluginFile): bool
    {
        ekesto_ca_edition_conflict_guard_register_notice_renderer();

        $edition = ekesto_ca_edition_conflict_guard_current_edition($pluginFile);
        $basenames = ekesto_ca_edition_conflict_guard_basenames();
        $currentBasename = ekesto_ca_edition_conflict_guard_current_basename($pluginFile);

        if ($edition === 'pro') {
            if (ekesto_ca_edition_conflict_guard_is_active($basenames['lite'])) {
                ekesto_ca_edition_conflict_guard_store_notice(
                    'edition_activation_blocked',
                    ekesto_ca_edition_conflict_guard_conflict_notice_message()
                );

                if (ekesto_ca_edition_conflict_guard_is_active($currentBasename)) {
                    ekesto_ca_edition_conflict_guard_deactivate($currentBasename);
                } else {
                    ekesto_ca_edition_conflict_guard_register_activation_self_deactivation($currentBasename);
                }

                return true;
            }

            return false;
        }

        if ($edition !== 'lite' || !ekesto_ca_edition_conflict_guard_is_active($basenames['pro'])) {
            return false;
        }

        $currentActive = ekesto_ca_edition_conflict_guard_is_active($currentBasename);

        ekesto_ca_edition_conflict_guard_store_notice(
            'edition_activation_blocked',
            ekesto_ca_edition_conflict_guard_conflict_notice_message()
        );

        if ($currentActive) {
            ekesto_ca_edition_conflict_guard_deactivate($currentBasename);
        } else {
            ekesto_ca_edition_conflict_guard_register_activation_self_deactivation($currentBasename);
        }

        return true;
    }
}
