<?php
/**
 * Theme admin option filter.
 *
 * @package WPR_Translate
 */

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

/**
 * Read theme admin string declarations when wpresidence_admin is requested.
 *
 * @param mixed  $value  Option value.
 * @param string $option Option name.
 *
 * @return mixed
 */
function wpr_translate_handle_theme_admin_option_filter( $value, $option ) {
    // Step 1: The option name is fixed by the hook, so we do not use this argument.
    unset( $option );

    // Step 2: Prepare language placeholders.
    $current_language = '';
    $default_language = '';
    $active_languages = array();

    // Step 3: Load active languages and resolve the default language code first.
    if ( function_exists( 'wpestate_translation_get_active_languages' ) ) {
        $active_languages = wpestate_translation_get_active_languages();
    }

    if ( is_array( $active_languages ) && ! empty( $active_languages ) && function_exists( 'wpr_translation_get_default_language_code' ) ) {
        $default_language = (string) wpr_translation_get_default_language_code( $active_languages );
    }

    // Step 4: Resolve current language for admin/front-end contexts.
    if ( is_admin() ) {
        // Step 4.1: Front-end AJAX can send the active language explicitly.
        if ( wp_doing_ajax() && isset( $_REQUEST['lang'] ) ) {
            $current_language = sanitize_key( wp_unslash( $_REQUEST['lang'] ) );
        }

        // Step 4.2: Admin screens use the admin language resolver.
        if ( '' === $current_language && function_exists( 'wpr_translate_return_current_language_admin' ) ) {
            $current_language = (string) wpr_translate_return_current_language_admin();
        }
    } else {
        // Step 4.3: Use router match first when available.
        if ( isset( $GLOBALS['wpr_translate_language_router']['matched_language']['code'] ) ) {
            $current_language = sanitize_key( (string) $GLOBALS['wpr_translate_language_router']['matched_language']['code'] );
        }

        // Step 4.4: Fall back to request URL first segment.
        if ( '' === $current_language ) {
            $request_uri  = isset( $_SERVER['REQUEST_URI'] ) ? (string) wp_unslash( $_SERVER['REQUEST_URI'] ) : '';
            $request_path = (string) wp_parse_url( $request_uri, PHP_URL_PATH );
            $segments     = array_values( array_filter( explode( '/', trim( $request_path, '/' ) ) ) );
            $home_path    = (string) wp_parse_url( home_url( '/' ), PHP_URL_PATH );
            $base_segments = array_values( array_filter( explode( '/', trim( $home_path, '/' ) ) ) );

            if ( ! empty( $base_segments ) && ! empty( $segments ) ) {
                foreach ( $base_segments as $index => $base_segment ) {
                    if ( isset( $segments[ $index ] ) && $segments[ $index ] === $base_segment ) {
                        unset( $segments[ $index ] );
                    }
                }
                $segments = array_values( $segments );
            }

            if ( ! empty( $segments ) ) {
                $first_segment = strtolower( sanitize_key( (string) $segments[0] ) );

                if ( isset( $active_languages[ $first_segment ]['code'] ) ) {
                    $current_language = sanitize_key( (string) $active_languages[ $first_segment ]['code'] );
                }
            }
        }

        // Step 4.5: No language slug in URL means default-language page.
        if ( '' === $current_language && '' !== $default_language ) {
            $current_language = $default_language;
        }

        // Step 4.6: Final fallback to legacy helper only when still empty.
        if ( '' === $current_language && function_exists( 'wpestate_get_current_language' ) ) {
            $current_language = (string) wpestate_get_current_language();
        }
    }

    // Step 5: Normalize language slug to language code when helper is available.
    if ( function_exists( 'wpr_translate_get_language' ) ) {
        $resolved_current = wpr_translate_get_language( $current_language );

        if ( is_array( $resolved_current ) && ! empty( $resolved_current['code'] ) ) {
            $current_language = (string) $resolved_current['code'];
        }
    }

    // Step 6: Sanitize/normalize language codes for safe comparisons.
    $current_language = strtolower( sanitize_key( $current_language ) );
    $default_language = strtolower( sanitize_key( $default_language ) );

    // Stop when the current language is the default language.
    // Step 7: Skip translation in default language and return original option.
    if ( '' !== $default_language && '' !== $current_language && $default_language === $current_language ) {
        return $value;
    }

    // Step 8: Guard clause - translations only work for array options.
    if ( ! is_array( $value ) ) {
        return $value;
    }

    // Step 9: Load theme declaration file that defines translatable paths.
    $source_file = trailingslashit( get_stylesheet_directory() ) . 'wpr/theme_admin_strings.json';

    if ( ! file_exists( $source_file ) || ! is_readable( $source_file ) ) {
        return $value;
    }

    $raw = file_get_contents( $source_file );

    if ( false === $raw ) {
        return $value;
    }

    // Step 10: Decode declarations and validate structure.
    $data = json_decode( $raw, true );

    if ( ! is_array( $data ) || ! isset( $data['wpresidence_admin'] ) || ! is_array( $data['wpresidence_admin'] ) ) {
        return $value;
    }

    // Step 11: Flatten declared nested paths to dot notation keys.
    $declared = wpr_translate_admin_flatten_theme_admin_strings( $data['wpresidence_admin'] );
    // Step 12: Stop when current language cannot be resolved.
    if ( '' === $current_language ) {
        return $value;
    }

    // Step 12.1: Reuse translated option value for repeated calls in the same request.
    static $request_cache = array();
    $cache_key            = 'wpresidence_admin|' . $current_language;

    if ( isset( $request_cache[ $cache_key ] ) ) {
        return $request_cache[ $cache_key ];
    }

    // Step 13: Prepare database table and working buffers.
    global $wpdb;
    $table_name = $wpdb->prefix . 'wpestate_translation_strings';


    $updated_value       = $value;
    $found_translations  = array();
    $translations_by_name = array();

    // Step 14: Fetch all context rows once, then filter by current language in PHP.
    $rows = $wpdb->get_results(
        $wpdb->prepare(
            "SELECT name, language_code, translation FROM {$table_name} WHERE context = %s",
            'wpresidence_admin'
        ),
        ARRAY_A
    );

    // Step 15: Build quick lookup map: name => translation for current language.
    if ( is_array( $rows ) ) {
        foreach ( $rows as $row ) {
            $name          = isset( $row['name'] ) ? (string) $row['name'] : '';
            $language_code = isset( $row['language_code'] ) ? strtolower( sanitize_key( (string) $row['language_code'] ) ) : '';
            $translation   = isset( $row['translation'] ) ? (string) $row['translation'] : '';

            if ( '' === $name || '' === trim( wp_strip_all_tags( $translation ) ) ) {
                continue;
            }

            if ( $language_code !== $current_language ) {
                continue;
            }

            $translations_by_name[ $name ] = $translation;
        }
    }
    // Step 16: Loop declared paths and apply translations when available.
    foreach ( $declared as $path => $source_value ) {
        unset( $source_value );

        if ( ! is_string( $path ) || '' === $path ) {
            continue;
        }

        // Step 16.1: Expand wildcard declarations (e.g. foo.bar.*) using live option indexes.
        if ( false !== strpos( $path, '.*' ) ) {
            $base_path = substr( $path, 0, -2 );

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

            $base_segments = explode( '.', $base_path );
            $base_cursor   = $updated_value;
            $base_exists   = true;

            // Step 16.1.1: Walk to wildcard parent path in current option value.
            foreach ( $base_segments as $base_segment ) {
                if ( ! is_array( $base_cursor ) || ! array_key_exists( $base_segment, $base_cursor ) ) {
                    $base_exists = false;
                    break;
                }

                $base_cursor = $base_cursor[ $base_segment ];
            }

            if ( ! $base_exists || ! is_array( $base_cursor ) ) {
                continue;
            }

            // Step 16.1.2: Apply each concrete indexed translation when present.
            foreach ( $base_cursor as $index => $current_item ) {
                if ( is_array( $current_item ) ) {
                    continue;
                }

                $concrete_path = $base_path . '.' . $index;

                if ( ! isset( $translations_by_name[ $concrete_path ] ) ) {
                    continue;
                }

                $translation = (string) $translations_by_name[ $concrete_path ];

                if ( '' === trim( wp_strip_all_tags( $translation ) ) ) {
                    continue;
                }

                // Step 16.1.3: Write translated value back to the exact nested target.
                $concrete_segments = explode( '.', $concrete_path );
                $target            = &$updated_value;

                foreach ( $concrete_segments as $concrete_segment ) {
                    $target = &$target[ $concrete_segment ];
                }

                $target                            = $translation;
                $found_translations[ $concrete_path ] = $translation;

                // Step 16.1.4: Keep flat advanced-search labels in sync with set_search labels.
                if ( 'wpestate_set_search.adv_search_label' === $base_path && isset( $updated_value['wp_estate_adv_search_label'] ) && is_array( $updated_value['wp_estate_adv_search_label'] ) ) {
                    $updated_value['wp_estate_adv_search_label'][ $index ] = $translation;
                    $found_translations[ 'wp_estate_adv_search_label.' . $index ] = $translation;
                }
            }

            continue;
        }

        // Step 16.2: Process normal (non-wildcard) declared keys.
        $segments = explode( '.', $path );
        $cursor   = $updated_value;
        $exists   = true;

        // Step 16.2.1: Walk target path and ensure it exists in option payload.
        foreach ( $segments as $segment ) {
            if ( ! is_array( $cursor ) || ! array_key_exists( $segment, $cursor ) ) {
                $exists = false;
                break;
            }

            $cursor = $cursor[ $segment ];
        }

        if ( ! $exists || is_array( $cursor ) ) {
            continue;
        }

        if ( ! isset( $translations_by_name[ $path ] ) ) {
            continue;
        }

        $translation = (string) $translations_by_name[ $path ];

        if ( '' === trim( wp_strip_all_tags( $translation ) ) ) {
            continue;
        }

        // Step 16.2.2: Assign translated value to final nested key.
        $target = &$updated_value;

        foreach ( $segments as $segment ) {
            $target = &$target[ $segment ];
        }

        $target                     = $translation;
        $found_translations[ $path ] = $translation;
    }

    // Step 18: Save translated option in request cache and return it.
    $request_cache[ $cache_key ] = $updated_value;

    return $request_cache[ $cache_key ];
}

add_filter( 'option_wpresidence_admin', 'wpr_translate_handle_theme_admin_option_filter', 999, 2 );
