<?php
/**
 * Menu Translation class - handles WordPress menu translations
 * 
 * @package LangForge
 */

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

// IDE hints for autoloaded classes
if (false) {
    class LF_Core {}
    class LF_Post_Translation {}
}

class LF_Menu_Translation {
    
    private static $instance = null;
    
    public static function instance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    private function __construct() {
        $this->init_hooks();
    }
    
    private function init_hooks() {
        // Add language selector to menu locations
        add_action('admin_init', [$this, 'register_menu_locations']);
        
        // Filter nav menu based on language
        add_filter('wp_nav_menu_args', [$this, 'filter_menu_args']);
        
        // Add language meta to menu items
        add_action('wp_nav_menu_item_custom_fields', [$this, 'add_menu_item_fields'], 10, 4);
        add_action('wp_update_nav_menu_item', [$this, 'save_menu_item_fields'], 10, 3);
        
        // Filter menu items to show only current language
        add_filter('wp_get_nav_menu_items', [$this, 'filter_menu_items'], 10, 3);

        // Fix current-menu-item class for translated front page on language root URLs 
        add_filter('wp_nav_menu_objects', [$this, 'fix_front_page_menu_active'], 10, 2);

        // Make custom-link / taxonomy menu items language-aware (Home link, etc.)
        add_filter('wp_nav_menu_objects', [$this, 'localize_menu_urls'], 20, 2);
    }

    /**
 * Carry the active language into nav-menu links.
 *
 * LangForge already rewrites post & page permalinks (LF_Post_Translation::
 * filter_permalink), but custom links — e.g. a "Home" item pointing at
 * home_url — and taxonomy archives keep the bare default-language URL, so
 * clicking them silently drops the visitor back to the default language.
 * Localize every internal, non-post/page item to the current language.
 */
    public function localize_menu_urls($items, $args) {
        if (is_admin() || empty($items)) {
            return $items;
        }
        $core    = LF_Core::instance();
        $current = $core->get_current_language();
        if (!$current || $current === $core->get_default_language()) {
            return $items; // default language already uses clean URLs
        }
        foreach ($items as $item) {
            // Post/page permalinks are localized by filter_permalink; skip them.
            if (isset($item->type) && $item->type === 'post_type') {
                continue;
            }
            if (empty($item->url) || $item->url === '#') {
                continue;
            }
            $item->url = $core->localize_url($item->url, $current);
        }
        return $items;
    }

    /**
 * Register language-specific menu locations
 */
    public function register_menu_locations() {
        $languages = LF_Core::instance()->get_active_languages();
        $theme_locations = get_registered_nav_menus();
        
        foreach ($theme_locations as $location => $description) {
            foreach ($languages as $code => $lang) {
                // Register language-specific locations
                // Theme can use: register_nav_menu('primary-en', 'Primary Menu (English)')
            }
        }
    }
    
    /**
 * Filter menu arguments to use language-specific menu
 */
    public function filter_menu_args($args) {
        if (is_admin()) {
            return $args;
        }
        
        $current_lang = LF_Core::instance()->get_current_language();
        $default_lang = LF_Core::instance()->get_default_language();
        
        // Check if there's a language-specific menu assigned
        if (isset($args['theme_location']) && !empty($args['theme_location'])) {
            $location = $args['theme_location'];
            $lang_location = $location . '-' . $current_lang;
            
            $locations = get_nav_menu_locations();
            
            // If language-specific location exists and has a menu, use it
            if (isset($locations[$lang_location]) && $locations[$lang_location]) {
                $args['theme_location'] = $lang_location;
            }
        }
        
        // Filter by menu language meta
        if (isset($args['menu']) && is_numeric($args['menu'])) {
            // Direct menu ID specified
        }
        
        return $args;
    }
    
    /**
 * Add language field to menu items
 */
    public function add_menu_item_fields($item_id, $item, $depth, $args) {
        $languages = LF_Core::instance()->get_active_languages();
        $item_lang = get_post_meta($item_id, '_lf_menu_item_language', true);
        ?>
        <p class="field-lf-language description description-wide">
            <label for="edit-menu-item-lf-language-<?php echo esc_attr($item_id); ?>">
                <?php esc_html_e('Show for language', 'langforge'); ?><br>
                <select id="edit-menu-item-lf-language-<?php echo esc_attr($item_id); ?>"
                        class="widefat"
                        name="menu-item-lf-language[<?php echo esc_attr($item_id); ?>]">
                    <option value=""><?php esc_html_e('All languages', 'langforge'); ?></option>
                    <?php foreach ($languages as $code => $lang): ?>
                        <option value="<?php echo esc_attr($code); ?>" <?php selected($item_lang, $code); ?>>
                            <?php echo esc_html($lang['native_name']); ?>
                        </option>
                    <?php endforeach; ?>
                </select>
            </label>
        </p>
        <?php
    }
    
    /**
 * Save menu item language field
 */
    public function save_menu_item_fields($menu_id, $menu_item_db_id, $args) {
        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified by WP core nav-menu edit screen (wp_update_nav_menu_item hook).
        if (isset($_POST['menu-item-lf-language'][$menu_item_db_id])) {
            $lang = sanitize_text_field(wp_unslash($_POST['menu-item-lf-language'][$menu_item_db_id])); // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified by core nav-menu screen (wp_update_nav_menu_item hook)
            update_post_meta($menu_item_db_id, '_lf_menu_item_language', $lang);
        }
    }
    
    /**
 * Filter menu items by language
 */
    public function filter_menu_items($items, $menu, $args) {
        if (is_admin()) {
            return $items;
        }
        
        $current_lang = LF_Core::instance()->get_current_language();
        
        $filtered_items = [];
        foreach ($items as $item) {
            $item_lang = get_post_meta($item->ID, '_lf_menu_item_language', true);
            
            // Show if no language set (show for all) or matches current
            if (empty($item_lang) || $item_lang === $current_lang) {
                // Update URL if item links to a translated post
                if ($item->type === 'post_type') {
                    $translation_id = LF_Post_Translation::instance()->get_translation($item->object_id, $current_lang);
                    if ($translation_id && $translation_id != $item->object_id) {
                        $item->url = get_permalink($translation_id);
                        $item->title = get_the_title($translation_id);
                    }
                }
                
                $filtered_items[] = $item;
            }
        }
        
        return $filtered_items;
    }
    
    /**
 * Add menu translation admin page
 */
    public function add_menu_translation_page() {
        add_submenu_page(
            'lf-settings',
            __('Menu Translation', 'langforge'),
            __('Menus', 'langforge'),
            'manage_options',
            'lf-menus',
            [$this, 'render_menu_page']
        );
    }
    
    /**
 * Render menu translation page
 */
    public function render_menu_page() {
        // Handle form submission BEFORE rendering so dropdowns show updated values
        $saved = false;
        if (isset($_POST['lf_save_menus']) && wp_verify_nonce(isset($_POST['lf_menu_nonce']) ? sanitize_text_field(wp_unslash($_POST['lf_menu_nonce'])) : '', 'lf_menu_settings')) {
            $this->save_menu_locations(isset($_POST['lf_menu_locations']) ? wp_unslash($_POST['lf_menu_locations']) : []); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Nested array sanitized per-field in save_menu_locations (keys built into theme-mod keys, values cast to int).
            $saved = true;
        }

        $languages = LF_Core::instance()->get_active_languages();
        $menus = wp_get_nav_menus();
        ?>
        <div class="wrap">
            <?php LF_Admin_Tabs::render('lf-menus'); ?>
            <h1><?php esc_html_e('Menu Translation', 'langforge'); ?><?php Forge_Docs_Link::render('langforge', 'translating-menus', __('Menu translation', 'langforge'), __('Assign menus per language or set visibility on menu items.', 'langforge')); ?></h1>

            <?php if ($saved): ?>
                <div class="notice notice-success"><p><?php esc_html_e('Menu settings saved.', 'langforge'); ?></p></div>
            <?php endif; ?>

            <p><?php esc_html_e('Configure which menus to display for each language. You can either:', 'langforge'); ?></p>
            <ul>
                <li><?php esc_html_e('Create separate menus for each language and assign them below', 'langforge'); ?></li>
                <li><?php esc_html_e('Use a single menu and set language visibility on individual menu items', 'langforge'); ?></li>
            </ul>

            <form method="post" action="">
                <?php wp_nonce_field('lf_menu_settings', 'lf_menu_nonce'); ?>

                <table class="widefat">
                    <thead>
                        <tr>
                            <th><?php esc_html_e('Menu Location', 'langforge'); ?></th>
                            <?php foreach ($languages as $code => $lang): ?>
                                <th><?php echo esc_html($lang['native_name']); ?></th>
                            <?php endforeach; ?>
                        </tr>
                    </thead>
                    <tbody>
                        <?php
                        $locations = get_registered_nav_menus();
                        $current_locations = get_nav_menu_locations();

                        foreach ($locations as $location => $description):
                            // Skip language-specific locations
                            if (preg_match('/-(' . implode('|', array_keys($languages)) . ')$/', $location)) {
                                continue;
                            }
                        ?>
                        <tr>
                            <td><strong><?php echo esc_html($description); ?></strong></td>
                            <?php foreach ($languages as $code => $lang):
                                $lang_location = $location . '-' . $code;
                                $selected_menu = isset($current_locations[$lang_location]) ? $current_locations[$lang_location] : '';
                            ?>
                            <td>
                                <select name="lf_menu_locations[<?php echo esc_attr($location); ?>][<?php echo esc_attr($code); ?>]">
                                    <option value=""><?php esc_html_e('— Select Menu —', 'langforge'); ?></option>
                                    <?php foreach ($menus as $menu): ?>
                                        <option value="<?php echo esc_attr($menu->term_id); ?>" <?php selected($selected_menu, $menu->term_id); ?>>
                                            <?php echo esc_html($menu->name); ?>
                                        </option>
                                    <?php endforeach; ?>
                                </select>
                            </td>
                            <?php endforeach; ?>
                        </tr>
                        <?php endforeach; ?>
                    </tbody>
                </table>

                <p class="submit">
                    <input type="submit" name="lf_save_menus" class="button button-primary" value="<?php esc_attr_e('Save Menu Settings', 'langforge'); ?>">
                </p>
            </form>
        </div>
        <?php
    }
    
    /**
 * Save menu locations
 */
    private function save_menu_locations($locations) {
        $current = get_nav_menu_locations();
        
        foreach ((array) $locations as $location => $languages) {
            foreach ((array) $languages as $lang => $menu_id) {
                $lang_location = sanitize_key($location) . '-' . sanitize_key($lang);
                if ($menu_id) {
                    $current[$lang_location] = (int) $menu_id;
                } else {
                    unset($current[$lang_location]);
                }
            }
        }
        
        set_theme_mod('nav_menu_locations', $current);
    }
    
    /**
 * Fix current-menu-item class for translated front page on language root URLs.
 *
 * When visiting /en/ (language root), WordPress may not recognize the translated
 * front page as the "current" page for menu highlighting. This filter adds
 * current-menu-item / current_page_item classes to the Home menu item when
 * the current page is the translated front page.
 *
 * @since 1.0.0 
 */
    public function fix_front_page_menu_active($items, $args) {
        if (is_admin()) {
            return $items;
        }

        // Only act on front page or the blog index
        if (!is_front_page() && !is_home()) {
            return $items;
        }

        $current_lang = LF_Core::instance()->get_current_language();
        $default_lang = LF_Core::instance()->get_default_language();
        if ($current_lang === $default_lang) {
            return $items;
        }

        // figure out which page WP would highlight on the default
        // language: page_on_front for the static front page, page_for_posts
        // for the blog index. Bypass our own translate_front_page_id filter so
        // we get the *original* (default-language) IDs.
        $core   = LF_Core::instance();
        $option = (is_home() && !is_front_page()) ? 'page_for_posts' : 'page_on_front';
        remove_filter('option_' . $option, [$core, 'translate_front_page_id']);
        $original_id = (int) get_option($option);
        add_filter('option_' . $option, [$core, 'translate_front_page_id']);

        if (!$original_id) {
            return $items;
        }
        // For the front-page case we still need show_on_front=page; the blog
        // case (page_for_posts) doesn't require that.
        if ($option === 'page_on_front' && get_option('show_on_front') !== 'page') {
            return $items;
        }

        $translation_id = LF_Post_Translation::instance()->get_translation($original_id, $current_lang);
        if (!$translation_id) {
            return $items;
        }

        // Check if any item already has current-menu-item — if so, WP handled it
        foreach ($items as $item) {
            if (in_array('current-menu-item', $item->classes, true)) {
                return $items;
            }
        }

        // Find the menu item that points to the original page or its translation
        foreach ($items as &$item) {
            if ($item->type !== 'post_type') {
                continue;
            }
            $obj_id = (int) $item->object_id;
            if ($obj_id === $original_id || $obj_id === $translation_id) {
                $item->classes[] = 'current-menu-item';
                $item->classes[] = 'current_page_item';
                break;
            }
        }

        return $items;
    }

    /**
 * Get translated menu
 */
    public function get_menu_for_language($location, $language = null) {
        if (!$language) {
            $language = LF_Core::instance()->get_current_language();
        }
        
        $locations = get_nav_menu_locations();
        $lang_location = $location . '-' . $language;
        
        if (isset($locations[$lang_location]) && $locations[$lang_location]) {
            return $locations[$lang_location];
        }
        
        // Fall back to default location
        return isset($locations[$location]) ? $locations[$location] : false;
    }
}
