<?php

declare(strict_types=1);

namespace FleekDash\Admin\Menu;

/**
 * Shared loader for WordPress admin files and menu globals.
 * Used by AdminMenuContextBuilder and MenuFromScratchBuilder to eliminate duplication.
 *
 * @package FleekDash\Admin\Menu
 */
class WordPressAdminMenuLoader
{
    private const MENU_PHP = 'wp-admin/menu.php';

    private const ADMIN_FILES = [
        'wp-admin/includes/admin.php',
        'wp-admin/includes/meta-boxes.php',
        'wp-admin/includes/screen.php',
        'wp-admin/includes/plugin.php',
    ];

    public static function loadCoreAdminFiles(string $logPrefix = 'FleekDash'): void
    {
        foreach (self::ADMIN_FILES as $file) {
            $file_path = ABSPATH . $file;
            if (\file_exists($file_path)) {
                try {
                    require_once $file_path; // NOSONAR - WordPress core file, cannot use "use"
                } catch (\Throwable $e) {
                    if (\defined('WP_DEBUG') && WP_DEBUG) {
                        \error_log("{$logPrefix}: Failed to load {$file}: " . $e->getMessage());
                    }
                }
            }
        }
    }

    public static function loadMenuPhp(): void
    {
        $path = ABSPATH . self::MENU_PHP;
        if (\file_exists($path)) {
            require_once $path; // NOSONAR - WordPress core file, cannot use "use"
        }
    }

    /**
     * Whether wp-admin/menu.php is already loaded in this request (require_once would no-op).
     * Used to avoid clearing $menu/$submenu when a second build cannot repopulate them.
     */
    public static function isAdminMenuPhpLoaded(): bool
    {
        $path = ABSPATH . self::MENU_PHP;
        if (!\file_exists($path)) {
            return false;
        }
        $resolved = \realpath($path);
        $expected = \wp_normalize_path($resolved !== false ? $resolved : $path);
        foreach (\get_included_files() as $file) {
            if (\wp_normalize_path((string) $file) === $expected) {
                return true;
            }
        }
        return false;
    }

    public static function initializeMenuGlobals(): void
    {
        global $_wp_submenu_nopriv, $_wp_menu_nopriv, $menu_order, $default_menu_order;
        if (!isset($_wp_submenu_nopriv)) {
            $_wp_submenu_nopriv = [];
        }
        if (!isset($_wp_menu_nopriv)) {
            $_wp_menu_nopriv = [];
        }
        if (!isset($menu_order) || !\is_array($menu_order)) {
            $menu_order = [];
        }
        if (!isset($default_menu_order) || !\is_array($default_menu_order)) {
            $default_menu_order = [];
        }
    }

    public static function filterNullMenuItems(): void
    {
        global $menu, $submenu;
        if (!empty($menu) && \is_array($menu)) {
            $menu = \array_filter($menu, static fn($item) =>
                $item !== null && \is_array($item) && !empty($item[0]));
        }
        if (!empty($submenu) && \is_array($submenu)) {
            $filtered = [];
            foreach ($submenu as $key => $items) {
                if ($items === null || !\is_array($items)) {
                    continue;
                }
                $valid = \array_filter($items, static fn($item) =>
                    $item !== null && \is_array($item) && !empty($item[0]));
                if (!empty($valid)) {
                    $filtered[$key] = $valid;
                }
            }
            $submenu = $filtered;
        }
    }

    public static function ensureDefaultMenuOrderComplete(): void
    {
        global $menu, $default_menu_order;
        if (empty($menu) || !\is_array($menu) || empty($default_menu_order) || !\is_array($default_menu_order)) {
            return;
        }
        foreach ($menu as $menu_item) {
            if ($menu_item === null || !\is_array($menu_item) || !isset($menu_item[2])) {
                continue;
            }
            if (!isset($default_menu_order[$menu_item[2]])) {
                $default_menu_order[$menu_item[2]] = 9999;
            }
        }
    }

    /**
     * Call after admin_menu / _admin_menu. WordPress fires current_screen from set_current_screen().
     * Must NOT run before wp-admin/menu.php and admin_menu — many plugins register submenus on current_screen.
     */
    public static function setDashboardScreenAfterAdminMenu(): void
    {
        if (!\function_exists('set_current_screen')) {
            return;
        }
        try {
            \set_current_screen('dashboard');
        } catch (\Throwable $e) {
            if (\defined('WP_DEBUG') && WP_DEBUG) {
                \error_log('[FleekDash WordPressAdminMenuLoader] set_current_screen failed: ' . $e->getMessage());
            }
        }
    }
}
