<?php
/**
 * 📋 MENU CONTROLLER - V2.2 PURE
 *
 * Manages WordPress admin menu and toolbar:
 * - Menu structure and data
 * - Role-based menu management
 * - Capability validation
 * - Menu filtering
 * - Cache management
 * - Menu overrides system
 *
 * **STATUS:** 100% Pure V2.2 - ZERO legacy dependencies
 *
 * @package FleekDash\Controllers
 * @since 2.2.0
 */

namespace FleekDash\Controllers;

use WP_REST_Request;
use FleekDash\Services\ResponseService;
use FleekDash\Admin\Menu\MenuCaptureService;
use FleekDash\Admin\Menu\MenuItemFormatter;
use FleekDash\Admin\Menu\RouteConverter;

/**
 * Class MenuController
 *
 * Pure V2.2 Controller - Uses V2.2 Services (NOT legacy APIs)
 * Uses MenuCaptureService, MenuItemFormatter for menu logic
 *
 * @package FleekDash\Controllers
 * @phpcs:ignore S1448 -- Orchestration controller; splitting would require broader menu API refactor
 */
class MenuController // NOSONAR php:S1448 - Orchestration controller; split would require broader menu API refactor
{
    /**
     * Cache group for menu data
     */
    private const CACHE_GROUP = 'fleekdash_menu';

    /**
     * Cache TTL (30 minutes)
     */
    private const CACHE_TTL = 1800;

    /** Error message when role parameter is missing */
    private const MSG_ROLE_REQUIRED = 'Role parameter is required';

    /**
     * Menu capture service
     */
    private $menuCapture;

    /**
     * Menu formatter
     */
    private $menuFormatter;

    /**
     * Constructor
     */
    public function __construct()
    {
        $routeConverter = new RouteConverter();
        $this->menuCapture = new MenuCaptureService();
        $this->menuFormatter = new MenuItemFormatter($routeConverter);
    }

    /**
     * 📋 Get menu data for current user
     *
     * @param WP_REST_Request $_request REST callback signature - unused
     * @return \WP_REST_Response
     */
    public function getMenu(WP_REST_Request $_request) // NOSONAR php:S1172 - WP REST callback
    {
        try {
            // Ensure menu is captured
            $this->menuCapture->ensureMenuCaptured();

            // Get stored menu data
            $menu = $this->menuCapture->getStoredMenu();
            $submenu = $this->menuCapture->getStoredSubmenu();

            // Format menu items
            $formatted_menu = $this->menuFormatter->formatMenuItems($menu, $submenu);

            return ResponseService::success('Menu data retrieved', [
                'menu' => $formatted_menu
            ]);

        } catch (\Exception $e) {
            return ResponseService::error(
                'Failed to retrieve menu',
                ['error' => $e->getMessage()],
                500
            );
        }
    }

    /**
     * 📋 Get menu data by role
     *
     * @param WP_REST_Request $request
     * @return \WP_REST_Response
     */
    public function getMenuByRole(WP_REST_Request $request)
    {
        try {
            $role = $request->get_param('role');

            if (empty($role)) {
                return ResponseService::error(self::MSG_ROLE_REQUIRED, null, 400);
            }

            // Ensure menu is captured
            $this->menuCapture->ensureMenuCaptured();

            // Get stored menu data
            $menu = $this->menuCapture->getStoredMenu();
            $submenu = $this->menuCapture->getStoredSubmenu();

            // Format menu items
            $formatted_menu = $this->menuFormatter->formatMenuItems($menu, $submenu);

            return ResponseService::success('Menu data retrieved for role', [
                'menu' => $formatted_menu,
                'role' => $role
            ]);

        } catch (\Exception $e) {
            return ResponseService::error(
                'Failed to retrieve menu by role',
                ['error' => $e->getMessage()],
                500
            );
        }
    }

    /**
     * 🔄 Refresh menu cache
     *
     * @param WP_REST_Request $_request REST callback signature - unused
     * @return \WP_REST_Response
     */
    public function refreshMenu(WP_REST_Request $_request) // NOSONAR php:S1172 - WP REST callback
    {
        try {
            // Clear all menu cache
            wp_cache_flush_group(self::CACHE_GROUP);

            return ResponseService::success('Menu cache refreshed');

        } catch (\Exception $e) {
            return ResponseService::error(
                'Failed to refresh menu cache',
                ['error' => $e->getMessage()],
                500
            );
        }
    }

    /**
     * 🗑️ Clear menu cache
     *
     * @param WP_REST_Request $_request REST callback signature - unused
     * @return \WP_REST_Response
     */
    public function clearMenuCache(WP_REST_Request $_request) // NOSONAR php:S1172 - WP REST callback
    {
        try {
            wp_cache_flush_group(self::CACHE_GROUP);

            return ResponseService::success('Menu cache cleared');

        } catch (\Exception $e) {
            return ResponseService::error(
                'Failed to clear menu cache',
                ['error' => $e->getMessage()],
                500
            );
        }
    }

    /**
     * 📊 Get cache status
     *
     * @param WP_REST_Request $_request REST callback signature - unused
     * @return \WP_REST_Response
     */
    public function getCacheStatus(WP_REST_Request $_request) // NOSONAR php:S1172 - WP REST callback
    {
        try {
            $cache_key = 'menu_' . \get_current_user_id();
            $cached = wp_cache_get($cache_key, self::CACHE_GROUP);

            return ResponseService::success('Cache status retrieved', [
                'cached' => !empty($cached),
                'cache_group' => self::CACHE_GROUP,
                'cache_ttl' => self::CACHE_TTL
            ]);

        } catch (\Exception $e) {
            return ResponseService::error(
                'Failed to get cache status',
                ['error' => $e->getMessage()],
                500
            );
        }
    }

    /**
     * 🔧 Get toolbar data
     *
     * @param WP_REST_Request $_request REST callback signature - unused
     * @return \WP_REST_Response
     */
    public function getToolbar(WP_REST_Request $_request) // NOSONAR php:S1172 - WP REST callback
    {
        try {
            // Get toolbar via WordPress admin bar
            global $wp_admin_bar;

            if (!isset($wp_admin_bar)) {
                // Initialize admin bar if needed
                require_once ABSPATH . 'wp-includes/class-wp-admin-bar.php';
                $wp_admin_bar = new \WP_Admin_Bar();
                do_action_ref_array('admin_bar_menu', [&$wp_admin_bar]);
            }

            $toolbar_nodes = $wp_admin_bar ? $wp_admin_bar->get_nodes() : [];

            return ResponseService::success('Toolbar data retrieved', [
                'toolbar' => array_values($toolbar_nodes)
            ]);

        } catch (\Exception $e) {
            return ResponseService::error(
                'Failed to retrieve toolbar',
                ['error' => $e->getMessage()],
                500
            );
        }
    }

    /**
     * 🔧 Get toolbar by role
     *
     * @param WP_REST_Request $request
     * @return \WP_REST_Response
     */
    public function getToolbarByRole(WP_REST_Request $request)
    {
        try {
            $role = $request->get_param('role');

            if (empty($role)) {
                return ResponseService::error(self::MSG_ROLE_REQUIRED, null, 400);
            }

            // Simplified: return same toolbar for all roles (can be enhanced later)
            global $wp_admin_bar;

            if (!isset($wp_admin_bar)) {
                require_once ABSPATH . 'wp-includes/class-wp-admin-bar.php';
                $wp_admin_bar = new \WP_Admin_Bar();
                do_action_ref_array('admin_bar_menu', [&$wp_admin_bar]);
            }

            $toolbar_nodes = $wp_admin_bar ? $wp_admin_bar->get_nodes() : [];

            return ResponseService::success('Toolbar data retrieved for role', [
                'toolbar' => array_values($toolbar_nodes),
                'role' => $role
            ]);

        } catch (\Exception $e) {
            return ResponseService::error(
                'Failed to retrieve toolbar by role',
                ['error' => $e->getMessage()],
                500
            );
        }
    }

    /**
     * 🔄 Refresh toolbar cache
     *
     * @param WP_REST_Request $_request REST callback signature - unused
     * @return \WP_REST_Response
     */
    public function refreshToolbar(WP_REST_Request $_request) // NOSONAR php:S1172 - WP REST callback
    {
        try {
            wp_cache_flush_group(self::CACHE_GROUP);

            return ResponseService::success('Toolbar cache refreshed');

        } catch (\Exception $e) {
            return ResponseService::error(
                'Failed to refresh toolbar cache',
                ['error' => $e->getMessage()],
                500
            );
        }
    }

    /**
     * 📊 Get toolbar cache status
     *
     * @param WP_REST_Request $_request REST callback signature - unused
     * @return \WP_REST_Response
     */
    public function getToolbarCacheStatus(WP_REST_Request $_request) // NOSONAR php:S1172 - WP REST callback
    {
        try {
            return ResponseService::success('Toolbar cache status retrieved', [
            'cached' => false,
                'message' => 'Toolbar cache tracking not yet implemented'
            ]);

        } catch (\Exception $e) {
            return ResponseService::error(
                'Failed to get toolbar cache status',
                ['error' => $e->getMessage()],
                500
            );
        }
    }

    /**
* Mark cache as cleared
     *
     * @param WP_REST_Request $_request REST callback signature - unused
     * @return \WP_REST_Response
     */
    public function markCacheCleared(WP_REST_Request $_request) // NOSONAR php:S1172 - WP REST callback
    {
        try {
            // Mark timestamp of cache clear
            \update_option('_fleekdash_menu_cache_cleared', time());

            return ResponseService::success('Cache marked as cleared');

        } catch (\Exception $e) {
            return ResponseService::error(
                'Failed to mark cache as cleared',
                ['error' => $e->getMessage()],
                500
            );
        }
    }

    /**
     * 📝 Get role overrides
     *
     * @param WP_REST_Request $request
     * @return \WP_REST_Response
     */
    public function getRoleOverrides(WP_REST_Request $request)
    {
        try {
            $role = $request->get_param('role');

            if (empty($role)) {
                return ResponseService::error(self::MSG_ROLE_REQUIRED, null, 400);
            }

            $overrides = \get_option("_fleekdash_menu_overrides_{$role}", []);

            return ResponseService::success('Role overrides retrieved', [
                'role' => $role,
                'overrides' => $overrides
            ]);

        } catch (\Exception $e) {
            return ResponseService::error(
                'Failed to get role overrides',
                ['error' => $e->getMessage()],
                500
            );
        }
    }

    /**
     * 💾 Save role overrides
     *
     * @param WP_REST_Request $request
     * @return \WP_REST_Response
     */
    public function saveRoleOverrides(WP_REST_Request $request)
    {
        try {
            $role = $request->get_param('role');
            $overrides = $request->get_param('overrides');

            if (empty($role)) {
                return ResponseService::error(self::MSG_ROLE_REQUIRED, null, 400);
            }

            \update_option("_fleekdash_menu_overrides_{$role}", $overrides);

            return ResponseService::success('Role overrides saved');

        } catch (\Exception $e) {
            return ResponseService::error(
                'Failed to save role overrides',
                ['error' => $e->getMessage()],
                500
            );
        }
    }

    /**
     * 🔄 Reset role overrides
     *
     * @param WP_REST_Request $request
     * @return \WP_REST_Response
     */
    public function resetRoleOverrides(WP_REST_Request $request)
    {
        try {
            $role = $request->get_param('role');

            if (empty($role)) {
                return ResponseService::error(self::MSG_ROLE_REQUIRED, null, 400);
            }

            \delete_option("_fleekdash_menu_overrides_{$role}");

            return ResponseService::success('Role overrides reset');

        } catch (\Exception $e) {
            return ResponseService::error(
                'Failed to reset role overrides',
                ['error' => $e->getMessage()],
                500
            );
        }
    }

    /**
     * 🔄 Reset all overrides
     *
     * @param WP_REST_Request $_request REST callback signature - unused
     * @return \WP_REST_Response
     */
    public function resetAllOverrides(WP_REST_Request $_request) // NOSONAR php:S1172 - WP REST callback
    {
        try {
            global $wpdb;

            // Delete all menu override options
            $wpdb->query(
                "DELETE FROM {$wpdb->options}
                 WHERE option_name LIKE '_fleekdash_menu_overrides_%'"
            );

            return ResponseService::success('All menu overrides reset');

        } catch (\Exception $e) {
            return ResponseService::error(
                'Failed to reset all overrides',
                ['error' => $e->getMessage()],
                500
            );
        }
    }

    /**
     * 📋 Get complete menu structure
     *
     * @param WP_REST_Request $_request REST callback signature - unused
     * @return \WP_REST_Response
     */
    public function getCompleteStructure(WP_REST_Request $_request) // NOSONAR php:S1172 - WP REST callback
    {
        try {
            // Get all roles
            $all_roles = wp_roles()->roles;

            // Get current menu structure
            $this->menuCapture->ensureMenuCaptured();
            $menu = $this->menuCapture->getStoredMenu();
            $submenu = $this->menuCapture->getStoredSubmenu();

            // Format menu
            $formatted_menu = $this->menuFormatter->formatMenuItems($menu, $submenu);

            $complete_structure = [
                'menu' => $formatted_menu,
                'roles' => $all_roles
            ];

            return ResponseService::success('Complete menu structure retrieved', $complete_structure);

        } catch (\Exception $e) {
            return ResponseService::error(
                'Failed to get complete structure',
                ['error' => $e->getMessage()],
                500
            );
        }
    }

    /**
     * 🔍 Get filtered menu (server-side filtering by capabilities)
     *
     * @param WP_REST_Request $request
     * @return \WP_REST_Response
     */
    public function getFilteredMenu(WP_REST_Request $request)
    {
        try {
            $role = $request->get_param('role');

            if (empty($role)) {
                return ResponseService::error(self::MSG_ROLE_REQUIRED, null, 400);
            }

            // Capture menu
            $this->menuCapture->ensureMenuCaptured();
            $menu = $this->menuCapture->getStoredMenu();
            $submenu = $this->menuCapture->getStoredSubmenu();

            // Format and filter menu
            $formatted_menu = $this->menuFormatter->formatMenuItems($menu, $submenu);
            $filtered_menu = $this->filterMenuByCapabilities($formatted_menu, $role);

            return ResponseService::success('Filtered menu retrieved', [
                'menu' => $filtered_menu,
                'role' => $role
            ]);

        } catch (\Exception $e) {
            return ResponseService::error(
                'Failed to get filtered menu',
                ['error' => $e->getMessage()],
                500
            );
        }
    }

    /**
     * Filter menu by role capabilities
     *
     * @param array $menu_data
     * @param string $role
     * @return array
     */
    private function filterMenuByCapabilities($menu_data, $role)
    {
        $role_obj = get_role($role);

        if (!$role_obj) {
            return $menu_data;
        }

        $filtered = [];

        foreach ($menu_data as $item) {
            $capability = $item['capability'] ?? '';

            if (empty($capability) || isset($role_obj->capabilities[$capability])) {
                $filtered[] = $item;
            }
        }

        return $filtered;
    }

    /**
* Validate capabilities
     *
     * @param WP_REST_Request $request
     * @return \WP_REST_Response
     */
    public function validateCapabilities(WP_REST_Request $request)
    {
        $result = $this->executeCapabilityValidation($request);
        return $result ?? ResponseService::error('Failed to validate capabilities', null, 500);
    }

    /**
     * Execute capability validation. Returns WP_REST_Response or null on exception.
     *
     * @param WP_REST_Request $request
     * @return \WP_REST_Response|null
     */
    private function executeCapabilityValidation(WP_REST_Request $request): ?\WP_REST_Response
    {
        $result = null;
        try {
            $role = $request->get_param('role');
            $menu_items = $request->get_param('menu_items');

            $validationError = $this->validateCapabilityParams($role);
            if ($validationError !== null) {
                return $validationError;
            }

            $role_obj = get_role($role);
            if (!$role_obj) {
                return ResponseService::error('Invalid role', null, 400);
            }
            $validated_items = $this->buildValidatedItems($menu_items ?? [], $role_obj);
            $result = ResponseService::success('Capabilities validated', [
                'role' => $role,
                'validated_items' => $validated_items
            ]);
        } catch (\Exception $e) {
            $result = ResponseService::error(
                'Failed to validate capabilities',
                ['error' => $e->getMessage()],
                500
            );
        }
        return $result;
    }

    /**
     * Validate role parameter. Returns error response or null if valid.
     *
     * @param string|null $role
     * @return \WP_REST_Response|null
     */
    private function validateCapabilityParams($role): ?\WP_REST_Response
    {
        if (empty($role)) {
            return ResponseService::error(self::MSG_ROLE_REQUIRED, null, 400);
        }
        $role_obj = get_role($role);
        if (!$role_obj) {
            return ResponseService::error('Invalid role', null, 400);
        }
        return null;
    }

    /**
     * Build validated items array from menu items and role object.
     *
     * @param array $menu_items
     * @param \WP_Role $role_obj
     * @return array
     */
    private function buildValidatedItems(array $menu_items, \WP_Role $role_obj): array
    {
        $validated_items = [];
        foreach ($menu_items as $item) {
            $capability = $item['capability'] ?? '';
            $validated_items[] = [
                'id' => $item['id'] ?? '',
                'has_capability' => !empty($capability) && isset($role_obj->capabilities[$capability])
            ];
        }
        return $validated_items;
    }

}
