<?php
/**
 * Language-aware navigation menu location helpers.
 *
 * @package WPR_Translate
 */

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

if ( ! function_exists( 'wpr_translation_get_nav_menu_locations_option_name' ) ) {
    /**
     * Returns the option name storing language-specific menu locations.
     *
     * @return string
     */
    function wpr_translation_get_nav_menu_locations_option_name() {
        return 'wpr_translate_nav_menu_locations';
    }
}

if ( ! function_exists( 'wpr_translation_normalize_nav_menu_locations_map' ) ) {
    /**
     * Sanitizes a nav menu locations map keyed by language and location.
     *
     * @param mixed $locations Raw location assignments.
     *
     * @return array<string, array<string, int>>
     */
    function wpr_translation_normalize_nav_menu_locations_map( $locations ) {
        if ( ! is_array( $locations ) ) {
            // Return an empty map for invalid input.
            return array();
        }

        $sanitized = array();

        foreach ( $locations as $location => $languages ) {
            $location_key = sanitize_key( $location );

            if ( '' === $location_key || ! is_array( $languages ) ) {
                // Skip invalid location entries.
                continue;
            }

            $language_map = array();

            foreach ( $languages as $code => $menu_id ) {
                $language_code = strtolower( sanitize_key( $code ) );
                $menu_value    = absint( $menu_id );

                if ( '' === $language_code || $menu_value <= 0 ) {
                    // Skip invalid language assignments.
                    continue;
                }

                $language_map[ $language_code ] = $menu_value;
            }

            if ( ! empty( $language_map ) ) {
                // Keep only locations that have valid language mappings.
                $sanitized[ $location_key ] = $language_map;
            }
        }

        return $sanitized;
    }
}

if ( ! function_exists( 'wpr_translation_get_stored_nav_menu_locations' ) ) {
    /**
     * Retrieves the stored nav menu location assignments grouped by language.
     *
     * @return array<string, array<string, int>>
     */
    function wpr_translation_get_stored_nav_menu_locations() {
        // Read the stored menu location map from options.
        $stored = get_option( wpr_translation_get_nav_menu_locations_option_name(), array() );

        return wpr_translation_normalize_nav_menu_locations_map( $stored );
    }
}

if ( ! function_exists( 'wpr_translation_update_nav_menu_locations_storage' ) ) {
    /**
     * Persists the provided nav menu locations map.
     *
     * @param array<string, array<string, int>> $locations Location assignments.
     */
    function wpr_translation_update_nav_menu_locations_storage( $locations ) {
        if ( empty( $locations ) ) {
            // Remove the option when no locations remain.
            delete_option( wpr_translation_get_nav_menu_locations_option_name() );
            return;
        }

        // Persist the normalized locations map.
        update_option( wpr_translation_get_nav_menu_locations_option_name(), $locations );
    }
}

if ( ! function_exists( 'wpr_translation_get_requested_nav_menu_language_code' ) ) {
    /**
     * Determines the requested nav menu language for the current request.
     *
     * @return string
     */
    function wpr_translation_get_requested_nav_menu_language_code() {
        $language = '';

        if ( isset( $_POST['wpr_menu_language'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
            // Read language from the submitted menu form when present.
            $language = sanitize_key( wp_unslash( $_POST['wpr_menu_language'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
        }

        if ( '' === $language && isset( $_GET['wpr_language'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            // Fall back to the query parameter when provided.
            $language = sanitize_key( wp_unslash( $_GET['wpr_language'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        }

        if ( '' === $language && is_admin() ) {
            global $pagenow;

            $is_nav_menus_screen = isset( $pagenow ) && 'nav-menus.php' === $pagenow;

            if ( $is_nav_menus_screen ) {
                // When editing a menu directly in wp-admin, mirror that menu's language context.
                $editing_menu = isset( $_GET['menu'] ) ? absint( wp_unslash( $_GET['menu'] ) ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended

                if ( $editing_menu <= 0 ) {
                    $recent_menu = get_user_option( 'nav_menu_recently_edited' );

                    if ( $recent_menu ) {
                        $editing_menu = (int) $recent_menu;
                    }
                }

                if ( $editing_menu > 0 && function_exists( 'wpr_translation_get_nav_menu_language_code' ) ) {
                    // Use the saved language assigned to the menu.
                    $menu_language = wpr_translation_get_nav_menu_language_code( $editing_menu );

                    if ( '' !== $menu_language ) {
                        $language = $menu_language;
                    }
                }
            }
        }

        if ( '' === $language && isset( $GLOBALS['wpr_translate_current_language'] ) && is_array( $GLOBALS['wpr_translate_current_language'] ) ) {
            // Prefer the router-resolved language when already set.
            $current = $GLOBALS['wpr_translate_current_language'];

            if ( ! empty( $current['code'] ) ) {
                $language = sanitize_key( $current['code'] );
            }
        }

        if ( '' === $language && function_exists( 'wpr_translate_get_current_language' ) ) {
            // Use the current language payload when available.
            $current = wpr_translate_get_current_language();

            if ( is_array( $current ) && ! empty( $current['code'] ) ) {
                $language = sanitize_key( $current['code'] );
            }
        }

        if ( '' === $language && function_exists( 'wpestate_get_current_language' ) ) {
            // Fall back to the legacy helper when no router language is set.
            $current_slug = sanitize_key( wpestate_get_current_language() );

            if ( '' !== $current_slug ) {
                $language_index = array();

                if ( function_exists( 'wpestate_translation_get_active_languages' ) ) {
                    $language_index = wpestate_translation_get_active_languages();
                } elseif ( function_exists( 'wpr_translation_get_active_languages' ) ) {
                    // Build a language index keyed by code and slug.
                    foreach ( wpr_translation_get_active_languages() as $language_item ) {
                        if ( empty( $language_item['code'] ) ) {
                            continue;
                        }

                        $code_key = strtolower( sanitize_key( $language_item['code'] ) );

                        if ( '' !== $code_key ) {
                            $language_index[ $code_key ] = $language_item;
                        }

                        if ( ! empty( $language_item['slug'] ) ) {
                            $slug_key = strtolower( sanitize_key( $language_item['slug'] ) );

                            if ( '' !== $slug_key ) {
                                $language_index[ $slug_key ] = $language_item;
                            }
                        }
                    }
                }

                if ( isset( $language_index[ $current_slug ]['code'] ) ) {
                    $language = strtolower( sanitize_key( $language_index[ $current_slug ]['code'] ) );
                } else {
                    $language = $current_slug;
                }
            }
        }

        if ( '' === $language ) {
            // Fall back to the default menu language.
            $overview = wpr_translation_get_nav_menu_overview();

            if ( ! empty( $overview['default'] ) ) {
                $language = strtolower( sanitize_key( $overview['default'] ) );
            }
        }

        return $language;
    }
}

if ( ! function_exists( 'wpr_translation_capture_nav_menu_locations' ) ) {
    /**
     * Captures nav menu location assignments per language before saving theme mods.
     *
     * @param array<string, int> $locations Submitted nav menu locations.
     *
     * @return array<string, int>
     */
    function wpr_translation_capture_nav_menu_locations( $locations ) {
        if ( ! is_array( $locations ) || empty( $locations ) ) {
            return $locations;
        }

        if ( ! current_user_can( 'edit_theme_options' ) ) {
            // Capability check prevents unauthorized updates.
            return $locations;
        }

        $overview         = wpr_translation_get_nav_menu_overview();
        $default_code     = isset( $overview['default'] ) ? $overview['default'] : '';
        $context_language = wpr_translation_get_requested_nav_menu_language_code();
        $stored           = wpr_translation_get_stored_nav_menu_locations();
        $default_code     = strtolower( sanitize_key( $default_code ) );

        $existing_theme_locations = get_theme_mod( 'nav_menu_locations', array() );

        if ( ! is_array( $existing_theme_locations ) ) {
            $existing_theme_locations = array();
        }

        // Normalize existing theme locations to a consistent map.
        $normalized_theme_locations = array();

        foreach ( $existing_theme_locations as $existing_location => $existing_menu_id ) {
            $existing_location_key = sanitize_key( $existing_location );
            $existing_menu_value   = absint( $existing_menu_id );

            if ( '' === $existing_location_key || $existing_menu_value <= 0 ) {
                continue;
            }

            $normalized_theme_locations[ $existing_location_key ] = $existing_menu_value;
        }

        $updated_theme_locations = $normalized_theme_locations;

        foreach ( $locations as $location => $menu_id ) {
            $location_key = sanitize_key( $location );
            $menu_id      = absint( $menu_id );

            if ( '' === $location_key ) {
                continue;
            }

            $menu_language = '';

            if ( $menu_id > 0 ) {
                // Use menu meta to determine language when assigned.
                $menu_language = get_term_meta( $menu_id, wpr_translation_get_nav_menu_language_meta_key(), true );
                $menu_language = strtolower( sanitize_key( $menu_language ) );
            }

            if ( '' === $menu_language ) {
                // Fall back to the current context language.
                $menu_language = $context_language;
            }

            if ( '' === $menu_language ) {
                // Fall back to the default language.
                $menu_language = strtolower( sanitize_key( $default_code ) );
            }

            if ( '' === $menu_language ) {
                continue;
            }

            if ( $menu_id > 0 ) {
                if ( ! isset( $stored[ $location_key ] ) || ! is_array( $stored[ $location_key ] ) ) {
                    $stored[ $location_key ] = array();
                }

                // Store the language-specific assignment.
                $stored[ $location_key ][ $menu_language ] = $menu_id;
            } elseif ( isset( $stored[ $location_key ][ $menu_language ] ) ) {
                unset( $stored[ $location_key ][ $menu_language ] );

                if ( empty( $stored[ $location_key ] ) ) {
                    unset( $stored[ $location_key ] );
                }
            }

            $is_default_language = ( '' === $default_code || $menu_language === $default_code );

            if ( $is_default_language ) {
                if ( $menu_id > 0 ) {
                    $updated_theme_locations[ $location_key ] = $menu_id;
                } else {
                    unset( $updated_theme_locations[ $location_key ] );
                }
            }
        }

        // Persist language-aware locations and sync translation links.
        wpr_translation_update_nav_menu_locations_storage( $stored );
        wpr_translation_sync_nav_menu_translations_from_locations( $stored );

        return $updated_theme_locations;
    }

    add_filter( 'pre_set_theme_mod_nav_menu_locations', 'wpr_translation_capture_nav_menu_locations' );
}

if ( ! function_exists( 'wpr_translation_store_submitted_nav_menu_locations' ) ) {
    /**
     * Persists submitted nav menu locations to the language-aware storage.
     *
     * @param int   $menu_id   Saved menu identifier.
     * @param array $menu_data Submitted menu data.
     */
    function wpr_translation_store_submitted_nav_menu_locations( $menu_id, $menu_data = array() ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedParameter
        if ( ! current_user_can( 'edit_theme_options' ) ) {
            return;
        }

        if ( ! isset( $_POST['menu-locations'] ) || ! is_array( $_POST['menu-locations'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
            return;
        }

        $raw_locations = wp_unslash( $_POST['menu-locations'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing

        if ( empty( $raw_locations ) || ! is_array( $raw_locations ) ) {
            return;
        }

        $locations = array();

        foreach ( $raw_locations as $location => $menu_assignment ) {
            $location_key = sanitize_key( $location );
            $menu_value   = absint( $menu_assignment );

            if ( '' === $location_key ) {
                continue;
            }

            $locations[ $location_key ] = $menu_value;
        }

        if ( empty( $locations ) ) {
            return;
        }

        // Store the submitted locations using the capture helper.
        wpr_translation_capture_nav_menu_locations( $locations );
    }

    add_action( 'wp_update_nav_menu', 'wpr_translation_store_submitted_nav_menu_locations', 20, 2 );
    add_action( 'wp_create_nav_menu', 'wpr_translation_store_submitted_nav_menu_locations', 20, 2 );
}

if ( ! function_exists( 'wpr_translation_filter_theme_mod_nav_menu_locations' ) ) {
    /**
     * Filters nav menu locations to return the language-specific assignments.
     *
     * @param array<string, int>|false $value Stored theme mod value.
     *
     * @return array<string, int>|false
     */
    function wpr_translation_filter_theme_mod_nav_menu_locations( $value ) {
        $stored = wpr_translation_get_stored_nav_menu_locations();

        if ( empty( $stored ) ) {
            // No stored mapping means default behavior.
            return $value;
        }

        $language_code   = wpr_translation_get_requested_nav_menu_language_code();
        $overview        = wpr_translation_get_nav_menu_overview();
        $default_code    = isset( $overview['default'] ) ? strtolower( sanitize_key( $overview['default'] ) ) : '';
        $language_filter = function_exists( 'wpr_translation_get_current_nav_menu_filter' ) ? wpr_translation_get_current_nav_menu_filter() : '';
        $should_fallback = true;

        if ( is_admin() && '' !== $language_filter ) {
            // Admin filtering should not fall back to defaults.
            $should_fallback = false;
        }

        if ( false === $value ) {
            // Initialize the array when theme mod is missing.
            $value = array();
        }

        foreach ( $stored as $location => $assignments ) {
            if ( isset( $assignments[ $language_code ] ) ) {
                // Use the language-specific assignment when available.
                $value[ $location ] = (int) $assignments[ $language_code ];
                continue;
            }

            if ( $should_fallback && '' !== $default_code && isset( $assignments[ $default_code ] ) ) {
                // Fall back to the default language assignment.
                $value[ $location ] = (int) $assignments[ $default_code ];
            } elseif ( isset( $value[ $location ] ) && ! isset( $assignments[ $language_code ] ) ) {
                // Clear stale assignments for this language.
                $value[ $location ] = 0;
            }
        }

        return $value;
    }

    add_filter( 'theme_mod_nav_menu_locations', 'wpr_translation_filter_theme_mod_nav_menu_locations' );
}

