<?php
/**
 * Post editor integrations for automatic translation.
 *
 * @package WPR_Translate
 */

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

/**
 * Bootstrap the post editor integrations.
 */
function wpr_translate_bootstrap_post_editor_integration() {
    // Register post editor screen hooks.
    add_action( 'load-post.php', 'wpr_translate_initialize_post_editor_hooks' );
    add_action( 'load-post-new.php', 'wpr_translate_initialize_post_editor_hooks' );
    // Register AJAX handlers for translation actions.
    add_action( 'wp_ajax_wpr_translate_auto_translate_post', 'wpr_translate_handle_auto_translate_post_ajax' );
    add_action( 'wp_ajax_wpr_translate_auto_translate_post_publish', 'wpr_translate_handle_auto_translate_post_publish_ajax' );
}

/**
 * Register hooks specific to the post editor screens.
 */
function wpr_translate_initialize_post_editor_hooks() {
    // Add the publish box button for manual auto-translation.
    add_action( 'post_submitbox_misc_actions', 'wpr_translate_render_post_auto_translation_button' );
    // Register the block editor meta box equivalent.
    add_action( 'add_meta_boxes', 'wpr_translate_register_auto_translate_metabox', 10, 2 );
    // Load scripts/styles required by the auto-translate UI.
    add_action( 'admin_enqueue_scripts', 'wpr_translate_enqueue_post_editor_assets' );
}

/**
 * Determine if a page uses WPBakery based on its meta flags.
 *
 * @param int    $post_id   Post ID.
 * @param string $post_type Post type slug.
 *
 * @return bool
 */
function wpr_translate_is_wpbakery_page( $post_id, $post_type ) {
    // Only pages store the WPBakery usage flag in this plugin context.
    if ( 'page' !== $post_type ) {
        return false;
    }

    // Read the WPBakery activation flag stored on the post.
    $status = get_post_meta( $post_id, '_wpb_vc_js_status', true );

    return ! empty( $status ) && 'true' === $status;
}

/**
 * Extract simple text snippets from a WPBakery layout.
 *
 * @param string $post_content Page content that stores WPBakery shortcodes.
 *
 * @return array
 */
function wpr_translate_extract_wpbakery_text_fields( $post_content ) {
    // Normalize the incoming content to a string.
    $post_content = (string) $post_content;
    $text_fields  = array();

    // Exit early when there is no content to parse.
    if ( '' === $post_content ) {
        return $text_fields;
    }

    // Collect text inside common content blocks.
    if ( preg_match_all( '/\[vc_column_text[^\]]*\](.*?)\[\/vc_column_text\]/si', $post_content, $matches ) ) {
        foreach ( $matches[1] as $match ) {
            $cleaned = wp_strip_all_tags( $match );

            if ( '' !== $cleaned ) {
                $text_fields[] = $cleaned;
            }
        }
    }

    // Collect button labels stored as shortcode attributes.
    if ( preg_match_all( '/\[vc_btn[^\]]*title="([^"]+)"/si', $post_content, $matches ) ) {
        foreach ( $matches[1] as $title ) {
            $cleaned = wp_strip_all_tags( $title );

            if ( '' !== $cleaned ) {
                $text_fields[] = $cleaned;
            }
        }
    }

    // Remove empty entries and reindex the array for consistent output.
    return array_values( array_filter( $text_fields ) );
}

/**
 * Render the automatic translation button inside the publish metabox.
 */
function wpr_translate_render_post_auto_translation_button() {
    global $post;

    // Ensure a valid post object is available.
    if ( ! class_exists( 'WP_Post' ) || ! ( $post instanceof WP_Post ) ) {
        return;
    }

    // Only show the button to users who can edit the post.
    if ( ! current_user_can( 'edit_post', $post->ID ) ) {
        return;
    }

    $language_label          = '';
    $language_code           = '';
    $default_language_code   = '';
    $languages               = array();

    if ( function_exists( 'wpr_translate_get_active_languages' ) ) {
        // Retrieve the active languages so we can determine the default one later on.
        $languages = wpr_translate_get_active_languages( false );
    }

    if ( function_exists( 'wpr_translate_get_post_language' ) ) {
        $language = wpr_translate_get_post_language( $post->ID );

        if ( is_array( $language ) ) {
            if ( ! empty( $language['name'] ) ) {
                $language_label = sanitize_text_field( $language['name'] );
            }

            if ( empty( $language_code ) && ! empty( $language['code'] ) ) {
                $language_code = sanitize_text_field( $language['code'] );
            }
        }
    }

    if ( '' === $language_code && function_exists( 'wpr_translation_resolve_post_language_code' ) ) {
        // Resolve the language if the direct lookup did not provide one.
        $language_code = sanitize_text_field( wpr_translation_resolve_post_language_code( $post->ID, $post->post_type ) );
    }

    if ( function_exists( 'wpr_translation_get_default_language_code' ) ) {
        $default_language_code = sanitize_text_field( wpr_translation_get_default_language_code( $languages ) );
    }

    if ( '' === $language_code && '' !== $default_language_code ) {
        $language_code = $default_language_code;
    }

    if ( '' === $language_label ) {
        $language_label = $language_code;
    }

    if ( '' === $language_label ) {
        // Fall back to a generic label if no language is resolved.
        $language_label = __( 'current language', 'wpr-translate' );
    }

    // Load auto-translation settings to determine the engine.
    $settings = get_option( 'wpr_translate_auto_translation', array() );
    $settings = is_array( $settings ) ? $settings : array();
    $engine   = isset( $settings['engine'] ) ? sanitize_key( $settings['engine'] ) : 'openai';

    if ( ! in_array( $engine, array( 'openai', 'google_translate', 'microsoft_azure', 'deepl' ), true ) ) {
        $engine = 'openai';
    }

    // Check if this post already ran through the automatic translation flow.
    $auto_translated_language = get_post_meta( $post->ID, '_wpr_translate_auto_translated_language', true );

    if ( is_string( $auto_translated_language ) ) {
        $auto_translated_language = sanitize_key( $auto_translated_language );
    } else {
        $auto_translated_language = '';
    }

    $has_completed_translation = (
        '' !== $language_code
        && '' !== $auto_translated_language
        && strtolower( $auto_translated_language ) === strtolower( $language_code )
    );

    if ( $has_completed_translation ) {
        // Allow admins to re-run translation for this language.
        $button_label = __( 'Redo the translation', 'wpr-translate' );
    } else {
        $button_label = sprintf(
            /* translators: %s: language label. */
            __( 'Auto translate in %s', 'wpr-translate' ),
            $language_label
        );
    }

    // Output the button container markup.
    echo '<div class="misc-pub-section wpr-translate-auto-translate">';

    if (
        '' !== $default_language_code
        && '' !== $language_code
        && strtolower( $language_code ) === strtolower( $default_language_code )
    ) {
        echo '<div class="wpr-translate-auto-translate-message">' . esc_html__( 'Original post -no translation action.', 'wpr-translate' ) . '</div>';
        echo '</div>';

        return;
    }

    $source_post_id = wpr_translate_resolve_metabox_source_post_id( $post->ID );

    if ( $source_post_id <= 0 ) {
        printf(
            '<button type="button" class="button wpr-translate-auto-translate-button" data-post-id="%1$s" data-source-post-id="" data-language="%2$s" data-engine="%3$s" data-original-label="%4$s" disabled="disabled" aria-disabled="true">%5$s</button>',
            esc_attr( (string) $post->ID ),
            esc_attr( $language_code ),
            esc_attr( $engine ),
            esc_attr__( 'Auto translation unavailable', 'wpr-translate' ),
            esc_html__( 'Auto translation unavailable', 'wpr-translate' )
        );
        echo '<div class="wpr-translate-auto-translate-message">' . esc_html__( 'Original source post was not found. Auto translation is disabled for this post.', 'wpr-translate' ) . '</div>';
        echo '</div>';

        return;
    }

    printf(
        '<button type="button" class="button wpr-translate-auto-translate-button" data-post-id="%1$s" data-source-post-id="%2$s" data-language="%3$s" data-engine="%4$s" data-original-label="%5$s">%6$s</button>',
        esc_attr( (string) $post->ID ),
        esc_attr( (string) $source_post_id ),
        esc_attr( $language_code ),
        esc_attr( $engine ),
        esc_attr( $button_label ),
        esc_html( $button_label )
    );

    $source_link  = get_edit_post_link( $source_post_id, 'url' );
    $source_title = wp_strip_all_tags( get_the_title( $source_post_id ) );

    if ( '' === $source_title ) {
        $source_title = '#' . $source_post_id;
    }

    if ( ! empty( $source_link ) ) {
        printf(
            '<div class="wpr-translate-auto-translate-message">%1$s <a href="%2$s">%3$s</a></div>',
            esc_html__( 'Source:', 'wpr-translate' ),
            esc_url( $source_link ),
            esc_html( $source_title )
        );
    }

    echo '</div>';
}

/**
 * Resolve the source/original post ID for metabox auto translation.
 *
 * @param int $post_id Target translated post ID.
 *
 * @return int
 */
function wpr_translate_resolve_metabox_source_post_id( $post_id ) {
    $post_id = absint( $post_id );

    if ( $post_id <= 0 ) {
        return 0;
    }

    // First source: explicit post meta link.
    $meta_source_id = absint( get_post_meta( $post_id, 'wpr_translated_original_post_id', true ) );

    if ( $meta_source_id > 0 && $meta_source_id !== $post_id && get_post( $meta_source_id ) ) {
        return $meta_source_id;
    }

    // Fallback source: translation group mapping in plugin tables.
    if ( function_exists( 'wpr_translation_get_element_type' ) && function_exists( 'wpr_translation_get_translation_group' ) ) {
        $post_type = get_post_type( $post_id );
        $post_type = is_string( $post_type ) ? sanitize_key( $post_type ) : '';

        if ( '' !== $post_type ) {
            $element_type = wpr_translation_get_element_type( $post_type );
            $group        = wpr_translation_get_translation_group( $post_id, $element_type );

            if ( is_array( $group ) ) {
                $source_language = isset( $group['source_language'] ) ? strtolower( sanitize_key( $group['source_language'] ) ) : '';

                if ( '' === $source_language && function_exists( 'wpr_translation_get_active_languages' ) && function_exists( 'wpr_translation_get_default_language_code' ) ) {
                    $languages       = wpr_translation_get_active_languages();
                    $source_language = strtolower( sanitize_key( wpr_translation_get_default_language_code( $languages ) ) );
                }

                if ( '' !== $source_language && ! empty( $group['translations'][ $source_language ] ) ) {
                    $group_source_id = absint( $group['translations'][ $source_language ] );

                    if ( $group_source_id > 0 && $group_source_id !== $post_id && get_post( $group_source_id ) ) {
                        return $group_source_id;
                    }
                }
            }
        }
    }

    return 0;
}

/**
 * Register the auto translate meta box for the block editor.
 *
 * @param string  $post_type Current post type.
 * @param WP_Post $post      Current post object.
 */
function wpr_translate_register_auto_translate_metabox( $post_type, $post ) {
    // Bail if no valid post is provided.
    if ( ! ( $post instanceof WP_Post ) ) {
        return;
    }

    // Only add the meta box when the block editor is active for this post.
    if ( ! function_exists( 'use_block_editor_for_post' ) || ! use_block_editor_for_post( $post ) ) {
        return;
    }

    // Register the meta box for the post editor sidebar.
    add_meta_box(
        'wpr-translate-auto-translate',
        __( 'Automatic Translation', 'wpr-translate' ),
        'wpr_translate_render_post_auto_translation_metabox',
        $post_type,
        'side',
        'high'
    );
}

/**
 * Render the auto translate button inside the meta box.
 */
function wpr_translate_render_post_auto_translation_metabox() {
    // Reuse the publish box renderer to keep the button logic in one place.
    wpr_translate_render_post_auto_translation_button();
}

/**
 * Enqueue the post editor assets for automatic translation interactions.
 *
 * @param string $hook Current admin page hook.
 */
function wpr_translate_enqueue_post_editor_assets( $hook ) {
    // Only enqueue assets on the post editor screens.
    if ( 'post.php' !== $hook && 'post-new.php' !== $hook ) {
        return;
    }

    // Define handles and paths for the admin assets.
    $script_handle = 'wpr-translate-admin';
    $style_handle  = 'wpr-translate-admin';
    $script_path   = WPR_TRANSLATE_PLUGIN_ROOT . 'assets/js/admin.js';
    $script_url    = WPR_TRANSLATE_PLUGIN_URL . 'assets/js/admin.js';
    $style_path    = WPR_TRANSLATE_PLUGIN_ROOT . 'assets/css/admin.css';
    $style_url     = WPR_TRANSLATE_PLUGIN_URL . 'assets/css/admin.css';
    $version       = file_exists( $script_path ) ? filemtime( $script_path ) : WPR_TRANSLATE_VERSION;
    $style_version = file_exists( $style_path ) ? filemtime( $style_path ) : WPR_TRANSLATE_VERSION;

    // Enqueue styles and scripts needed by the auto-translate UI.
    wp_enqueue_style( $style_handle, $style_url, array(), $style_version );
    wp_enqueue_script( $script_handle, $script_url, array( 'jquery', 'wp-util' ), $version, true );

    // Build localized settings for the front-end script.
    $settings = get_option( 'wpr_translate_auto_translation', array() );
    $settings = is_array( $settings ) ? $settings : array();

    $localized = array(
        'enabled' => ! empty( $settings['enabled'] ),
        'engine'  => isset( $settings['engine'] ) ? sanitize_key( $settings['engine'] ) : 'openai',
        'ajax'    => array(
            'url'   => admin_url( 'admin-ajax.php' ),
            'nonce' => wp_create_nonce( 'wpr_translate_auto_translate_post' ),
        ),
        'strings' => array(
            'error'      => __( 'Automatic translation failed. Please try again.', 'wpr-translate' ),
            'success'    => __( 'Automatic translation completed.', 'wpr-translate' ),
            'processing' => __( 'Doing the translation. Please wait....', 'wpr-translate' ),
        ),
    );

    if ( ! in_array( $localized['engine'], array( 'openai', 'google_translate', 'microsoft_azure', 'deepl' ), true ) ) {
        // Fallback to OpenAI if the stored value is invalid.
        $localized['engine'] = 'openai';
    }

    // Pass settings to the admin script.
    wp_localize_script( $script_handle, 'wprTranslateAutoSettings', $localized );
}

/**
 * Handle the automatic translation AJAX request.
 */
function wpr_translate_handle_auto_translate_post_ajax() {
    // Validate the request nonce for the manual translation action.
    if ( ! check_ajax_referer( 'wpr_translate_auto_translate_post', 'nonce', false ) ) {
        wp_send_json_error( array( 'message' => __( 'Invalid request. Please refresh the page and try again.', 'wpr-translate' ) ), 400 );
    }

    // Validate the post and user permissions.
    $post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0;

    if ( ! $post_id || ! current_user_can( 'edit_post', $post_id ) ) {
        wp_send_json_error( array( 'message' => __( 'You are not allowed to translate this post.', 'wpr-translate' ) ), 403 );
    }

    if ( class_exists( 'QueryMonitor', false ) ) {
        // Stop Query Monitor collectors for heavy translation requests.
        do_action( 'qm/cease' );
    }

    // Gather request parameters and engine selection.
    $language       = isset( $_POST['language'] ) ? sanitize_text_field( wp_unslash( $_POST['language'] ) ) : '';
    $source_post_id = isset( $_POST['source_post_id'] ) ? absint( $_POST['source_post_id'] ) : 0;

    if ( $source_post_id <= 0 ) {
        wp_send_json_error( array( 'message' => __( 'Missing source post for translation.', 'wpr-translate' ) ), 400 );
    }

    $settings = get_option( 'wpr_translate_auto_translation', array() );
    $settings = is_array( $settings ) ? $settings : array();

    $engine = isset( $settings['engine'] ) ? sanitize_key( $settings['engine'] ) : 'openai';

    if ( ! in_array( $engine, array( 'openai', 'google_translate', 'microsoft_azure', 'deepl' ), true ) ) {
        $engine = 'openai';
    }

    // Perform translation via the selected engine.
    if ( function_exists( 'wpr_translate_auto_translate_post' ) ) {
        $result = wpr_translate_auto_translate_post( $post_id, $language, $engine, $source_post_id );
    } else {
        $result = new WP_Error( 'wpr_translate_auto_post_removed', __( 'Automatic post translation function is not available.', 'wpr-translate' ) );
    }

    if ( is_wp_error( $result ) ) {
        wp_send_json_error( array( 'message' => $result->get_error_message() ) );
    }


    // Respond with a success message for the UI.
    wp_send_json_success( array( 'message' => __( 'Automatic translation completed.', 'wpr-translate' ) ) );
}

/**
 * Handle automatic translation for queued runs and publish the post once complete.
 */
function wpr_translate_handle_auto_translate_post_publish_ajax() {
    // Validate the request nonce for queued translations.
    if ( ! check_ajax_referer( 'wpr_translate_auto_translate_post_publish', 'nonce', false ) ) {
        wp_send_json_error( array( 'message' => __( 'Invalid request. Please refresh the page and try again.', 'wpr-translate' ) ), 400 );
    }

    // Validate the post ID and user capability.
    $post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0;

    if ( ! $post_id || ! current_user_can( 'edit_post', $post_id ) ) {
        wp_send_json_error( array( 'message' => __( 'You are not allowed to translate this post.', 'wpr-translate' ) ), 403 );
    }

    if ( class_exists( 'QueryMonitor', false ) ) {
        // Stop Query Monitor collectors for heavy translation requests.
        do_action( 'qm/cease' );
    }

    // Gather request parameters and engine selection.
    $language       = isset( $_POST['language'] ) ? sanitize_text_field( wp_unslash( $_POST['language'] ) ) : '';
    $source_post_id = isset( $_POST['source_post_id'] ) ? absint( $_POST['source_post_id'] ) : 0;

    if ( $source_post_id <= 0 ) {
        wp_send_json_error( array( 'message' => __( 'Missing source post for translation.', 'wpr-translate' ) ), 400 );
    }

    $settings = get_option( 'wpr_translate_auto_translation', array() );
    $settings = is_array( $settings ) ? $settings : array();

    $engine = isset( $settings['engine'] ) ? sanitize_key( $settings['engine'] ) : 'openai';

    if ( ! in_array( $engine, array( 'openai', 'google_translate', 'microsoft_azure', 'deepl' ), true ) ) {
        $engine = 'openai';
    }

    // Run the auto-translation flow before publishing.
    if ( function_exists( 'wpr_translate_auto_translate_post' ) ) {
        $result = wpr_translate_auto_translate_post( $post_id, $language, $engine, $source_post_id );
    } else {
        $result = new WP_Error( 'wpr_translate_auto_post_removed', __( 'Automatic post translation function is not available.', 'wpr-translate' ) );
    }


    if ( is_wp_error( $result ) ) {
        if ( 'wpr_translate_missing_openai_key' === $result->get_error_code() ) {
            // Publish the translation draft even when OpenAI is unavailable.
            $publish_result = wp_update_post(
                array(
                    'ID'          => $post_id,
                    'post_status' => 'publish',
                ),
                true
            );

            if ( is_wp_error( $publish_result ) ) {
                wp_send_json_error( array( 'message' => $publish_result->get_error_message() ) );
            }

            if ( function_exists( 'wpr_translate_purge_wpestate_cache' ) ) {
                wpr_translate_purge_wpestate_cache();
            }

            wp_send_json_success(
                array(
                    'message' => __( 'Automatic translation skipped (missing OpenAI key). Post published.', 'wpr-translate' ),
                )
            );
        }

        wp_send_json_error( array( 'message' => $result->get_error_message() ) );
    }


    // Publish the translated post once translation completes.
    $publish_result = wp_update_post(
        array(
            'ID'          => $post_id,
            'post_status' => 'publish',
        ),
        true
    );

    if ( is_wp_error( $publish_result ) ) {
        wp_send_json_error( array( 'message' => $publish_result->get_error_message() ) );
    }

    if ( function_exists( 'wpr_translate_purge_wpestate_cache' ) ) {
        wpr_translate_purge_wpestate_cache();
    }


    // Respond with a success message for the UI.
    wp_send_json_success( array( 'message' => __( 'Automatic translation completed.', 'wpr-translate' ) ) );
}

/**
 * Prepare the translation payload and dispatch it to the selected engine.
 *
 * @param int    $post_id        Post identifier that will be translated.
 * @param string $language       Target language slug.
 * @param string $engine         Selected translation engine key.
 * @param int    $source_post_id Source/original post ID used to build payload.
 *
 * @return true|WP_Error
 */
function wpr_translate_auto_translate_post( $post_id, $language, $engine, $source_post_id = 0 ) {
    // Normalize incoming identifiers before reading post data.
    $post_id        = absint( $post_id );
    $source_post_id = absint( $source_post_id );
    $language       = sanitize_text_field( $language );
    $engine         = sanitize_key( $engine );

    if ( $post_id <= 0 ) {
        return new WP_Error( 'wpr_translate_invalid_post', __( 'Invalid post selected for translation.', 'wpr-translate' ) );
    }

    if ( $source_post_id <= 0 ) {
        return new WP_Error( 'wpr_translate_missing_source_post', __( 'Missing source post for translation.', 'wpr-translate' ) );
    }

    // Load the source post as an array so we can safely build a payload.
    $post = get_post( $source_post_id, ARRAY_A );

    if ( empty( $post ) || ! is_array( $post ) ) {
        return new WP_Error( 'wpr_translate_missing_post', __( 'Unable to load the selected post for translation.', 'wpr-translate' ) );
    }

    // Resolve and normalize the post type used for custom-field and taxonomy filtering.
    $post_type = isset( $post['post_type'] ) ? sanitize_key( $post['post_type'] ) : '';

    if ( '' === $post_type ) {
        $post_type = sanitize_key( get_post_type( $source_post_id ) );
    }

    // Normalize post fields and keep a reduced set that is relevant for translation.
    $post_fields = array();

    foreach ( $post as $field_key => $field_value ) {
        $normalized_key = sanitize_key( $field_key );

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

        $post_fields[ $normalized_key ] = maybe_unserialize( $field_value );
    }

    // Remove non-translatable post fields to keep payload small and predictable.
    $skip_post_fields = array(
        'post_status',
        'comment_status',
        'ping_status',
        'post_password',
        'to_ping',
        'pinged',
        'post_modified',
        'post_modified_gmt',
        'post_content_filtered',
        'post_parent',
        'menu_order',
        'post_type',
        'post_mime_type',
        'comment_count',
        'filter',
    );

    foreach ( $skip_post_fields as $skip_field ) {
        if ( isset( $post_fields[ $skip_field ] ) ) {
            unset( $post_fields[ $skip_field ] );
        }
    }

    // Collect translatable post meta based on configured custom field rules.
    $post_meta_fields = array();

    if ( function_exists( 'wpr_translate_get_custom_field_rules' ) ) {
        $rules = wpr_translate_get_custom_field_rules();
        $rules = is_array( $rules ) ? $rules : array();

        foreach ( $rules as $rule ) {
            if ( ! is_array( $rule ) ) {
                continue;
            }

            $raw_meta_key = isset( $rule['id'] ) && is_string( $rule['id'] ) ? trim( $rule['id'] ) : '';
            $meta_key     = sanitize_key( $raw_meta_key );
            $action       = isset( $rule['action'] ) ? sanitize_key( $rule['action'] ) : '';
            $rule_post    = isset( $rule['post'] ) && is_string( $rule['post'] ) ? sanitize_key( $rule['post'] ) : '';

            if ( '' === $raw_meta_key || '' === $meta_key || 'translate' !== $action ) {
                continue;
            }

            if ( '' !== $rule_post && '' !== $post_type && $rule_post !== $post_type ) {
                continue;
            }

            $post_meta_fields[ $raw_meta_key ] = maybe_unserialize( get_post_meta( $source_post_id, $raw_meta_key, true ) );
        }
    }

    // Collect translatable taxonomy terms from the source post.
    $taxonomy_payload = array();
    $taxonomies       = get_object_taxonomies( $post_type, 'objects' );

    if ( ! empty( $taxonomies ) ) {
        foreach ( $taxonomies as $taxonomy_object ) {
            if ( empty( $taxonomy_object->name ) ) {
                continue;
            }

            $taxonomy = sanitize_key( $taxonomy_object->name );

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

            if ( function_exists( 'wpr_translation_is_taxonomy_translatable' ) && ! wpr_translation_is_taxonomy_translatable( $taxonomy ) ) {
                continue;
            }

            $terms = wp_get_object_terms(
                $source_post_id,
                $taxonomy,
                array(
                    'hide_empty' => false,
                )
            );

            if ( is_wp_error( $terms ) || empty( $terms ) ) {
                continue;
            }

            $term_entries = array();

            foreach ( $terms as $term ) {
                if ( ! ( $term instanceof WP_Term ) ) {
                    continue;
                }

                $term_description      = is_string( $term->description ) ? $term->description : '';
                $term_category_tagline = '';
                $term_option_payload   = get_option( 'taxonomy_' . (int) $term->term_id, array() );

                if ( is_array( $term_option_payload ) && isset( $term_option_payload['category_tagline'] ) ) {
                    $term_category_tagline = is_string( $term_option_payload['category_tagline'] ) ? (string) $term_option_payload['category_tagline'] : '';
                }

                $term_entries[] = array(
                    'term_id'          => (int) $term->term_id,
                    'slug'             => sanitize_title( $term->slug ),
                    'name'             => sanitize_text_field( $term->name ),
                    'description'      => wp_kses_post( $term_description ),
                    'category_tagline' => wp_kses_post( $term_category_tagline ),
                );
            }

            if ( empty( $term_entries ) ) {
                continue;
            }

            $taxonomy_payload[ $taxonomy ] = array(
                'label' => isset( $taxonomy_object->label ) ? sanitize_text_field( $taxonomy_object->label ) : $taxonomy,
                'terms' => $term_entries,
            );
        }
    }

    // Add Elementor structured payload when this helper is available for the post.
    $elementor_translate = array();

    if (
        function_exists( 'wpr_translate_is_elementor_page' )
        && function_exists( 'wpr_translate_prepare_elementor_translation_payload' )
        && wpr_translate_is_elementor_page( $source_post_id, $post_type )
    ) {
        $elementor_translate = wpr_translate_prepare_elementor_translation_payload( $source_post_id, $language );
        $elementor_translate = is_array( $elementor_translate ) ? $elementor_translate : array();

        // Elementor pages carry full translatable content in structured data.
        // Avoid sending duplicate classic post_content for these pages.
        if ( isset( $post_fields['post_content'] ) ) {
            unset( $post_fields['post_content'] );
        }
    }

    // Build the final payload used by all translation engines.
    $payload = array(
        'post_id'          => $source_post_id,
        'language'         => $language,
        'post_type'        => $post_type,
        'post'             => $post_fields,
        'post_meta_fields' => $post_meta_fields,
        'custom_fields'    => $post_meta_fields,
        'taxonomies'       => $taxonomy_payload,
    );

    if ( ! empty( $elementor_translate ) ) {
        $payload['elementor_translate'] = $elementor_translate;
    }

    $payload_json = wp_json_encode( $payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES );

    if ( false === $payload_json || null === $payload_json ) {
        return new WP_Error( 'wpr_translate_payload_encoding_failed', __( 'Failed to prepare the translation payload.', 'wpr-translate' ) );
    }

    // Dispatch to the configured translation engine.
    switch ( $engine ) {
        case 'google_translate':
            return wpr_translate_auto_translate_post_google( $post_id, $language, $payload, $payload_json );
        case 'microsoft_azure':
            return wpr_translate_auto_translate_post_microsoft_azure( $post_id, $language, $payload, $payload_json );
        case 'deepl':
            return wpr_translate_auto_translate_post_deepl( $post_id, $language, $payload, $payload_json );
        case 'openai':
        default:
            return wpr_translate_auto_translate_post_openai( $post_id, $language, $payload, $payload_json );
    }
}

/**
 * Apply translated post data to a translated post.
 *
 * @param int   $post_id            Post identifier that will be updated.
 * @param array $translated_payload Translated payload returned by the engine.
 *
 * @return array|WP_Error
 */
function wpr_translate_apply_translated_post_data( $post_id, $translated_payload ) {
    // Sanitize inputs and normalize the payload.
    $post_id            = absint( $post_id );
    $translated_payload = is_array( $translated_payload ) ? $translated_payload : array();

    // Load the post object to inspect the post type and builder status.
    $post_object = get_post( $post_id );
    $post_type   = ( $post_object instanceof WP_Post ) ? $post_object->post_type : '';

    $is_elementor_post = false;

    if ( $post_object instanceof WP_Post ) {
        $is_elementor_post = wpr_translate_is_elementor_page( $post_id, $post_type );
    }

    if ( $post_id <= 0 ) {
        return new WP_Error( 'wpr_translate_invalid_post', __( 'Invalid post selected for translation.', 'wpr-translate' ) );
    }

    // Track the target language so taxonomy term lookups can prefer localized IDs.
    $target_language        = '';
    $target_language_code   = '';
    $target_language_slug   = '';
    $target_language_locale = '';

    if ( isset( $translated_payload['language'] ) ) {
        $target_language      = sanitize_text_field( (string) $translated_payload['language'] );
        $target_language_code = strtolower( $target_language );

        if ( function_exists( 'wpr_translate_get_language' ) ) {
            $target_language_data = wpr_translate_get_language( $target_language );

            if ( is_array( $target_language_data ) ) {
                if ( function_exists( 'wpr_translate_normalize_language' ) ) {
                    $target_language_data = wpr_translate_normalize_language( $target_language_data );
                }

                if ( ! empty( $target_language_data['code'] ) ) {
                    $target_language_code = strtolower( sanitize_text_field( $target_language_data['code'] ) );
                }

                if ( ! empty( $target_language_data['slug'] ) ) {
                    $target_language_slug = strtolower( sanitize_text_field( $target_language_data['slug'] ) );
                }

                if ( ! empty( $target_language_data['locale'] ) ) {
                    $target_language_locale = strtolower( str_replace( '_', '-', sanitize_text_field( $target_language_data['locale'] ) ) );
                }
            }
        }
    }

    $post_updates = array( 'ID' => $post_id );

    // Detect builder payloads so content can be preserved when needed.
    $has_builder_meta = (
        isset( $translated_payload['post_meta_fields']['_elementor_data'] )
        || isset( $translated_payload['post_meta_fields']['_wpbakery_fields'] )
    );

    if ( $has_builder_meta && ( ! isset( $translated_payload['post']['post_content'] ) ) ) {
    }

    if ( isset( $translated_payload['post'] ) && is_array( $translated_payload['post'] ) ) {
        // Map translated post fields into the update array.
        foreach ( $translated_payload['post'] as $field_key => $field_value ) {
            $sanitized_key = sanitize_key( $field_key );

            switch ( $sanitized_key ) {
                case 'post_title':
                    $post_updates['post_title'] = sanitize_text_field( (string) $field_value );
                    break;
                case 'post_excerpt':
                    $post_updates['post_excerpt'] = wp_kses_post( (string) $field_value );
                    break;
                case 'post_content':
                    $post_updates['post_content'] = wp_kses_post( (string) $field_value );
                    break;
                case 'post_name':
                    $post_updates['post_name'] = sanitize_title( (string) $field_value );
                    break;
                default:
                    break;
            }
        }
    }

    if ( count( $post_updates ) > 1 ) {
        // Preserve the page template and update the post record.
        $page_template = wpr_translation_get_validated_page_template( get_post( $post_id ) );
        update_post_meta( $post_id, '_wp_page_template', $page_template );

        $update_result = wp_update_post( wp_slash( $post_updates ), true );

        if ( is_wp_error( $update_result ) ) {
            return new WP_Error( 'wpr_translate_post_update_failed', __( 'Failed to update the translated post content.', 'wpr-translate' ) );
        }
    }



    // Apply translated custom fields and builder meta.
    if ( function_exists( 'wpr_translate_apply_translated_post_meta_fields' ) ) {
        wpr_translate_apply_translated_post_meta_fields( $post_id, $translated_payload );
    }

    // Apply translated Elementor content when available.
    wpr_translate_apply_elementor_translations( $post_id, $translated_payload, $target_language );











    // Apply translated taxonomy relationships for this post.
    $taxonomy_result = wpr_translate_apply_translated_taxonomies(
        $post_id,
        $translated_payload,
        $target_language,
        $target_language_code,
        $target_language_slug,
        $target_language_locale
    );

    if ( is_wp_error( $taxonomy_result ) ) {
        return $taxonomy_result;
    }

    if ( $is_elementor_post ) {
        // Regenerate Elementor CSS so translated content displays correctly.

        if ( class_exists( '\\Elementor\\Plugin' ) && isset( \Elementor\Plugin::$instance ) ) {
            $files_manager = \Elementor\Plugin::$instance->files_manager;

            if ( $files_manager && method_exists( $files_manager, 'clear_cache' ) ) {
                $files_manager->clear_cache();
            }
        } else {
        }

        if ( class_exists( '\\Elementor\\Core\\Files\\CSS\\Post' ) ) {
            $css_file = new \Elementor\Core\Files\CSS\Post( $post_id );

            if ( method_exists( $css_file, 'update' ) ) {
                $css_file->update();
            }
        } else {
        }
    }

    // Track that the automatic translation finished for this post/language.
    $auto_translation_language = '';

    if ( '' !== $target_language_code ) {
        $auto_translation_language = sanitize_key( $target_language_code );
    } elseif ( '' !== $target_language_slug ) {
        $auto_translation_language = sanitize_key( $target_language_slug );
    } elseif ( '' !== $target_language ) {
        $auto_translation_language = sanitize_key( $target_language );
    }

    if ( '' !== $auto_translation_language ) {
        $auto_translation_original_post_id = 0;
        $auto_translation_trid             = 0;

        if ( function_exists( 'wpr_translation_get_element_type' ) && function_exists( 'wpr_translation_get_translation_group' ) ) {
            $translated_post_type = get_post_type( $post_id );
            $translated_post_type = is_string( $translated_post_type ) ? sanitize_key( $translated_post_type ) : '';

            if ( '' !== $translated_post_type ) {
                $element_type = wpr_translation_get_element_type( $translated_post_type );
                $group        = wpr_translation_get_translation_group( $post_id, $element_type );

                if ( is_array( $group ) ) {
                    $auto_translation_trid = isset( $group['trid'] ) ? absint( $group['trid'] ) : 0;
                    $source_language       = isset( $group['source_language'] ) ? strtolower( sanitize_key( $group['source_language'] ) ) : '';
                    $default_language      = '';

                    if ( '' === $source_language && function_exists( 'wpr_translation_get_active_languages' ) && function_exists( 'wpr_translation_get_default_language_code' ) ) {
                        $languages         = wpr_translation_get_active_languages();
                        $default_language  = strtolower( sanitize_key( wpr_translation_get_default_language_code( $languages ) ) );
                        $source_language   = $default_language;
                    }

                    if ( '' !== $source_language && isset( $group['translations'][ $source_language ] ) ) {
                        $auto_translation_original_post_id = absint( $group['translations'][ $source_language ] );
                    }
                }
            }
        }

        if ( $auto_translation_original_post_id <= 0 ) {
            $auto_translation_original_post_id = $post_id;
        }

        update_post_meta( $post_id, '_wpr_translate_auto_translated_language', $auto_translation_language );
        update_post_meta( $post_id, 'wpr_translated_language', $auto_translation_language );
        update_post_meta( $post_id, 'wpr_translated_original_post_id', $auto_translation_original_post_id );

        if ( $auto_translation_trid > 0 ) {
            update_post_meta( $post_id, 'wpr_translated_trid', $auto_translation_trid );
        }

    }

    return true;
}

/**
 * Log translated Elementor fields for debugging purposes.
 *
 * @param array $translated_payload Payload returned by the translation engine.
 */
function wpr_translate_log_translated_elementor_data( $translated_payload ) {
    // Skip logging if no Elementor data was translated.
    if ( ! isset( $translated_payload['post_meta_fields']['_elementor_data'] ) ) {
        return;
    }

    // Extract text nodes from the translated Elementor JSON.
    $text_nodes = wpr_translate_extract_elementor_text_fields( $translated_payload['post_meta_fields']['_elementor_data'] );

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

}

/**
 * Log translated WPBakery fields for debugging purposes.
 *
 * @param array $translated_payload Payload returned by the translation engine.
 */
function wpr_translate_log_translated_wpbakery_data( $translated_payload ) {
    // Skip logging if no WPBakery data was translated.
    if ( ! isset( $translated_payload['post_meta_fields']['_wpbakery_fields'] ) ) {
        return;
    }

    // Sanitize the translated fields before logging.
    $fields = $translated_payload['post_meta_fields']['_wpbakery_fields'];
    $fields = is_array( $fields ) ? array_filter( array_map( 'wp_strip_all_tags', $fields ) ) : array();

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

}

/**
 * Sanitize translated values recursively.
 *
 * @param mixed $value Value to sanitize.
 *
 * @return mixed
 */
function wpr_translate_sanitize_translated_value( $value ) {
    // Recursively sanitize arrays while preserving structure.
    if ( is_array( $value ) ) {
        $clean_value = array();

        foreach ( $value as $key => $sub_value ) {
            $clean_key               = is_string( $key ) ? sanitize_text_field( $key ) : $key;
            $clean_value[ $clean_key ] = wpr_translate_sanitize_translated_value( $sub_value );
        }

        return $clean_value;
    }

    // Allow safe HTML for translated strings.
    if ( is_string( $value ) ) {
        return wp_kses_post( $value );
    }

    // Preserve numeric values.
    if ( is_int( $value ) || is_float( $value ) ) {
        return $value;
    }

    // Preserve boolean values.
    if ( is_bool( $value ) ) {
        return (bool) $value;
    }

    // Return any other types unchanged.
    return $value;
}

/**
 * Apply translated post meta fields to the translated post.
 *
 * @param int   $post_id            Post identifier that will receive translated meta.
 * @param array $translated_payload Translated payload returned by the engine.
 *
 * @return void
 */
function wpr_translate_apply_translated_post_meta_fields( $post_id, $translated_payload ) {
    $post_id            = absint( $post_id );
    $translated_payload = is_array( $translated_payload ) ? $translated_payload : array();

    if ( $post_id <= 0 ) {
        return;
    }

    // Accept translated meta from either the current or legacy payload keys.
    $meta_payload = array();

    if ( isset( $translated_payload['post_meta_fields'] ) && is_array( $translated_payload['post_meta_fields'] ) ) {
        $meta_payload = $translated_payload['post_meta_fields'];
    } elseif ( isset( $translated_payload['custom_fields'] ) && is_array( $translated_payload['custom_fields'] ) ) {
        $meta_payload = $translated_payload['custom_fields'];
    }

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

    // Allow only fields configured with the "translate" rule for this post type.
    $allowed_meta_keys = array();
    $post_type         = sanitize_key( get_post_type( $post_id ) );

    if ( function_exists( 'wpr_translate_get_custom_field_rules' ) ) {
        $rules = wpr_translate_get_custom_field_rules();
        $rules = is_array( $rules ) ? $rules : array();

        foreach ( $rules as $rule ) {
            if ( ! is_array( $rule ) ) {
                continue;
            }

            $raw_meta_key = isset( $rule['id'] ) && is_string( $rule['id'] ) ? trim( $rule['id'] ) : '';
            $action       = isset( $rule['action'] ) ? sanitize_key( $rule['action'] ) : '';
            $rule_post    = isset( $rule['post'] ) && is_string( $rule['post'] ) ? sanitize_key( $rule['post'] ) : '';

            if ( '' === $raw_meta_key || 'translate' !== $action ) {
                continue;
            }

            if ( '' !== $rule_post && '' !== $post_type && $rule_post !== $post_type ) {
                continue;
            }

            $allowed_meta_keys[ $raw_meta_key ] = true;
        }
    }

    foreach ( $meta_payload as $meta_key => $meta_value ) {
        $raw_meta_key = is_string( $meta_key ) ? trim( $meta_key ) : '';

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

        if ( ! empty( $allowed_meta_keys ) && ! isset( $allowed_meta_keys[ $raw_meta_key ] ) ) {
            continue;
        }

        // Elementor/WPBakery payloads are handled by dedicated processors.
        if ( in_array( $raw_meta_key, array( '_elementor_data', '_wpbakery_fields' ), true ) ) {
            continue;
        }

        update_post_meta( $post_id, $raw_meta_key, wpr_translate_sanitize_translated_value( $meta_value ) );
    }
}

/**
 * Apply translated taxonomy assignments for a given post.
 *
 * @param int    $post_id                Post ID being updated.
 * @param array  $translated_payload     Payload returned by the translation engine.
 * @param string $target_language        Target language identifier.
 * @param string $target_language_code   Target language code.
 * @param string $target_language_slug   Target language slug.
 * @param string $target_language_locale Target language locale.
 *
 * @return true|WP_Error
 */
function wpr_translate_apply_translated_taxonomies( $post_id, $translated_payload, $target_language, $target_language_code, $target_language_slug, $target_language_locale ) {
    // Collect taxonomy payloads from the translated response.
    $taxonomy_payloads = array();
    $source_post_id = 0;

    // Normalize input to handle both 'taxonomy' and 'taxonomies' keys
    if ( isset( $translated_payload['taxonomy'] ) && is_array( $translated_payload['taxonomy'] ) ) {
        foreach ( $translated_payload['taxonomy'] as $taxonomy => $taxonomy_data ) {
            $taxonomy_payloads[ $taxonomy ] = $taxonomy_data;
        }
    }

    if ( isset( $translated_payload['taxonomies'] ) && is_array( $translated_payload['taxonomies'] ) ) {
        foreach ( $translated_payload['taxonomies'] as $taxonomy => $taxonomy_data ) {
            $taxonomy_payloads[ $taxonomy ] = $taxonomy_data;
        }
    }

    if ( isset( $translated_payload['_wpr_source_post_id'] ) ) {
        $source_post_id = absint( $translated_payload['_wpr_source_post_id'] );
    } elseif ( isset( $translated_payload['original_post_id'] ) ) {
        $source_post_id = absint( $translated_payload['original_post_id'] );
    }

    if ( $source_post_id <= 0 ) {
        $source_post_id = absint( $post_id );
    }

    wpr_translate_taxonomy_apply_error_log(
        'apply_start',
        array(
            'post_id'              => $post_id,
            'source_post_id'       => $source_post_id,
            'target_language'      => $target_language,
            'target_language_code' => $target_language_code,
            'target_language_slug' => $target_language_slug,
            'taxonomy_payloads'    => $taxonomy_payloads,
        )
    );

    // Early exit if there's no taxonomy data.
    if ( empty( $taxonomy_payloads ) ) {
        wpr_translate_taxonomy_apply_error_log(
            'apply_skip_empty_payload',
            array(
                'post_id'        => $post_id,
                'source_post_id' => $source_post_id,
            )
        );
        return true;
    }


    // Process each taxonomy.
    foreach ( $taxonomy_payloads as $taxonomy => $taxonomy_data ) {
        $sanitized_taxonomy = sanitize_key( $taxonomy );

        // Skip if invalid taxonomy.
        if ( '' === $sanitized_taxonomy || ! taxonomy_exists( $sanitized_taxonomy ) ) {
            wpr_translate_taxonomy_apply_error_log(
                'apply_skip_invalid_taxonomy',
                array(
                    'post_id'   => $post_id,
                    'taxonomy'  => $taxonomy,
                    'sanitized' => $sanitized_taxonomy,
                )
            );
            continue;
        }

        $term_inputs           = array();
        $element_type          = '';
        $target_term_language  = '';

        // Attempt to get the element type for WPML/translation tracking.
        if ( '' !== $target_language && function_exists( 'wpr_translation_get_taxonomy_element_type' ) ) {
            $element_type = sanitize_key( wpr_translation_get_taxonomy_element_type( $sanitized_taxonomy ) );
        }

        if ( '' !== $target_language_code ) {
            $target_term_language = sanitize_key( $target_language_code );
        } elseif ( '' !== $target_language ) {
            $target_term_language = sanitize_key( $target_language );
        }

        $source_terms_by_id        = array();
        $source_terms_by_slug      = array();
        $source_terms = wp_get_object_terms(
            $source_post_id,
            $sanitized_taxonomy,
            array(
                'hide_empty' => false,
            )
        );

        if ( ! is_wp_error( $source_terms ) && ! empty( $source_terms ) ) {
            foreach ( $source_terms as $source_term ) {
                if ( ! ( $source_term instanceof WP_Term ) ) {
                    continue;
                }

                $source_term_entry = array(
                    'term_id' => (int) $source_term->term_id,
                    'slug'    => sanitize_title( $source_term->slug ),
                    'name'    => sanitize_text_field( $source_term->name ),
                );

                $source_terms_by_id[ $source_term_entry['term_id'] ] = $source_term_entry;

                if ( '' !== $source_term_entry['slug'] ) {
                    $source_terms_by_slug[ $source_term_entry['slug'] ] = $source_term_entry;
                }
            }
        }

        wpr_translate_taxonomy_apply_error_log(
            'apply_taxonomy_input',
            array(
                'post_id'               => $post_id,
                'taxonomy'              => $sanitized_taxonomy,
                'target_term_language'  => $target_term_language,
                'source_terms_by_id'    => $source_terms_by_id,
                'incoming_taxonomy_data'=> $taxonomy_data,
            )
        );

        if ( isset( $taxonomy_data['terms'] ) && is_array( $taxonomy_data['terms'] ) ) {
            // Loop over each term in the taxonomy.
            foreach ( $taxonomy_data['terms'] as $term_entry ) {
                $term_id_to_assign = 0;
                $response_term_id  = isset( $term_entry['term_id'] ) ? absint( $term_entry['term_id'] ) : 0;
                $term_name         = isset( $term_entry['name'] ) ? sanitize_text_field( (string) $term_entry['name'] ) : '';
                $term_slug         = isset( $term_entry['slug'] ) ? sanitize_title( (string) $term_entry['slug'] ) : '';
                $source_term_entry = array();

                if ( $response_term_id > 0 && function_exists( 'wpr_translate_resolve_original_term_id' ) ) {
                    $response_term_id = absint( wpr_translate_resolve_original_term_id( $response_term_id, $sanitized_taxonomy ) );
                }

                if ( $response_term_id > 0 && isset( $source_terms_by_id[ $response_term_id ] ) ) {
                    $source_term_entry = $source_terms_by_id[ $response_term_id ];
                } elseif ( '' !== $term_slug && isset( $source_terms_by_slug[ $term_slug ] ) ) {
                    $source_term_entry = $source_terms_by_slug[ $term_slug ];
                }

                $term_parent       = isset( $term_entry['parent'] ) ? absint( $term_entry['parent'] ) : 0;
                $has_description   = is_array( $term_entry ) && array_key_exists( 'description', $term_entry );
                $has_tagline       = is_array( $term_entry ) && array_key_exists( 'category_tagline', $term_entry );
                $term_description  = $has_description ? wp_kses_post( (string) $term_entry['description'] ) : '';
                $term_tagline      = $has_tagline ? wp_kses_post( (string) $term_entry['category_tagline'] ) : '';
                $copied_meta_keys  = array();
                $copied_option_keys = array();
                $copied_meta_values = array();
                $copied_option_values = array();
                $saved_translated_meta = array();
                $source_term_description = '';
                $source_term_tagline = '';
                $source_term_object = null;
                $original_term_id = isset( $source_term_entry['term_id'] ) ? absint( $source_term_entry['term_id'] ) : 0;

                if (
                    $original_term_id > 0
                    && function_exists( 'wpr_translate_resolve_original_term_id' )
                ) {
                    $original_term_id = absint( wpr_translate_resolve_original_term_id( $original_term_id, $sanitized_taxonomy ) );
                }

                if ( '' === $term_name && isset( $source_term_entry['name'] ) ) {
                    $term_name = sanitize_text_field( (string) $source_term_entry['name'] );
                }

                if ( '' === $term_slug && isset( $source_term_entry['slug'] ) ) {
                    $term_slug = sanitize_title( (string) $source_term_entry['slug'] );
                }

                if ( $original_term_id > 0 ) {
                    $source_term_object = get_term( $original_term_id, $sanitized_taxonomy );

                    if ( ! ( $source_term_object instanceof WP_Term ) ) {
                        $original_term_id = 0;
                    }
                }

                if ( $original_term_id > 0 && $source_term_object instanceof WP_Term ) {
                    $source_term_description = is_string( $source_term_object->description ) ? (string) $source_term_object->description : '';
                }

                if ( $original_term_id > 0 ) {
                    $source_term_option_for_log = get_option( 'taxonomy_' . $original_term_id, array() );

                    if ( is_array( $source_term_option_for_log ) && isset( $source_term_option_for_log['category_tagline'] ) ) {
                        $source_term_tagline = is_string( $source_term_option_for_log['category_tagline'] ) ? (string) $source_term_option_for_log['category_tagline'] : '';
                    }
                }

                if ( $original_term_id <= 0 ) {
                    wpr_translate_taxonomy_apply_error_log(
                        'apply_term_skip_missing_original',
                        array(
                            'post_id'         => $post_id,
                            'taxonomy'        => $sanitized_taxonomy,
                            'response_term_id'=> $response_term_id,
                            'term_slug'       => $term_slug,
                            'term_name'       => $term_name,
                        )
                    );
                    continue;
                }

                // Try to retrieve the translation group (trid).
                $group = ( $original_term_id && '' !== $element_type && function_exists( 'wpr_translation_get_translation_group' ) ) ? wpr_translation_get_translation_group( $original_term_id, $element_type ) : array();

                $resolved_translation_id = 0;

                if ( $original_term_id > 0 && '' !== $target_term_language && function_exists( 'wpr_translate_lookup_translated_term_id_strict' ) ) {
                    $meta_first_translation = wpr_translate_lookup_translated_term_id_strict( $original_term_id, $sanitized_taxonomy, $target_term_language );

                    if ( is_numeric( $meta_first_translation ) ) {
                        $meta_first_translation = absint( $meta_first_translation );

                        if ( $meta_first_translation > 0 ) {
                            $resolved_translation_id = $meta_first_translation;
                        }
                    }
                }

                if (
                    0 === $resolved_translation_id
                    && '' !== $target_term_language
                    && isset( $group['translations'][ $target_term_language ] )
                ) {
                    $resolved_translation_id = absint( $group['translations'][ $target_term_language ] );
                }

                $has_valid_translation = ( $resolved_translation_id > 0 );

                if ( $has_valid_translation && $original_term_id > 0 && $resolved_translation_id === $original_term_id ) {
                    // Treat invalid self-referential translation mappings as missing.
                    $has_valid_translation = false;
                }

                $trid_exists = isset( $group['trid'] ) && intval( $group['trid'] ) > 0;

                // Create a translated term when no valid mapping is available.
                if ( ! $has_valid_translation ) {
                    // Let WordPress generate the slug from the translated name.
                    // Keep a local seed only for the fallback collision retry path.
                    $term_slug_base = sanitize_title( $term_name );

                    if ( '' === $term_slug_base ) {
                        $term_slug_base = $term_slug;
                    }

                    $term_args = array();

                    if ( $term_parent > 0 ) {
                        $term_args['parent'] = $term_parent;
                    }

                    if ( $has_description ) {
                        $term_args['description'] = $term_description;
                    }

                    // Create new term using the sanitized payload.
                    $inserted_term = wp_insert_term(
                        $term_name,
                        $sanitized_taxonomy,
                        $term_args
                    );



                    // Handle error or resolve the term ID.
                    if ( is_wp_error( $inserted_term ) ) {
                        if ( 'term_exists' === $inserted_term->get_error_code() ) {
                            $existing_term_id = (int) $inserted_term->get_error_data();

                            if ( $existing_term_id > 0 && $existing_term_id !== $original_term_id ) {
                                $term_id_to_assign = $existing_term_id;
                            } elseif ( $existing_term_id === $original_term_id && '' !== $target_term_language ) {
                                // When slug collides with the original term, retry once with language suffix.
                                $fallback_seed = '' !== $term_slug_base ? $term_slug_base : sanitize_title( $term_name );
                                $fallback_slug = sanitize_title( $fallback_seed . '-' . $target_term_language );

                                if ( '' !== $fallback_slug ) {
                                    $retry_args         = $term_args;
                                    $retry_args['slug'] = $fallback_slug;

                                    $retry_inserted_term = wp_insert_term(
                                        $term_name,
                                        $sanitized_taxonomy,
                                        $retry_args
                                    );

                                    if ( is_wp_error( $retry_inserted_term ) ) {
                                        if ( 'term_exists' === $retry_inserted_term->get_error_code() ) {
                                            $retry_term_id = (int) $retry_inserted_term->get_error_data();

                                            if ( $retry_term_id > 0 && $retry_term_id !== $original_term_id ) {
                                                $term_id_to_assign = $retry_term_id;
                                            }
                                        }
                                    } elseif ( isset( $retry_inserted_term['term_id'] ) ) {
                                        $term_id_to_assign = (int) $retry_inserted_term['term_id'];
                                    }
                                }
                            }
                        }
                    } elseif ( isset( $inserted_term['term_id'] ) ) {
                        $term_id_to_assign = (int) $inserted_term['term_id'];
                    }




                    // Persist bidirectional term meta links for new/reused terms.
                    if (
                        $term_id_to_assign > 0
                        && $original_term_id > 0
                        && '' !== $target_term_language
                        && function_exists( 'wpr_translate_link_term_translation_meta' )
                    ) {
                        wpr_translate_link_term_translation_meta( $original_term_id, $term_id_to_assign, $target_term_language, $sanitized_taxonomy );
                    }

                    if (
                        $term_id_to_assign > 0
                        && $original_term_id > 0
                        && $term_id_to_assign !== $original_term_id
                        && function_exists( 'wpr_translation_duplicate_term_meta' )
                    ) {
                        $source_term_meta = get_term_meta( $original_term_id );
                        if ( is_array( $source_term_meta ) ) {
                            $copied_meta_keys = array_values( array_map( 'sanitize_key', array_keys( $source_term_meta ) ) );

                            foreach ( $source_term_meta as $meta_key => $meta_values ) {
                                $clean_meta_key = sanitize_key( $meta_key );
                                $copied_meta_values[ $clean_meta_key ] = array();

                                if ( ! is_array( $meta_values ) ) {
                                    continue;
                                }

                                foreach ( $meta_values as $meta_value ) {
                                    $copied_meta_values[ $clean_meta_key ][] = maybe_unserialize( $meta_value );
                                }
                            }
                        }

                        $source_term_option = get_option( 'taxonomy_' . $original_term_id, array() );
                        if ( is_array( $source_term_option ) ) {
                            $copied_option_keys = array_values( array_map( 'sanitize_key', array_keys( $source_term_option ) ) );
                            $copied_option_values = $source_term_option;
                        }

                        // Keep media/maps/documents/custom term metadata aligned with the source term.
                        wpr_translation_duplicate_term_meta( $original_term_id, $term_id_to_assign );
                    }

                    if ( $term_id_to_assign > 0 && '' !== $term_name ) {
                        $name_update_result = wp_update_term(
                            $term_id_to_assign,
                            $sanitized_taxonomy,
                            array(
                                'name' => $term_name,
                            )
                        );

                        $saved_translated_meta['name'] = array(
                            'value' => $term_name,
                            'saved' => is_wp_error( $name_update_result ) ? 'no' : 'yes',
                        );
                    }

                    if ( $term_id_to_assign > 0 && $has_description ) {
                        $description_result = wp_update_term(
                            $term_id_to_assign,
                            $sanitized_taxonomy,
                            array(
                                'description' => $term_description,
                            )
                        );

                        $saved_translated_meta['description'] = array(
                            'value' => $term_description,
                            'saved' => is_wp_error( $description_result ) ? 'no' : 'yes',
                        );
                    }

                    if ( $term_id_to_assign > 0 && $has_tagline ) {
                        $term_option_payload = get_option( 'taxonomy_' . $term_id_to_assign, array() );
                        $term_option_payload = is_array( $term_option_payload ) ? $term_option_payload : array();
                        $term_option_payload['category_tagline'] = $term_tagline;
                        $saved_translated_meta['category_tagline'] = array(
                            'value' => $term_tagline,
                            'saved' => update_option( 'taxonomy_' . $term_id_to_assign, $term_option_payload ) ? 'yes' : 'no',
                        );
                    }

                    // Reuse existing TRID when available; create a new group only when missing.
                    if ( $term_id_to_assign > 0 && '' !== $element_type && function_exists( 'wpr_translation_insert_translation_record' ) ) {
                        $translation_trid = $trid_exists ? absint( $group['trid'] ) : 0;

                        if ( $translation_trid <= 0 && function_exists( 'wpr_translation_generate_trid' ) ) {
                            $translation_trid = absint( wpr_translation_generate_trid() );
                        }

                        if ( $translation_trid > 0 ) {
                            $source_language = isset( $group['source_language'] ) ? sanitize_key( $group['source_language'] ) : '';

                            if ( '' === $source_language && function_exists( 'wpr_translation_get_active_languages' ) && function_exists( 'wpr_translation_get_default_language_code' ) ) {
                                $languages        = wpr_translation_get_active_languages();
                                $source_language = sanitize_key( wpr_translation_get_default_language_code( $languages ) );
                            }

                            if ( '' === $source_language ) {
                                $source_language = $target_term_language;
                            }

                            if ( $original_term_id > 0 ) {
                                // Ensure the source term remains registered in the shared translation group.
                                wpr_translation_insert_translation_record( $original_term_id, $element_type, $translation_trid, $source_language, '', 'publish', true );
                            }

                            // Register the translated term inside the same translation group.
                            wpr_translation_insert_translation_record( $term_id_to_assign, $element_type, $translation_trid, $target_term_language, $source_language, 'publish', false );
                        }
                    }

                    // Assign and move to next term.
                    wpr_translate_taxonomy_apply_error_log(
                        'apply_term_after_insert_branch',
                        array(
                            'post_id'                 => $post_id,
                            'taxonomy'                => $sanitized_taxonomy,
                            'target_term_language'    => $target_term_language,
                            'original_term_id'        => $original_term_id,
                            'resolved_translation_id' => $resolved_translation_id,
                            'term_id_to_assign'       => $term_id_to_assign,
                            'term_slug'               => $term_slug,
                            'term_name'               => $term_name,
                        )
                    );
                    $term_inputs[] = $term_id_to_assign;
                    continue;
                }

                // If translation already exists, reuse it.
                if ( $has_valid_translation ) {
                    $term_id_to_assign = $resolved_translation_id;

                    if (
                        $term_id_to_assign > 0
                        && $original_term_id > 0
                        && '' !== $target_term_language
                        && function_exists( 'wpr_translate_link_term_translation_meta' )
                    ) {
                        wpr_translate_link_term_translation_meta( $original_term_id, $term_id_to_assign, $target_term_language, $sanitized_taxonomy );
                    }

                    if (
                        $term_id_to_assign > 0
                        && $original_term_id > 0
                        && $term_id_to_assign !== $original_term_id
                        && function_exists( 'wpr_translation_duplicate_term_meta' )
                    ) {
                        $source_term_meta = get_term_meta( $original_term_id );
                        if ( is_array( $source_term_meta ) ) {
                            $copied_meta_keys = array_values( array_map( 'sanitize_key', array_keys( $source_term_meta ) ) );

                            foreach ( $source_term_meta as $meta_key => $meta_values ) {
                                $clean_meta_key = sanitize_key( $meta_key );
                                $copied_meta_values[ $clean_meta_key ] = array();

                                if ( ! is_array( $meta_values ) ) {
                                    continue;
                                }

                                foreach ( $meta_values as $meta_value ) {
                                    $copied_meta_values[ $clean_meta_key ][] = maybe_unserialize( $meta_value );
                                }
                            }
                        }

                        $source_term_option = get_option( 'taxonomy_' . $original_term_id, array() );
                        if ( is_array( $source_term_option ) ) {
                            $copied_option_keys = array_values( array_map( 'sanitize_key', array_keys( $source_term_option ) ) );
                            $copied_option_values = $source_term_option;
                        }

                        // Keep media/maps/documents/custom term metadata aligned with the source term.
                        wpr_translation_duplicate_term_meta( $original_term_id, $term_id_to_assign );
                    }

                    if ( $term_id_to_assign > 0 && '' !== $term_name ) {
                        $name_update_result = wp_update_term(
                            $term_id_to_assign,
                            $sanitized_taxonomy,
                            array(
                                'name' => $term_name,
                            )
                        );

                        $saved_translated_meta['name'] = array(
                            'value' => $term_name,
                            'saved' => is_wp_error( $name_update_result ) ? 'no' : 'yes',
                        );
                    }

                    if ( $term_id_to_assign > 0 && $has_description ) {
                        $description_result = wp_update_term(
                            $term_id_to_assign,
                            $sanitized_taxonomy,
                            array(
                                'description' => $term_description,
                            )
                        );

                        $saved_translated_meta['description'] = array(
                            'value' => $term_description,
                            'saved' => is_wp_error( $description_result ) ? 'no' : 'yes',
                        );
                    }

                    if ( $term_id_to_assign > 0 && $has_tagline ) {
                        $term_option_payload = get_option( 'taxonomy_' . $term_id_to_assign, array() );
                        $term_option_payload = is_array( $term_option_payload ) ? $term_option_payload : array();
                        $term_option_payload['category_tagline'] = $term_tagline;
                        $saved_translated_meta['category_tagline'] = array(
                            'value' => $term_tagline,
                            'saved' => update_option( 'taxonomy_' . $term_id_to_assign, $term_option_payload ) ? 'yes' : 'no',
                        );
                    }

                    wpr_translate_taxonomy_apply_error_log(
                        'apply_term_existing_translation_branch',
                        array(
                            'post_id'                 => $post_id,
                            'taxonomy'                => $sanitized_taxonomy,
                            'target_term_language'    => $target_term_language,
                            'original_term_id'        => $original_term_id,
                            'resolved_translation_id' => $resolved_translation_id,
                            'term_id_to_assign'       => $term_id_to_assign,
                            'term_slug'               => $term_slug,
                            'term_name'               => $term_name,
                        )
                    );
                    $term_inputs[] = $term_id_to_assign;
                    continue;
                }
            }
        }

        // Sanitize and assign unique terms.
        $term_inputs = array_filter( array_unique( array_map( 'absint', $term_inputs ) ) );

        wpr_translate_taxonomy_apply_error_log(
            'apply_taxonomy_before_set_terms',
            array(
                'post_id'      => $post_id,
                'taxonomy'     => $sanitized_taxonomy,
                'term_inputs'  => $term_inputs,
                'source_post_id'=> $source_post_id,
            )
        );

        // Assign the terms to the post.
        $set_terms = wp_set_object_terms( $post_id, $term_inputs, $sanitized_taxonomy, false );

        wpr_translate_taxonomy_apply_error_log(
            'apply_taxonomy_after_set_terms',
            array(
                'post_id'     => $post_id,
                'taxonomy'    => $sanitized_taxonomy,
                'set_terms'   => $set_terms,
                'is_wp_error' => is_wp_error( $set_terms ) ? 'yes' : 'no',
            )
        );

        // Fail if term assignment fails.
        if ( is_wp_error( $set_terms ) ) {
            return new WP_Error( 'wpr_translate_terms_update_failed', __( 'Failed to update translated taxonomy terms.', 'wpr-translate' ) );
        }
    }

    // Return success.
    return true;
}

/**
 * Write taxonomy apply debug traces to error log using print_r.
 *
 * @param string $stage   Debug stage label.
 * @param mixed  $payload Debug payload.
 *
 * @return void
 */
function wpr_translate_taxonomy_apply_error_log( $stage, $payload ) {
    unset( $stage, $payload );
}

