<?php

/**
 * Admin Menu Handler
 *
 * Utilizes the MenuRegistry service to construct the WordPress admin menu
 * following the 11-item IA structure from ProRank_Combined_Reference_v1.md §3.1.
 *
 * @package ProRank\Admin
 * @since   0.1.0
 */

declare(strict_types=1);

namespace ProRank\SEO\Admin;

use ProRank\SEO\Plugin;
use ProRank\SEO\Core\MenuRegistry;
use ProRank\SEO\Core\ModuleManager;
use ProRank\SEO\Admin\Pages\SupportPage;
use ProRank\SEO\Admin\Pages\CwvDashboardPage;

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


/**
 * MenuHandler class
 *
 * Registers admin menu items with conditional visibility
 */


class MenuHandler {

    /**
     * Plugin instance
     *
     * @var Plugin
     */
    private Plugin $plugin;

    /**
     * Support page instance
     *
     * @var SupportPage|null
     */
    private ?SupportPage $support_account_page = null;


    /**
     * CWV Dashboard page instance
     *
     * @var CwvDashboardPage|null
     */
    private ?CwvDashboardPage $cwv_dashboard_page = null;

    /**
     * Constructor
     *
     * @param Plugin $plugin Plugin instance
     */
    public function __construct(Plugin $plugin) {
        $this->plugin = $plugin;

        // Initialize pages
        $this->support_account_page = new SupportPage();
        add_action('admin_enqueue_scripts', [$this->support_account_page, 'enqueue_assets']);

        // Analytics Settings is rendered as part of the main Analytics page React app
        // No separate page initialization needed

        $this->cwv_dashboard_page = new CwvDashboardPage();
        add_action('admin_enqueue_scripts', [$this->cwv_dashboard_page, 'enqueue_assets']);
    }

    /**
     * Check if premium plugin is active
     *
     * @return bool
     */
    private function is_premium_active(): bool {
        if (defined('PRORANK_PREMIUM_VERSION')) {
            return true;
        }

        if (!function_exists('is_plugin_active')) {
            require_once ABSPATH . 'wp-admin/includes/plugin.php';
        }

        if (!function_exists('is_plugin_active')) {
            return false;
        }

        return is_plugin_active('prorank-seo-premium/prorank-seo.php')
            || is_plugin_active('prorank-seo-premium/prorank-seo-premium.php');
    }

    /**
     * Check if the upgrade menu should be shown
     *
     * @return bool
     */
    private function should_show_upgrade_menu(): bool {
        return true;
    }

    /**
     * Initialize menu registration
     *
     * @return void
     */
    public function init(): void {
        // Redirect legacy internal-linking page slugs before admin page access checks.
        add_action('admin_init', [$this, 'maybe_redirect_legacy_link_map_slug'], 1);
        add_action('admin_init', [$this, 'maybe_redirect_legacy_bulk_edit_route'], 1);

        // Handle OAuth callbacks early
        add_action('admin_init', [$this, 'handle_oauth_callbacks']);

        // Remove third-party admin notices on ProRank pages before they render
        add_action('current_screen', [$this, 'suppress_third_party_notices'], 0);

        // Hide third-party admin notices on ProRank pages
        add_action('admin_head', [$this, 'hide_third_party_notices'], 1);

        $is_premium_installed = $this->is_premium_active();

        $menu_registry = $this->plugin->menus();

        // Register top-level ProRank SEO menu
        $menu_registry->register_top_level(
            'prorank-seo',
            'ProRank SEO Dashboard',
            'ProRank SEO',
            'manage_options',
            [$this, 'render_dashboard_page'],
            $this->get_menu_icon(),
            null, // No condition for main menu
            26
        );

        // 1. Dashboard (always visible as main page)
        // Register with same slug as parent to replace auto-generated submenu
        $menu_registry->register_sub_menu(
            'prorank-seo',
            'prorank-seo', // Same as parent for first item
            'Dashboard',
            'Dashboard',
            'manage_options',
            [$this, 'render_dashboard_page'],
            null,
            0 // Position 0 to ensure it's first
        );

        // 2. On-Page SEO (FREE)
        $menu_registry->register_sub_menu(
            'prorank-seo',
            'prorank-on-page-seo',
            'On-Page SEO',
            'On-Page SEO',
            'manage_options',
            [$this, 'render_on_page_seo_page'],
            null, // No special conditions for free tier
            10
        );

        // Hidden: Bulk Edit page (only accessible via posts list bulk action)
        // Register directly with WordPress using null parent to avoid menu entry
        add_submenu_page(
            null, // null parent = no menu entry
            __('Bulk Edit SEO', 'prorank-seo'),
            __('Bulk Edit SEO', 'prorank-seo'),
            'edit_posts',
            'prorank-bulk-edit',
            [$this, 'render_bulk_edit_page']
        );

        // Hidden route so upgrade links always resolve even when the sidebar menu item is hidden.
        add_submenu_page(
            null,
            __('Upgrade to Pro', 'prorank-seo'),
            __('Upgrade to Pro', 'prorank-seo'),
            'manage_options',
            'prorank-upgrade',
            [$this, 'render_upgrade_page']
        );

        // Hidden legacy aliases and Internal Linking — all gated together
        // when a competing linking plugin (e.g. Link Whisper) is active.
        $il_detector = new \ProRank\SEO\Core\Compatibility\CompetitorDetector();
        if (!$il_detector->should_enable_internal_linking_safe_mode()) {
            add_submenu_page(
                null,
                __('Link Map', 'prorank-seo'),
                __('Link Map', 'prorank-seo'),
                'manage_options',
                'prorank-link-map',
                [$this, 'redirect_legacy_link_map_page']
            );
            add_submenu_page(
                null,
                __('Visual Link Map', 'prorank-seo'),
                __('Visual Link Map', 'prorank-seo'),
                'manage_options',
                'prorank-visual-link-map',
                [$this, 'redirect_legacy_link_map_page']
            );
        }
        if (!$il_detector->should_enable_internal_linking_safe_mode()) {
            $menu_registry->register_sub_menu(
                'prorank-seo',
                'prorank-internal-linking',
                'Internal Linking',
                'Internal Linking',
                'manage_options',
                [$this, 'render_internal_linking_page'],
                null,
                15
            );
        }

        // 4. Performance (FREE)
        $menu_registry->register_sub_menu(
            'prorank-seo',
            'prorank-performance',
            'Performance',
            'Performance',
            'manage_options',
            [$this, 'render_performance_page'],
            null, // Base features are free
            20
        );

        // 5. Technical SEO (FREE)
        $menu_registry->register_sub_menu(
            'prorank-seo',
            'prorank-technical-seo',
            'Technical SEO',
            'Technical SEO',
            'manage_options',
            [$this, 'render_technical_seo_page'],
            null, // Base features are free
            30
        );

        // 6. Site Audit & Tools (FREE)
        $menu_registry->register_sub_menu(
            'prorank-seo',
            'prorank-site-audit',
            'Site Audit & Tools',
            'Site Audit & Tools',
            'manage_options',
            [$this, 'render_site_audit_page'],
            null, // Base features are free
            40
        );

        // 7. Support & Resources (FREE)
        $menu_registry->register_sub_menu(
            'prorank-seo',
            'prorank-support',
            'Support & Resources',
            'Support & Resources',
            'manage_options',
            [$this->support_account_page, 'render'],
            null, // Always visible
            50
        );

        // Upgrade menu (FREE)
        if ($this->should_show_upgrade_menu()) {
            $menu_registry->register_sub_menu(
                'prorank-seo',
                'prorank-upgrade',
                'Upgrade to Pro',
                'Upgrade to Pro',
                'manage_options',
                [$this, 'render_upgrade_page'],
                null,
                110
            );
        }

        // Actually register all menus with WordPress
        $menu_registry->register_menus();

        // Remove hidden utility submenus to avoid blank rows in the sidebar.
        $this->remove_hidden_submenus();
    }

    /**
     * Remove hidden submenu items from the WordPress sidebar.
     *
     * @return void
     */
    private function remove_hidden_submenus(): void {
        remove_submenu_page('prorank-seo', 'prorank-bulk-edit');
    }

    /**
     * Get menu icon
     *
     * Returns the ProRank favicon as a data URI for WordPress admin menu.
     *
     * @return string
     */
    private function get_menu_icon(): string {
        $icon_paths = [
            PRORANK_PLUGIN_DIR . 'assets/prorank.svg',
            PRORANK_PLUGIN_DIR . 'prorank.svg',
        ];

        foreach ($icon_paths as $icon_path) {
            if (!file_exists($icon_path)) {
                continue;
            }

            $svg = file_get_contents($icon_path);
            if ($svg !== false) {
                return 'data:image/svg+xml;base64,' . base64_encode($svg);
            }
        }

        // Fallback: simple hexagonal icon.
        $fallback = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"><path d="M12 2L4 6.5V17.5L12 22L20 17.5V6.5L12 2Z" fill="#a7aaad" fill-opacity="0.15" stroke="#a7aaad" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>';
        return 'data:image/svg+xml;base64,' . base64_encode( $fallback );
    }

    /**
     * Render dashboard page
     *
     * @return void
     */
    public function render_dashboard_page(): void {
        echo '<div id="prorank-seo-dashboard" class="wrap prorank-seo-admin-page">';
        echo '<h1>' . esc_html('ProRank SEO Dashboard') . '</h1>';
        // Add the container that React app is looking for
        echo '<div class="prorank-admin-container" id="prorank-admin-root">';
        echo '<!-- React component will mount here -->';
        echo '<noscript>' . esc_html('JavaScript is required to view this page.') . '</noscript>';
        echo '</div>';
        echo '</div>';
    }

    /**
     * Render On-Page SEO page
     *
     * @return void
     */
    public function render_on_page_seo_page(): void {
        echo '<div id="prorank-seo-on-page" class="wrap prorank-seo-admin-page prorank-on-page-seo-page">';
        echo '<h1>' . esc_html('On-Page SEO') . '</h1>';
        // Add the container that React app is looking for
        echo '<div class="prorank-admin-container" id="prorank-admin-root">';
        echo '<!-- React component will mount here -->';
        echo '<noscript>' . esc_html('JavaScript is required to view this page.') . '</noscript>';
        echo '</div>';
        echo '</div>';
    }

    /**
     * Render Bulk Edit SEO page
     *
     * @return void
     */
    public function render_bulk_edit_page(): void {
        echo '<div class="wrap prorank-seo-admin-page prorank-bulk-edit-page">';
        echo '<div class="prorank-admin-container" id="prorank-admin-root">';
        echo '<!-- React component will mount here -->';
        echo '<noscript>' . esc_html('JavaScript is required to view this page.') . '</noscript>';
        echo '</div>';
        echo '</div>';
    }

    /**
     * Render Performance page
     *
     * @return void
     */
    public function render_performance_page(): void {
        echo '<div id="prorank-performance" class="wrap prorank-seo-admin-page">';
        echo '<h1>' . esc_html('Performance') . '</h1>';
        // Add the container that React app is looking for
        echo '<div class="prorank-admin-container" id="prorank-admin-root">';
        echo '<!-- React component will mount here -->';
        echo '<noscript>' . esc_html('JavaScript is required to view this page.') . '</noscript>';
        echo '</div>';
        echo '</div>';
    }

    /**
     * Render Technical SEO page
     *
     * @return void
     */
    public function render_technical_seo_page(): void {
        echo '<div id="prorank-technical-seo" class="wrap prorank-seo-admin-page prorank-technical-seo-page">';
        echo '<h1>' . esc_html('Technical SEO') . '</h1>';
        // Add the container that React app is looking for
        echo '<div class="prorank-admin-container" id="prorank-admin-root">';
        echo '<!-- React component will mount here -->';
        echo '<noscript>' . esc_html('JavaScript is required to view this page.') . '</noscript>';
        echo '</div>';

        echo '</div>';
    }

    /**
     * Render Internal Linking page
     *
     * @return void
     */
    public function render_internal_linking_page(): void {
        echo '<div id="prorank-internal-linking" class="wrap prorank-seo-admin-page prorank-internal-linking-page">';
        echo '<h1>' . esc_html('Internal Linking') . '</h1>';
        echo '<div class="prorank-admin-container" id="prorank-admin-root">';
        echo '<!-- React component will mount here -->';
        echo '<noscript>' . esc_html('JavaScript is required to view this page.') . '</noscript>';
        echo '</div>';

        echo '</div>';
    }

    /**
     * Redirect legacy Link Map page slugs to the current Internal Linking tab route.
     *
     * @return void
     */
    public function redirect_legacy_link_map_page(): void {
        $target = admin_url('admin.php?page=prorank-internal-linking#?tab=visual-map');
        wp_safe_redirect($target);
        exit;
    }

    /**
     * Redirect legacy Link Map slugs even when WordPress doesn't register a menu callback.
     *
     * This avoids "Sorry, you are not allowed to access this page" for old deep links.
     *
     * @return void
     */
    public function maybe_redirect_legacy_link_map_slug(): void {
        if (!is_admin()) {
            return;
        }

        $page = sanitize_key(prorank_get_query_var('page'));
        if ($page === '') {
            return;
        }

        if (!in_array($page, ['prorank-link-map', 'prorank-visual-link-map'], true)) {
            return;
        }

        // Don't redirect to internal-linking page when a competitor is active.
        $il_detector = new \ProRank\SEO\Core\Compatibility\CompetitorDetector();
        if ($il_detector->should_enable_internal_linking_safe_mode()) {
            return;
        }

        $this->redirect_legacy_link_map_page();
    }

    /**
     * Redirect the old On-Page SEO bulk-edit tab route to the dedicated hidden page.
     *
     * @return void
     */
    public function maybe_redirect_legacy_bulk_edit_route(): void {
        if (!is_admin()) {
            return;
        }

        $page = sanitize_key(prorank_get_query_var('page'));
        $tab = sanitize_key(prorank_get_query_var('tab'));

        if ($page !== 'prorank-on-page-seo' || $tab !== 'bulk-edit') {
            return;
        }

        $target_args = [
            'page' => 'prorank-bulk-edit',
        ];

        $post_ids = sanitize_text_field(prorank_get_query_var('post_ids'));
        if ($post_ids !== '') {
            $target_args['post_ids'] = $post_ids;
        }

        $post_type = sanitize_key(prorank_get_query_var('post_type'));
        if ($post_type !== '') {
            $target_args['post_type'] = $post_type;
        }

        wp_safe_redirect(add_query_arg($target_args, admin_url('admin.php')));
        exit;
    }


    /**
     * Handle OAuth callbacks early in admin_init
     *
     * @return void
     */
    public function handle_oauth_callbacks(): void {
        // Free build does not handle premium OAuth flows.
    }

    /**
     * Render Upgrade page
     *
     * @return void
     */
    public function render_upgrade_page(): void {
        $pricing_url = 'https://prorank.io/pricing';
        echo '<div class="wrap prorank-seo-admin-page">';
        echo '<h1>' . esc_html__('Upgrade to ProRank Pro', 'prorank-seo') . '</h1>';
        echo '<div class="card" style="max-width:760px;padding:20px;">';
        echo '<p>' . esc_html__('Unlock AI tools, advanced performance optimization, cloud image credits, and premium analytics.', 'prorank-seo') . '</p>';
        echo '<p><a class="button button-primary" target="_blank" href="' . esc_url($pricing_url) . '">' . esc_html__('View Plans', 'prorank-seo') . '</a></p>';
        echo '<p style="color:#6b7280;font-size:12px;margin-top:12px;">' . esc_html__('Need Premium features? Install ProRank Premium on this site.', 'prorank-seo') . '</p>';
        echo '</div>';
        echo '</div>';
    }

    /**
     * Render Site Audit & Tools page
     *
     * @return void
     */
    public function render_site_audit_page(): void {
        echo '<div id="prorank-site-audit" class="wrap prorank-seo-admin-page prorank-site-audit-page">';
        echo '<div class="prorank-admin-container" id="prorank-admin-root">';
        echo '<noscript>' . esc_html('JavaScript is required to view this page.') . '</noscript>';
        echo '</div>';
        echo '</div>';
    }

    /**
     * Render Support page
     *
     * @return void
     */
    public function render_support_page(): void {
        echo '<div id="prorank-support" class="wrap prorank-seo-admin-page">';
        echo '<h1>' . esc_html__('Support', 'prorank-seo') . '</h1>';
        // Add the container that React app is looking for
        echo '<div class="prorank-admin-container" id="prorank-admin-root">';
        echo '<!-- React component will mount here -->';
        echo '<noscript>' . esc_html('JavaScript is required to view this page.') . '</noscript>';
        echo '</div>';
        echo '</div>';
    }

    /**
     * Render Import/Export page
     *
     * @return void
     */
    public function render_import_export_page(): void {
        // Always render the React container - React handles locked state per feature
        echo '<div id="prorank-seo-import-export" class="wrap prorank-seo-admin-page prorank-import-export-page">';
        echo '<div class="prorank-admin-container" id="prorank-admin-root"></div>';
        echo '</div>';
    }

    /**
     * Hide third-party admin notices on ProRank SEO pages
     *
     * Prevents other plugins/themes from displaying their notices
     * on top of our plugin interface for a cleaner UX.
     *
     * @return void
     */
    public function hide_third_party_notices(): void {
        // Only run on ProRank admin pages
        $current_page = prorank_get_query_var('page');
        if ($current_page === '' || strpos($current_page, 'prorank') !== 0) {
            return;
        }

        // Output CSS to hide all admin notices except our own
        echo '<style>
            /* Hide all third-party admin notices on ProRank pages */
            .prorank-seo-admin-page ~ .notice:not(.prorank-notice),
            .prorank-seo-admin-page ~ .update-nag,
            .prorank-seo-admin-page ~ .updated:not(.prorank-notice),
            .prorank-seo-admin-page ~ .error:not(.prorank-notice),
            .prorank-seo-admin-page ~ .notice-warning:not(.prorank-notice),
            .prorank-seo-admin-page ~ .notice-error:not(.prorank-notice),
            .prorank-seo-admin-page ~ .notice-info:not(.prorank-notice),
            .prorank-seo-admin-page ~ .notice-success:not(.prorank-notice),
            #wpbody-content > .notice:not(.prorank-notice),
            #wpbody-content > .update-nag,
            #wpbody-content > .updated:not(.prorank-notice),
            #wpbody-content > .error:not(.prorank-notice),
            #wpbody-content > div.notice:not(.prorank-notice),
            /* Specifically hide common plugin/theme notices */
            .td-admin-notice,
            .tagdiv-admin-notice,
            [class*="td-"][class*="notice"],
            /* Generic third-party notice patterns */
            .wrap > .notice:not(.prorank-notice):not(:has(+ .prorank-seo-admin-page)):first-child,
            .wrap > .update-nag:first-child,
            /* Hide notices that appear before our content */
            body.prorank-seo_page_prorank-seo #wpbody-content > .notice:not(.prorank-notice),
            body.prorank-seo_page_prorank-performance #wpbody-content > .notice:not(.prorank-notice),
            body.prorank-seo_page_prorank-on-page-seo #wpbody-content > .notice:not(.prorank-notice),
            body.prorank-seo_page_prorank-technical-seo #wpbody-content > .notice:not(.prorank-notice),
            body.prorank-seo_page_prorank-site-audit #wpbody-content > .notice:not(.prorank-notice),
            body.prorank-seo_page_prorank-support #wpbody-content > .notice:not(.prorank-notice),
            body.prorank-seo_page_prorank-import-export #wpbody-content > .notice:not(.prorank-notice),
            body[class*="prorank-seo_page_prorank"] #wpbody-content > .notice:not(.prorank-notice),
            body[class*="prorank-seo_page_prorank"] #wpbody-content > .update-nag,
            body[class*="prorank-seo_page_prorank"] #wpbody-content > .updated:not(.prorank-notice),
            body[class*="prorank-seo_page_prorank"] #wpbody-content > .error:not(.prorank-notice) {
                display: none !important;
            }
        </style>';
    }

    /**
     * Suppress third-party admin notices on ProRank pages.
     *
     * @param \WP_Screen|null $screen Current screen (provided by hook).
     * @return void
     */
    public function suppress_third_party_notices($screen = null): void {
        if (!$this->is_prorank_screen($screen)) {
            return;
        }

        $hooks = [
            'admin_notices',
            'all_admin_notices',
            'network_admin_notices',
            'user_admin_notices',
        ];

        foreach ($hooks as $hook) {
            $this->remove_non_prorank_callbacks($hook);
        }
    }

    /**
     * Check whether the current admin screen is a ProRank page.
     *
     * @param \WP_Screen|null $screen
     * @return bool
     */
    private function is_prorank_screen($screen = null): bool {
        if (!$screen && function_exists('get_current_screen')) {
            $screen = get_current_screen();
        }

        if ($screen && isset($screen->id) && strpos((string) $screen->id, 'prorank') !== false) {
            return true;
        }

        if ($screen && isset($screen->base) && strpos((string) $screen->base, 'prorank') !== false) {
            return true;
        }

        return false;
    }

    /**
     * Remove non-ProRank callbacks from a notice hook.
     *
     * @param string $hook
     * @return void
     */
    private function remove_non_prorank_callbacks(string $hook): void {
        global $wp_filter;

        if (empty($wp_filter[$hook]) || !($wp_filter[$hook] instanceof \WP_Hook)) {
            return;
        }

        $to_remove = [];

        foreach ($wp_filter[$hook]->callbacks as $priority => $callbacks) {
            foreach ($callbacks as $callback) {
                $function = $callback['function'] ?? null;
                if (!$this->is_prorank_callback($function)) {
                    $to_remove[] = [$hook, $function, $priority];
                }
            }
        }

        foreach ($to_remove as $removal) {
            [$hook_name, $function, $priority] = $removal;
            if ($function !== null) {
                remove_action($hook_name, $function, $priority);
            }
        }
    }

    /**
     * Determine whether a callback belongs to ProRank.
     *
     * @param mixed $callback
     * @return bool
     */
    private function is_prorank_callback($callback): bool {
        if ($callback === null) {
            return false;
        }

        if (is_string($callback)) {
            return strpos($callback, 'prorank') !== false;
        }

        if (is_array($callback)) {
            $target = $callback[0] ?? null;
            $class = '';
            if (is_object($target)) {
                $class = get_class($target);
            } elseif (is_string($target)) {
                $class = $target;
            }

            if ($class !== '' && strpos($class, 'ProRank\\SEO\\') === 0) {
                return true;
            }

            return $this->is_prorank_reflection_target($target);
        }

        if ($callback instanceof \Closure) {
            return $this->is_prorank_reflection_target($callback);
        }

        if (is_object($callback) && method_exists($callback, '__invoke')) {
            return $this->is_prorank_reflection_target($callback);
        }

        return false;
    }

    /**
     * Check callback file location to confirm it belongs to ProRank.
     *
     * @param mixed $target
     * @return bool
     */
    private function is_prorank_reflection_target($target): bool {
        try {
            if ($target instanceof \Closure) {
                $ref = new \ReflectionFunction($target);
                return $this->is_prorank_path($ref->getFileName());
            }

            if (is_object($target)) {
                $ref = new \ReflectionClass($target);
                return $this->is_prorank_path($ref->getFileName());
            }

            if (is_string($target) && class_exists($target)) {
                $ref = new \ReflectionClass($target);
                return $this->is_prorank_path($ref->getFileName());
            }
        } catch (\ReflectionException $e) {
            return false;
        }

        return false;
    }

    /**
     * Determine if a file path belongs to ProRank plugin directories.
     *
     * @param string|null $file
     * @return bool
     */
    private function is_prorank_path(?string $file): bool {
        if (!$file) {
            return false;
        }

        $path = str_replace('\\', '/', $file);
        $markers = [
            '/prorank-seo/',
            '/prorank-seo/',
            '/free/',
            '/premium/',
        ];

        foreach ($markers as $marker) {
            if (strpos($path, $marker) !== false) {
                return true;
            }
        }

        return false;
    }


}
