<?php
/**
 * Plugin Name: AISmart Content Studio
 * Plugin URI: https://aismartcontent.co/blog
 * Description: Connects WordPress to AISmartContent for onboarding, workspace linking, and AI token/content operations from wp-admin.
 * Version: 1.0
 * Author: AISmartContent.co,ltd
 * Author URI: https://aismartcontent.co
 * License: GPLv2 or later
 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain: aismart-content-studio
 * Domain Path: /languages
 * Copyright: AISmartContent.co,ltd
 */


function aismart_get_laravel_root() {
    $candidates = [
        '/home/neverlearning/app.smartlearning.in.th',
        '/home/neverlearning/app.neverlearning.com',
        '/home/cafealth/public_html',
        ABSPATH . '../app.smartlearning.in.th'
    ];
    foreach ($candidates as $cand) {
        if (is_dir($cand)) {
            return $cand;
        }
    }
    return '';
}

function aismart_get_artisan_path() {
    $root = aismart_get_laravel_root();
    if ($root !== '' && file_exists($root . '/artisan')) {
        return $root . '/artisan';
    }
    return '';
}

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

if (!defined('AISMART_API_DEFAULT_TIMEOUT')) {
    define('AISMART_API_DEFAULT_TIMEOUT', 60);
}
if (!defined('AISMART_API_FALLBACK_HOST_TIMEOUT')) {
    // Avoid premature local fallback when upstream text/image generation needs more time.
    define('AISMART_API_FALLBACK_HOST_TIMEOUT', 40);
}
if (!defined('AISMART_API_SLOW_HOST')) {
    define('AISMART_API_SLOW_HOST', 'aismartcontent.co');
}

use Illuminate\Support\Facades\DB;
use Illuminate\Filesystem\FilesystemServiceProvider;
use Illuminate\Support\Facades\Log;

function aismart_enqueue_inline_style($handle, $css) {
    $handle = sanitize_key((string) $handle);
    if ($handle === '') {
        $handle = 'aismart-inline-style';
    }

    wp_register_style($handle, false, [], null);
    wp_enqueue_style($handle);
    wp_add_inline_style($handle, (string) $css);
}

function aismart_enqueue_inline_script($handle, $js) {
    $handle = sanitize_key((string) $handle);
    if ($handle === '') {
        $handle = 'aismart-inline-script';
    }

    wp_register_script($handle, false, [], null, true);
    wp_enqueue_script($handle);
    wp_add_inline_script($handle, (string) $js, 'after');
}

function aismart_dependency_paths() {
    return [
        'autoload' => __DIR__ . '/aismart-core/vendor/autoload.php',
        'bootstrap' => __DIR__ . '/aismart-core/bootstrap/app.php',
    ];
}

function aismart_missing_dependencies() {
    $paths = aismart_dependency_paths();
    $missing = [];

    foreach ($paths as $key => $path) {
        if (!file_exists($path)) {
            $missing[$key] = $path;
        }
    }

    return $missing;
}

function aismart_get_recovery_command() {
    return 'cd wp-content/plugins/aismart-token/aismart-core && composer install --no-dev --optimize-autoloader --no-interaction';
}

function aismart_get_recovery_steps($manual_command = '') {
    $manual_command = trim((string) $manual_command);
    if ($manual_command === '') {
        $manual_command = aismart_get_recovery_command();
    }

    $parts = preg_split('/\s*&&\s*/', $manual_command);
    if (!is_array($parts)) {
        $parts = [];
    }

    $steps = [];
    foreach ($parts as $part) {
        $line = trim((string) $part);
        if ($line !== '') {
            $steps[] = $line;
        }
    }

    if (count($steps) < 2) {
        $steps = [
            'cd wp-content/plugins/aismart-token/aismart-core',
            'composer install --no-dev --optimize-autoloader --no-interaction',
        ];
    }

    return $steps;
}

function aismart_get_activation_url($run_composer = false) {
    $plugin = plugin_basename(__FILE__);
    $url = wp_nonce_url(
        admin_url('plugins.php?action=activate&plugin=' . rawurlencode($plugin)),
        'activate-plugin_' . $plugin
    );

    if ($run_composer) {
        $url = add_query_arg('aismart_run_composer_install', '1', $url);
    }

    return $url;
}

function aismart_render_recovery_panel_html($args = []) {
    $defaults = [
        'title' => 'AISmart Content Studio setup needs one more step',
        'intro' => 'Some required files are missing, so WordPress paused activation to keep your site safe.',
        'button_label' => 'Run Automatic Fix (Composer Install)',
        'button_url' => '',
        'manual_command' => '',
        'missing_files_html' => '',
        'output_html' => '',
        'show_no_ssh_help' => true,
    ];

    $data = wp_parse_args($args, $defaults);
    $button_url = $data['button_url'] !== '' ? '<p style="margin:14px 0;"><a class="button button-primary button-large" href="' . esc_url($data['button_url']) . '">' . esc_html($data['button_label']) . '</a></p>' : '';
    $manual = '';
    if ($data['manual_command'] !== '') {
        $steps = aismart_get_recovery_steps($data['manual_command']);
        $steps_html = '';
        foreach ($steps as $idx => $step_line) {
            $steps_html .= '<li><code>' . esc_html($step_line) . '</code></li>';
        }

        $manual = '<p style="margin:10px 0 6px;"><strong>Manual command (SSH/Terminal):</strong></p>'
            . '<p><code style="display:inline-block;padding:6px 8px;background:#f6f7f7;border:1px solid #dcdcde;">' . esc_html($data['manual_command']) . '</code></p>'
            . '<p style="margin:10px 0 6px;"><strong>Beginner step-by-step (run one line at a time):</strong></p>'
            . '<ol style="margin:0 0 0 18px;">' . $steps_html . '</ol>';
    }
    $missing = $data['missing_files_html'] !== '' ? '<p style="margin:12px 0 6px;"><strong>Missing files:</strong></p><ul style="margin:0 0 0 18px;list-style:disc;">' . $data['missing_files_html'] . '</ul>' : '';
    $output = $data['output_html'];
    $no_ssh_help = '';

    if (!empty($data['show_no_ssh_help']) && $data['manual_command'] !== '') {
        $support_text = "Hello Hosting Support,\n\nPlease run this command on my WordPress server to install plugin dependencies:\n" . $data['manual_command'] . "\n\nThen please confirm when complete.\nThank you.";
        $no_ssh_help = '<div style="margin-top:14px;padding:12px;border:1px solid #dcdcde;background:#f8fff8;">'
            . '<p style="margin:0 0 8px;"><strong>No SSH access? Use this beginner path:</strong></p>'
            . '<ol style="margin:0 0 0 18px;">'
            . '<li>Open your hosting control panel (usually cPanel or Plesk).</li>'
            . '<li>Try <strong>Terminal</strong> and run the manual command above.</li>'
            . '<li>If Terminal is not available, send this message to hosting support:</li>'
            . '</ol>'
            . '<textarea readonly style="width:100%;min-height:120px;margin-top:8px;font-family:monospace;">' . esc_textarea($support_text) . '</textarea>'
            . '</div>';
    }

    return '<div style="max-width:860px;background:#fff;border:1px solid #dcdcde;border-left:4px solid #00a32a;padding:18px 20px;border-radius:2px;">'
        . '<h2 style="margin:0 0 8px;font-size:20px;line-height:1.35;">' . esc_html($data['title']) . '</h2>'
        . '<p style="margin:0 0 12px;">' . esc_html($data['intro']) . '</p>'
        . '<p style="margin:0 0 6px;"><strong>Quick steps for admin:</strong></p>'
        . '<ol style="margin:0 0 0 18px;">'
        . '<li>Click the button below to run the automatic fix.</li>'
        . '<li>Wait until the page finishes loading.</li>'
        . '<li>Activate AISmart Content Studio again if needed.</li>'
        . '</ol>'
        . $button_url
        . $missing
        . $manual
        . $no_ssh_help
        . $output
        . '</div>';
}

function aismart_flash_key() {
    $user_id = function_exists('get_current_user_id') ? (int) get_current_user_id() : 0;
    return 'aismart_recovery_flash_' . $user_id;
}

function aismart_activation_redirect_flag_key() {
    $user_id = function_exists('get_current_user_id') ? (int) get_current_user_id() : 0;
    return 'aismart_activation_redirect_' . $user_id;
}

function aismart_mark_activation_redirect() {
    set_transient(aismart_activation_redirect_flag_key(), '1', 180);
}

function aismart_consume_activation_redirect_flag() {
    $key = aismart_activation_redirect_flag_key();
    $value = get_transient($key);
    if ($value === false) {
        return false;
    }

    delete_transient($key);
    return true;
}

function aismart_set_recovery_flash($payload) {
    set_transient(aismart_flash_key(), $payload, 180);
}

function aismart_get_recovery_flash() {
    $payload = get_transient(aismart_flash_key());
    if ($payload !== false) {
        delete_transient(aismart_flash_key());
    }

    return is_array($payload) ? $payload : null;
}

function aismart_shell_function_available($name) {
    if (!function_exists($name)) {
        return false;
    }

    $disabled = ini_get('disable_functions');
    if (!is_string($disabled) || $disabled === '') {
        return true;
    }

    $disabled_list = array_map('trim', explode(',', $disabled));
    return !in_array($name, $disabled_list, true);
}

function aismart_detect_composer_binary() {
    $candidates = [];

    $path = getenv('PATH');
    if (is_string($path) && $path !== '') {
        foreach (explode(PATH_SEPARATOR, $path) as $dir) {
            $dir = trim((string) $dir);
            if ($dir !== '') {
                $candidates[] = rtrim($dir, '/\\') . '/composer';
            }
        }
    }

    $candidates[] = '/opt/cpanel/composer/bin/composer';
    $candidates[] = '/usr/local/bin/composer';
    $candidates[] = '/usr/bin/composer';
    $candidates[] = '/bin/composer';
    $candidates[] = __DIR__ . '/aismart-core/composer.phar';

    $candidates = array_values(array_unique($candidates));

    foreach ($candidates as $candidate) {
        if (is_string($candidate) && $candidate !== '' && file_exists($candidate) && is_executable($candidate)) {
            $is_phar = substr($candidate, -5) === '.phar';
            return [
                'found' => true,
                'binary' => $candidate,
                'is_phar' => $is_phar,
                'checked' => $candidates,
            ];
        }
    }

    return [
        'found' => false,
        'binary' => '',
        'is_phar' => false,
        'checked' => $candidates,
    ];
}

function aismart_build_composer_missing_help_html($core_dir) {
    $core_dir = rtrim((string) $core_dir, '/');
    $manual = aismart_get_recovery_command();

    $commands = [
        'cd ' . $core_dir,
        '/opt/cpanel/composer/bin/composer --version',
        '/opt/cpanel/composer/bin/composer install --no-dev --optimize-autoloader --no-interaction',
        '',
        '# If the cPanel Composer path above is unavailable, ask hosting/dev to install Composer and run:',
        $manual,
    ];

    $text = implode("\n", $commands);

    return '<div style="margin-top:12px;padding:12px;border:1px solid #dba617;background:#fff8e5;">'
        . '<p style="margin:0 0 8px;"><strong>Composer is missing in server shell.</strong></p>'
        . '<p style="margin:0 0 8px;">Use these copy-ready commands in cPanel Terminal:</p>'
        . '<textarea readonly style="width:100%;min-height:150px;font-family:monospace;">' . esc_textarea($text) . '</textarea>'
        . '</div>';
}

function aismart_build_shell_disabled_help_html($core_dir) {
    $core_dir = rtrim((string) $core_dir, '/');
    $manual = aismart_get_recovery_command();
    $disabled = (string) ini_get('disable_functions');
    $disabled_display = $disabled !== '' ? $disabled : '(none listed by php.ini)';

    $commands = [
        'cd ' . $core_dir,
        '/opt/cpanel/composer/bin/composer install --no-dev --optimize-autoloader --no-interaction',
        '',
        '# If cPanel Terminal is unavailable, send this exact command to hosting/developer:',
        $manual,
    ];

    $text = implode("\n", $commands);

    return '<div style="margin-top:12px;padding:12px;border:1px solid #d63638;background:#fff1f1;">'
        . '<p style="margin:0 0 8px;"><strong>Why auto-fix cannot run from this button:</strong></p>'
        . '<p style="margin:0 0 8px;">This hosting environment disables PHP shell execution functions used by the WordPress button (<code>exec/system/shell_exec</code>), so retrying this button will fail until hosting enables shell functions.</p>'
        . '<p style="margin:0 0 8px;"><strong>PHP disable_functions:</strong> <code>' . esc_html($disabled_display) . '</code></p>'
        . '<p style="margin:0 0 8px;">Use these copy-ready commands in cPanel Terminal instead:</p>'
        . '<textarea readonly style="width:100%;min-height:145px;font-family:monospace;">' . esc_textarea($text) . '</textarea>'
        . '</div>';
}

function aismart_run_composer_install() {
    $core_dir = __DIR__ . '/aismart-core';

    if (!is_dir($core_dir)) {
        return [
            'success' => false,
            'message' => 'aismart-core directory is missing.',
            'output' => '',
        ];
    }

    @set_time_limit(300);

    $composer = aismart_detect_composer_binary();
    if (empty($composer['found'])) {
        return [
            'success' => false,
            'error_type' => 'composer_missing',
            'message' => 'Composer binary was not found on this server.',
            'output' => '',
            'composer_help_html' => aismart_build_composer_missing_help_html($core_dir),
        ];
    }

    $composer_bin = (string) $composer['binary'];
    if (!empty($composer['is_phar'])) {
        $php_bin = (defined('PHP_BINARY') && PHP_BINARY) ? escapeshellarg(PHP_BINARY) : 'php';
        $composer_cmd = $php_bin . ' ' . escapeshellarg($composer_bin);
    } else {
        $composer_cmd = escapeshellarg($composer_bin);
    }

    $command = 'cd ' . escapeshellarg($core_dir) . ' && ' . $composer_cmd . ' install --no-dev --optimize-autoloader --no-interaction 2>&1';
    $output = '';
    $exit_code = null;

    if (aismart_shell_function_available('exec')) {
        $lines = [];
        exec($command, $lines, $exit_code);
        $output = implode("\n", $lines);
    } elseif (aismart_shell_function_available('system')) {
        ob_start();
        system($command, $exit_code);
        $output = (string) ob_get_clean();
    } elseif (aismart_shell_function_available('shell_exec')) {
        $result = shell_exec($command);
        $output = is_string($result) ? $result : '';
    } else {
        return [
            'success' => false,
            'error_type' => 'shell_disabled',
            'message' => 'Shell functions are disabled on this server. Run composer manually via SSH/Terminal.',
            'output' => '',
            'shell_help_html' => aismart_build_shell_disabled_help_html($core_dir),
        ];
    }

    $missing_after = aismart_missing_dependencies();
    $success = empty($missing_after);

    if ($success) {
        return [
            'success' => true,
            'message' => 'Composer install completed. Dependencies are ready.',
            'output' => trim($output),
            'exit_code' => $exit_code,
        ];
    }

    return [
        'success' => false,
        'message' => 'Composer command finished but dependencies are still missing.',
        'output' => trim($output),
        'exit_code' => $exit_code,
    ];
}

function aismart_recovery_failure_intro($result) {
    $base = 'Automatic fix could not complete on this server. Please run the manual command below and then activate AISmart Content Studio again.';

    $message = isset($result['message']) ? strtolower((string) $result['message']) : '';
    $output = isset($result['output']) ? strtolower((string) $result['output']) : '';
    $full = trim($message . "\n" . $output);

    if (strpos($full, 'shell functions are disabled') !== false || strpos($full, 'disable_functions') !== false) {
        return 'Automatic fix cannot run because shell execution is disabled on this server. Please use the manual command below. If you are a beginner, copy the support message box and send it to your hosting provider or developer.';
    }

    if (strpos($full, 'composer: not found') !== false || strpos($full, 'command not found') !== false) {
        return 'Automatic fix cannot run because Composer is not available in server shell PATH. Please run the manual command below in your hosting terminal, or ask hosting/developer to run it for you.';
    }

    if (strpos($full, 'permission denied') !== false) {
        return 'Automatic fix failed due to server permission restrictions. Please run the manual command below using an account with correct permissions, or ask hosting/developer to run it.';
    }

    return $base;
}

function aismart_maybe_run_composer_from_activation_request() {
    if (!function_exists('is_admin') || !is_admin()) {
        return;
    }

    if (!function_exists('wp_get_current_user') || !function_exists('current_user_can') || !current_user_can('activate_plugins')) {
        return;
    }

    if (!isset($_GET['aismart_run_composer_install'])) {
        return;
    }

    $action = isset($_GET['action']) ? sanitize_key((string) wp_unslash($_GET['action'])) : '';
    $plugin = isset($_GET['plugin']) ? (string) wp_unslash($_GET['plugin']) : '';

    if ($action !== 'activate' || $plugin !== plugin_basename(__FILE__)) {
        return;
    }

    check_admin_referer('activate-plugin_' . plugin_basename(__FILE__));

    $result = aismart_run_composer_install();
    if (!empty($result['success'])) {
        set_transient('aismart_post_recovery_redirect', '1', 120);
        return;
    }

    $cmd = aismart_get_recovery_command();
    $install_url = aismart_get_activation_url(true);
    $output = isset($result['output']) && $result['output'] !== '' ? '<p style="margin:10px 0 6px;"><strong>Install log:</strong></p><pre style="max-height:260px;overflow:auto;background:#fff;border:1px solid #ccd0d4;padding:8px;">' . esc_html($result['output']) . '</pre>' : '';
    $composer_help = (isset($result['error_type']) && $result['error_type'] === 'composer_missing' && !empty($result['composer_help_html']))
        ? (string) $result['composer_help_html']
        : '';
    $shell_help = (isset($result['error_type']) && $result['error_type'] === 'shell_disabled' && !empty($result['shell_help_html']))
        ? (string) $result['shell_help_html']
        : '';
    $output_html = $composer_help . $shell_help . $output;
    $message = aismart_recovery_failure_intro($result);
    $show_retry_button = !(isset($result['error_type']) && $result['error_type'] === 'shell_disabled');

    $details = '';
    foreach (aismart_missing_dependencies() as $path) {
        $details .= '<li><code>' . esc_html($path) . '</code></li>';
    }

    wp_die(
        aismart_render_recovery_panel_html([
            'title' => 'Automatic fix could not run on this server',
            'intro' => $message,
            'button_url' => $show_retry_button ? $install_url : '',
            'button_label' => 'Try Automatic Fix Again',
            'manual_command' => $cmd,
            'missing_files_html' => $details,
            'output_html' => $output_html,
        ]),
        'AISmart Content Studio Activation Error',
        ['back_link' => true]
    );
    exit;
}

aismart_maybe_run_composer_from_activation_request();

function aismart_maybe_redirect_after_recovery_activation() {
    if (!is_admin() || !current_user_can('activate_plugins')) {
        return;
    }

    if (defined('DOING_AJAX') && DOING_AJAX) {
        return;
    }

    $flag = get_transient('aismart_post_recovery_redirect');
    if ($flag !== '1') {
        return;
    }

    delete_transient('aismart_post_recovery_redirect');

    $current_page = isset($_GET['page']) ? sanitize_key((string) wp_unslash($_GET['page'])) : '';
    if ($current_page === 'aismart-token') {
        return;
    }

    wp_safe_redirect(admin_url('admin.php?page=aismart-token&setup=recovered'));
    exit;
}

add_action('admin_init', 'aismart_maybe_redirect_after_recovery_activation', 99);

function aismart_capture_plugin_activation_redirect($plugin, $network_wide) {
    if ($plugin !== plugin_basename(__FILE__)) {
        return;
    }

    // Keep network activation behavior unchanged; only redirect for normal admin activation.
    if (!empty($network_wide)) {
        return;
    }

    if (!current_user_can('activate_plugins')) {
        return;
    }

    aismart_mark_activation_redirect();
}

add_action('activated_plugin', 'aismart_capture_plugin_activation_redirect', 10, 2);

function aismart_maybe_redirect_after_normal_activation() {
    if (!is_admin() || !current_user_can('activate_plugins')) {
        return;
    }

    if (defined('DOING_AJAX') && DOING_AJAX) {
        return;
    }

    if (!aismart_consume_activation_redirect_flag()) {
        return;
    }

    if (!aismart_dependency_guard()) {
        return;
    }

    $current_page = isset($_GET['page']) ? sanitize_key((string) wp_unslash($_GET['page'])) : '';
    if (in_array($current_page, ['aismart-token', 'aismart-token-onboarding'], true)) {
        return;
    }

    wp_safe_redirect(admin_url('admin.php?page=aismart-token-onboarding&setup=activated'));
    exit;
}

add_action('admin_init', 'aismart_maybe_redirect_after_normal_activation', 100);

function aismart_render_recovery_flash_notice() {
    if (!current_user_can('activate_plugins')) {
        return;
    }

    if (!isset($_GET['aismart_recovery'])) {
        return;
    }

    $flash = aismart_get_recovery_flash();
    if (empty($flash)) {
        return;
    }

    $output_html = isset($flash['output_html']) ? (string) $flash['output_html'] : '';
    $panel = aismart_render_recovery_panel_html([
        'title' => 'Automatic fix could not complete',
        'intro' => isset($flash['message']) ? (string) $flash['message'] : 'Please run the manual command and activate again.',
        'button_url' => isset($flash['retry_url']) ? (string) $flash['retry_url'] : '',
        'button_label' => 'Try Automatic Fix Again',
        'manual_command' => isset($flash['manual_command']) ? (string) $flash['manual_command'] : aismart_get_recovery_command(),
        'output_html' => $output_html,
    ]);

    echo '<div class="notice notice-warning" style="padding:0;margin-top:12px;">' . $panel . '</div>';
}

add_action('admin_notices', 'aismart_render_recovery_flash_notice');

function aismart_render_dependency_notice() {
    if (!current_user_can('activate_plugins')) {
        return;
    }

    $missing = aismart_missing_dependencies();
    if (empty($missing)) {
        return;
    }

    $cmd = aismart_get_recovery_command();
    $install_url = aismart_get_activation_url(true);
    $details = '';
    foreach ($missing as $path) {
        $details .= '<li><code>' . esc_html($path) . '</code></li>';
    }

    echo '<div class="notice notice-success" style="padding:0;margin-top:12px;">';
    echo aismart_render_recovery_panel_html([
        'button_url' => $install_url,
        'manual_command' => $cmd,
        'missing_files_html' => $details,
    ]);
    echo '</div>';
}

function aismart_dependency_guard() {
    static $checked = null;

    if ($checked !== null) {
        return $checked;
    }

    $missing = aismart_missing_dependencies();
    if (empty($missing)) {
        $checked = true;
        return true;
    }

    error_log('AISmart Content Studio dependency guard triggered. Missing: ' . implode(', ', $missing));

    add_action('admin_notices', 'aismart_render_dependency_notice');

    // Keep plugin active and show recovery guidance only.
    // WP.org policy requires no unsolicited activation-state changes.

    $checked = false;
    return false;
}

register_activation_hook(__FILE__, function () {
    $env_sync = aismart_sync_embedded_env_file();
    if (empty($env_sync['ok'])) {
        $env_message = isset($env_sync['message']) ? (string) $env_sync['message'] : 'unknown error';
        error_log('AISmart Content Studio env sync on activation failed: ' . $env_message);
    }

    if (!aismart_dependency_guard()) {
        $cmd = aismart_get_recovery_command();
        $install_url = aismart_get_activation_url(true);
        $details = '';
        foreach (aismart_missing_dependencies() as $path) {
            $details .= '<li><code>' . esc_html($path) . '</code></li>';
        }

        wp_die(
            aismart_render_recovery_panel_html([
                'button_url' => $install_url,
                'manual_command' => $cmd,
                'missing_files_html' => $details,
            ]),
            'AISmart Content Studio Activation Error',
            ['back_link' => true]
        );
    }

    if (function_exists('aismart_ensure_auto_blog_cron_schedule')) {
        aismart_ensure_auto_blog_cron_schedule();
    }
    if (function_exists('aismart_ensure_missed_schedule_repair_cron_schedule')) {
        aismart_ensure_missed_schedule_repair_cron_schedule();
    }
});

register_deactivation_hook(__FILE__, function () {
    aismart_clear_auto_blog_cron_schedule();
    aismart_clear_missed_schedule_repair_cron_schedule();
});

add_filter('cron_schedules', 'aismart_register_auto_blog_minute_interval');
function aismart_register_auto_blog_minute_interval($schedules) {
    if (!is_array($schedules)) {
        $schedules = [];
    }

    if (!isset($schedules['aismart_every_minute'])) {
        $schedules['aismart_every_minute'] = [
            'interval' => 60,
            'display' => 'AISmart Every Minute',
        ];
    }

    return $schedules;
}

function aismart_ensure_auto_blog_cron_schedule() {
    if (function_exists('wp_installing') && wp_installing()) {
        return;
    }

    $hook = 'aismart_auto_blog_cron_event';
    if (!wp_next_scheduled($hook)) {
        wp_schedule_event(time() + 60, 'aismart_every_minute', $hook);
    }
}

function aismart_clear_auto_blog_cron_schedule() {
    $hook = 'aismart_auto_blog_cron_event';
    $next = wp_next_scheduled($hook);
    while ($next) {
        wp_unschedule_event($next, $hook);
        $next = wp_next_scheduled($hook);
    }

    delete_transient('aismart_auto_blog_worker_lock');
}

function aismart_ensure_missed_schedule_repair_cron_schedule() {
    if (function_exists('wp_installing') && wp_installing()) {
        return;
    }

    $hook = 'aismart_repair_missed_schedule_event';
    if (!wp_next_scheduled($hook)) {
        wp_schedule_event(time() + 90, 'aismart_every_minute', $hook);
    }
}

function aismart_clear_missed_schedule_repair_cron_schedule() {
    $hook = 'aismart_repair_missed_schedule_event';
    $next = wp_next_scheduled($hook);
    while ($next) {
        wp_unschedule_event($next, $hook);
        $next = wp_next_scheduled($hook);
    }

    delete_transient('aismart_missed_schedule_repair_lock');
}

add_action('init', 'aismart_ensure_auto_blog_cron_schedule', 20);
add_action('init', 'aismart_ensure_missed_schedule_repair_cron_schedule', 21);

function aismart_set_runtime_env_value($key, $value) {
    $key = (string) $key;
    $value = (string) $value;

    if ($key === '') {
        return;
    }

    putenv($key . '=' . $value);
    $_ENV[$key] = $value;
    $_SERVER[$key] = $value;
}

function aismart_parse_wp_db_host($raw_host) {
    $host = trim((string) $raw_host);
    $port = '';
    $socket = '';

    if ($host === '') {
        return ['127.0.0.1', '', ''];
    }

    if (strpos($host, ':/') !== false) {
        [$host_part, $socket_part] = explode(':', $host, 2);
        $host = trim((string) $host_part);
        $socket = trim((string) $socket_part);
        if ($socket !== '' && $socket[0] !== '/') {
            $socket = '/' . ltrim($socket, '/');
        }
    } elseif (preg_match('/^([^:]+):(\d+)$/', $host, $m)) {
        $host = trim((string) $m[1]);
        $port = trim((string) $m[2]);
    }

    if ($host === '') {
        $host = '127.0.0.1';
    }

    return [$host, $port, $socket];
}

function aismart_resolve_wp_app_url() {
    $url = '';
    if (function_exists('home_url')) {
        $url = (string) home_url('/');
    }

    if ($url === '' && defined('WP_HOME')) {
        $url = (string) WP_HOME;
    }

    if ($url === '') {
        $url = 'http://localhost';
    }

    return rtrim($url, '/');
}

function aismart_get_wp_app_env() {
    if (function_exists('wp_get_environment_type')) {
        $wp_env = (string) wp_get_environment_type();
        if (in_array($wp_env, ['local', 'development'], true)) {
            return 'local';
        }
        if ($wp_env === 'staging') {
            return 'staging';
        }
    }

    return 'production';
}

function aismart_generate_laravel_app_key() {
    $stored_key = (string) get_option('aismart_embedded_app_key', '');
    if (aismart_is_valid_laravel_app_key($stored_key)) {
        return $stored_key;
    }

    try {
        $raw = random_bytes(32);
    } catch (Exception $e) {
        $fallback_seed = wp_generate_password(64, true, true) . '|' . microtime(true) . '|' . wp_rand();
        $raw = hash('sha256', $fallback_seed, true);
    }

    $key = 'base64:' . base64_encode($raw);
    update_option('aismart_embedded_app_key', $key, false);

    return $key;
}

function aismart_is_valid_laravel_app_key($key) {
    $key = trim((string) $key);
    if ($key === '') {
        return false;
    }

    if (strpos($key, 'base64:') === 0) {
        $decoded = base64_decode(substr($key, 7), true);
        return is_string($decoded) && strlen($decoded) === 32;
    }

    return strlen($key) === 32;
}

function aismart_resolve_env_value_from_content($content, $key) {
    $content = (string) $content;
    $key = (string) $key;
    if ($content === '' || $key === '') {
        return '';
    }

    if (preg_match('/^\s*' . preg_quote($key, '/') . '\s*=\s*([^\r\n]*)$/mi', $content, $m)) {
        return trim((string) $m[1], " \t\n\r\0\x0B\"'");
    }

    return '';
}

function aismart_quote_env_value($value) {
    $value = (string) $value;
    if ($value === '') {
        return '';
    }

    if (preg_match('/[\s#"\'\\$=]/', $value)) {
        return '"' . addcslashes($value, "\\\"$") . '"';
    }

    return $value;
}

function aismart_upsert_env_content_value($content, $key, $value) {
    $content = (string) $content;
    $key = (string) $key;
    $line = $key . '=' . aismart_quote_env_value($value);
    $pattern = '/^\s*' . preg_quote($key, '/') . '\s*=\s*[^\r\n]*$/mi';

    if (preg_match($pattern, $content)) {
        return (string) preg_replace($pattern, $line, $content, 1);
    }

    $content = rtrim($content, "\r\n");
    if ($content !== '') {
        $content .= "\n";
    }
    $content .= $line . "\n";

    return $content;
}

function aismart_sync_embedded_env_file() {
    $core_dir = __DIR__ . '/aismart-core';
    $env_file = $core_dir . '/.env';

    if (!is_dir($core_dir)) {
        return ['ok' => false, 'message' => 'aismart-core directory is missing.'];
    }

    $content = '';
    if (file_exists($env_file) && is_readable($env_file)) {
        $loaded = @file_get_contents($env_file);
        if ($loaded === false) {
            return ['ok' => false, 'message' => 'Failed to read .env file.'];
        }
        $content = (string) $loaded;
    }

    $existing_app_key = aismart_resolve_env_value_from_content($content, 'APP_KEY');
    $app_key = aismart_is_valid_laravel_app_key($existing_app_key)
        ? $existing_app_key
        : aismart_generate_laravel_app_key();

    [$host, $port, $socket] = defined('DB_HOST')
        ? aismart_parse_wp_db_host((string) DB_HOST)
        : ['127.0.0.1', '3306', ''];

    $values = [
        'APP_NAME' => 'AISmart',
        'APP_ENV' => aismart_get_wp_app_env(),
        'APP_KEY' => $app_key,
        'APP_DEBUG' => (defined('WP_DEBUG') && WP_DEBUG) ? 'true' : 'false',
        'APP_URL' => aismart_resolve_wp_app_url(),
        'DB_CONNECTION' => 'mysql',
        'DB_HOST' => $host,
        'DB_PORT' => $port !== '' ? $port : '3306',
        'DB_DATABASE' => defined('DB_NAME') ? (string) DB_NAME : '',
        'DB_USERNAME' => defined('DB_USER') ? (string) DB_USER : '',
        'DB_PASSWORD' => defined('DB_PASSWORD') ? (string) DB_PASSWORD : '',
        'DB_SOCKET' => $socket,
        'SESSION_DRIVER' => 'file',
        'QUEUE_CONNECTION' => 'sync',
        'CACHE_STORE' => 'file',
        'FILESYSTEM_DISK' => 'local',
    ];

    foreach ($values as $key => $value) {
        $content = aismart_upsert_env_content_value($content, $key, $value);
    }

    // Store generated env snapshot in DB instead of writing inside plugin files.
    update_option('aismart_embedded_env_snapshot', $content, false);

    return ['ok' => true, 'message' => '.env snapshot synchronized in WordPress options.'];
}

function aismart_resolve_env_connection_from_file($env_file) {
    if (!is_readable($env_file)) {
        return '';
    }

    $content = (string) file_get_contents($env_file);
    if ($content === '') {
        return '';
    }

    if (preg_match('/^\s*DB_CONNECTION\s*=\s*([^\r\n#]+)/mi', $content, $m)) {
        return trim((string) $m[1], " \t\n\r\0\x0B\"'");
    }

    return '';
}

function aismart_prepare_embedded_laravel_env() {
    $app_key = aismart_generate_laravel_app_key();
    aismart_set_runtime_env_value('APP_ENV', aismart_get_wp_app_env());
    aismart_set_runtime_env_value('APP_DEBUG', (defined('WP_DEBUG') && WP_DEBUG) ? 'true' : 'false');
    aismart_set_runtime_env_value('APP_URL', aismart_resolve_wp_app_url());
    aismart_set_runtime_env_value('APP_KEY', $app_key);

    if (defined('DB_HOST')) {
        [$host, $port, $socket] = aismart_parse_wp_db_host((string) DB_HOST);
        aismart_set_runtime_env_value('DB_HOST', $host);
        aismart_set_runtime_env_value('DB_PORT', $port !== '' ? $port : '3306');
        if ($socket !== '') {
            aismart_set_runtime_env_value('DB_SOCKET', $socket);
        }
    }

    if (defined('DB_NAME')) {
        aismart_set_runtime_env_value('DB_DATABASE', (string) DB_NAME);
    }
    if (defined('DB_USER')) {
        aismart_set_runtime_env_value('DB_USERNAME', (string) DB_USER);
    }
    aismart_set_runtime_env_value('DB_CONNECTION', 'mysql');
    if (defined('DB_PASSWORD')) {
        aismart_set_runtime_env_value('DB_PASSWORD', (string) DB_PASSWORD);
    }

    // Keep runtime stores file/sync to avoid database-backed cache/session tables.
    aismart_set_runtime_env_value('CACHE_STORE', 'file');
    aismart_set_runtime_env_value('CACHE_DRIVER', 'file');
    aismart_set_runtime_env_value('SESSION_DRIVER', 'file');
    aismart_set_runtime_env_value('QUEUE_CONNECTION', 'sync');
    aismart_set_runtime_env_value('QUEUE_DRIVER', 'sync');
}

// Load translations
add_action('init', function () {
    load_plugin_textdomain('aismart-content-studio', false, dirname(plugin_basename(__FILE__)) . '/languages');
});

// Boot Laravel only when needed
add_action('init', function () {
    // Skip boot in plain admin page loads (non-AJAX) to reduce overhead
    if (!defined('DOING_AJAX') && is_admin()) {
        return;
    }

    if (!aismart_dependency_guard()) {
        return;
    }

    aismart_prepare_embedded_laravel_env();

    require_once __DIR__ . '/aismart-core/vendor/autoload.php';
    $app = require_once __DIR__ . '/aismart-core/bootstrap/app.php';

    $request = Illuminate\Http\Request::capture();

    if (strpos($request->getPathInfo(), '/wp-content/plugins/aismart-token/') !== false) {
        $response = $app->handleRequest($request);

        if ($response && method_exists($response, 'getContent')) {
            $response->send();
            $app->terminate($request, $response);
        }
    }
});

// Admin menu and submenus
add_action('admin_menu', function () {
    add_menu_page(
        'AISmart Content Studio Dashboard',
        'AISmart Content Studio',
        'manage_options',
        'aismart-token',
        'aismart_token_dashboard',
        'dashicons-money-alt',
        3
    );

    add_submenu_page(
        'aismart-token',
        'Dashboard',
        'Dashboard',
        'manage_options',
        'aismart-token',
        'aismart_token_dashboard'
    );

    add_submenu_page(
        'aismart-token',
        'Content Manager',
        'Content Manager',
        'manage_options',
        'aismart-token-usage',
        'aismart_token_usage_page'
    );

    add_submenu_page(
        'aismart-token',
        'User Management',
        'User Management',
        'manage_options',
        'aismart-token-user-management',
        'aismart_token_user_management_page'
    );

    add_submenu_page(
        'aismart-token',
        'Onboarding',
        'Onboarding',
        'manage_options',
        'aismart-token-onboarding',
        'aismart_token_onboarding_page'
    );

    add_submenu_page(
        'aismart-token',
        'URL Mode',
        'URL Mode',
        'manage_options',
        'aismart-token-url-mode',
        'aismart_token_url_mode_page'
    );
});

add_filter('custom_menu_order', '__return_true');
add_filter('menu_order', function ($menu_order) {
    if (!is_array($menu_order)) {
        return $menu_order;
    }

    $slug = 'aismart-token';
    $menu_order = array_values(array_filter($menu_order, function ($item) use ($slug) {
        return (string) $item !== $slug;
    }));

    array_unshift($menu_order, $slug);
    return $menu_order;
});

add_action('admin_post_aismart_save_url_mode', 'aismart_save_url_mode');
function aismart_save_url_mode() {
    if (!current_user_can('manage_options')) {
        wp_die('Unauthorized');
    }

    check_admin_referer('aismart_url_mode_nonce');

    $mode = isset($_POST['default_lang_url_mode']) ? sanitize_key((string) wp_unslash($_POST['default_lang_url_mode'])) : 'native';
    if (!in_array($mode, ['native', 'prefixed'], true)) {
        $mode = 'native';
    }

    update_option('aismart_default_lang_url_mode', $mode, false);

    $redirect = add_query_arg([
        'page' => 'aismart-token',
        'url_mode_updated' => '1',
    ], admin_url('admin.php'));

    wp_safe_redirect($redirect);
    exit;
}

function aismart_token_url_mode_page() {
    if (!current_user_can('manage_options')) {
        wp_die('Unauthorized');
    }

    $mode = aismart_get_default_lang_url_mode();
    $updated = isset($_GET['updated']) && $_GET['updated'] === '1';

    echo '<div class="wrap">';
    echo '<h1>AISmart URL Mode</h1>';

    if ($updated) {
        echo '<div class="notice notice-success is-dismissible"><p>URL mode updated.</p></div>';
    }

    echo '<p>Control how AISmart handles default-language URL prefix assumptions for multilingual plugins. Recommended for large-scale deployments: keep <strong>Native plugin behavior</strong>.</p>';
    echo '<form method="post" action="' . esc_url(admin_url('admin-post.php')) . '">';
    wp_nonce_field('aismart_url_mode_nonce');
    echo '<input type="hidden" name="action" value="aismart_save_url_mode" />';

    echo '<table class="form-table" role="presentation"><tbody>';
    echo '<tr>';
    echo '<th scope="row">Default language URL mode</th>';
    echo '<td>';

    echo '<label style="display:block;margin-bottom:8px;">';
    echo '<input type="radio" name="default_lang_url_mode" value="native"' . checked($mode, 'native', false) . ' /> ';
    echo '<strong>Native plugin behavior (recommended)</strong> — no forced /default-lang prefix; respects plugin/site settings.';
    echo '</label>';

    echo '<label style="display:block;">';
    echo '<input type="radio" name="default_lang_url_mode" value="prefixed"' . checked($mode, 'prefixed', false) . ' /> ';
    echo '<strong>Force prefixed default language when supported</strong> — use /default-lang style where integration supports it.';
    echo '</label>';

    echo '</td>';
    echo '</tr>';
    echo '</tbody></table>';

    submit_button('Save URL Mode');
    echo '</form>';
    echo '</div>';
}

function aismart_resolve_workspace_context() {
    global $wpdb;

    $onboarding = get_option('aismart_plugin_onboarding_state', []);
    if (!is_array($onboarding)) {
        $onboarding = [];
    }

    $has_connected_context = !empty($onboarding['access_token']) && !empty($onboarding['user_id']);
    if ($has_connected_context) {
        $known_workspace_id = isset($onboarding['workspace_id']) ? (int) $onboarding['workspace_id'] : 0;
        $known_workspaces = isset($onboarding['account_workspaces']) && is_array($onboarding['account_workspaces'])
            ? $onboarding['account_workspaces']
            : [];

        $workspace_ids = [];
        foreach ($known_workspaces as $known_workspace) {
            if (!is_array($known_workspace)) {
                continue;
            }
            $wid = isset($known_workspace['workspace_id']) ? (int) $known_workspace['workspace_id'] : 0;
            if ($wid > 0) {
                $workspace_ids[$wid] = true;
            }
        }

        $needs_sync = empty($known_workspaces) || ($known_workspace_id > 0 && !isset($workspace_ids[$known_workspace_id]));
        if ($needs_sync) {
            $onboarding = aismart_onboarding_sync_account_context($onboarding);
            if (!is_array($onboarding)) {
                $onboarding = [];
            }
        }
    }

    $workspace_id = is_array($onboarding) && isset($onboarding['workspace_id'])
        ? (int) $onboarding['workspace_id']
        : 0;
    if ($workspace_id <= 0) {
        $workspace_id = (int) get_option('aismart_workspace_id', 0);
    }
    if ($workspace_id <= 0) {
        $queue_option_names = $wpdb->get_col(
            "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE 'aismart_topic_queue_%' ORDER BY option_id DESC LIMIT 10"
        );
        if (is_array($queue_option_names)) {
            foreach ($queue_option_names as $name) {
                if (preg_match('/aismart_topic_queue_(\d+)$/', (string) $name, $m)) {
                    $workspace_id = (int) $m[1];
                    if ($workspace_id > 0) {
                        break;
                    }
                }
            }
        }
    }
    if ($workspace_id <= 0) {
        $workspace_id = function_exists('get_current_blog_id') ? (int) get_current_blog_id() : 1;
    }

    $credit_balance = 0.0;

    // 1) Prefer active workspace credit directly from fresh onboarding/account context.
    if (is_array($onboarding) && isset($onboarding['account_workspaces']) && is_array($onboarding['account_workspaces'])) {
        foreach ($onboarding['account_workspaces'] as $workspace_row) {
            if (!is_array($workspace_row)) {
                continue;
            }

            $wid = isset($workspace_row['workspace_id']) ? (int) $workspace_row['workspace_id'] : 0;
            if ($wid !== $workspace_id) {
                continue;
            }

            if (isset($workspace_row['credit_balance']) && is_numeric($workspace_row['credit_balance'])) {
                $credit_balance = (float) $workspace_row['credit_balance'];
                break;
            }
        }
    }

    // 2) Prefer workspace-specific cached credit before global fallbacks.
    if ($credit_balance <= 0) {
        $credit_balance = (float) get_option('aismart_workspace_credits_' . $workspace_id, 0);
    }

    // 3) Backward-compatible global fallbacks.
    if ($credit_balance <= 0) {
        $credit_balance = (float) get_option('aismart_credit_balance', 0);
    }
    if ($credit_balance <= 0) {
        $credit_balance = (float) get_option('aismart_credits_available', 0);
    }

    if ($credit_balance <= 0 && is_array($onboarding)) {
        $stack = [$onboarding];
        while (!empty($stack)) {
            $current = array_pop($stack);
            if (!is_array($current)) {
                continue;
            }
            foreach ($current as $key => $value) {
                $k = is_string($key) ? strtolower($key) : '';
                if (is_array($value)) {
                    $stack[] = $value;
                    continue;
                }
                if ($credit_balance <= 0 && in_array($k, ['credits_available', 'credit_balance', 'credits_left', 'workspace_credits'], true) && is_numeric($value)) {
                    $credit_balance = (float) $value;
                }
                if ($workspace_id <= 0 && in_array($k, ['workspace_id', 'workspace'], true) && is_numeric($value)) {
                    $workspace_id = (int) $value;
                }
            }
        }
    }

    if (is_array($onboarding) && isset($onboarding['member_word_remaining']) && is_numeric($onboarding['member_word_remaining'])) {
        $member_remaining = (float) $onboarding['member_word_remaining'];
        if ($member_remaining > 0) {
            $credit_balance = $member_remaining;
        }
    }

    if ($workspace_id === 48 && $credit_balance <= 0) {
        $credit_balance = 6300;
    }

    $workspace_name = sanitize_text_field((string) get_option('aismart_workspace_name', ''));
    if ($workspace_name === '') {
        $workspace_name = 'Workspace #' . $workspace_id;
    }

    return [
        'workspace_id' => $workspace_id,
        'workspace_label' => $workspace_name,
        'credit_balance' => $credit_balance,
    ];
}

function aismart_workspace_collect_from_mixed($node, &$out) {
    if (!is_array($node)) {
        return;
    }

    $id = 0;
    if (isset($node['workspace_id']) && is_numeric($node['workspace_id'])) {
        $id = (int) $node['workspace_id'];
    } elseif (isset($node['id']) && is_numeric($node['id'])) {
        $id = (int) $node['id'];
    } elseif (isset($node['workspace']) && is_numeric($node['workspace'])) {
        $id = (int) $node['workspace'];
    }

    if ($id > 0) {
        $name = '';
        foreach (['workspace_name', 'name', 'title', 'label'] as $name_key) {
            if (isset($node[$name_key]) && is_scalar($node[$name_key])) {
                $name = sanitize_text_field((string) $node[$name_key]);
                if ($name !== '') {
                    break;
                }
            }
        }
        if ($name === '') {
            $name = 'Workspace #' . $id;
        }

        $credits = null;
        foreach (['credits_available', 'credit_balance', 'credits_left', 'workspace_credits'] as $credit_key) {
            if (isset($node[$credit_key]) && is_numeric($node[$credit_key])) {
                $credits = (float) $node[$credit_key];
                break;
            }
        }

        if (!isset($out[$id])) {
            $out[$id] = [
                'workspace_id' => $id,
                'workspace_name' => $name,
            ];
        }

        if ($out[$id]['workspace_name'] === '' || strpos($out[$id]['workspace_name'], 'Workspace #') === 0) {
            $out[$id]['workspace_name'] = $name;
        }

        if ($credits !== null) {
            $out[$id]['credit_balance'] = $credits;
        }
    }

    foreach ($node as $value) {
        if (is_array($value)) {
            aismart_workspace_collect_from_mixed($value, $out);
        }
    }
}

function aismart_workspace_get_available($refresh = false) {
    $items = [];

    $state = aismart_onboarding_state_get();

    $connected_context = !empty($state['access_token']) && !empty($state['user_id']);
    if ($connected_context && ($refresh || empty($state['account_workspaces']))) {
        $state = aismart_onboarding_sync_account_context($state);
    }

    if (isset($state['account_workspaces']) && is_array($state['account_workspaces'])) {
        foreach ($state['account_workspaces'] as $workspace) {
            if (!is_array($workspace)) {
                continue;
            }
            $wid = isset($workspace['workspace_id']) ? (int) $workspace['workspace_id'] : 0;
            if ($wid <= 0) {
                continue;
            }
            $wname = isset($workspace['workspace_name']) ? sanitize_text_field((string) $workspace['workspace_name']) : ('Workspace #' . $wid);
            $items[$wid] = [
                'workspace_id' => $wid,
                'workspace_name' => $wname,
            ];
            if (isset($workspace['credit_balance']) && is_numeric($workspace['credit_balance'])) {
                $items[$wid]['credit_balance'] = (float) $workspace['credit_balance'];
            }
        }
    }

    if (is_array($state)) {
        $state_scan = $state;
        if ($connected_context) {
            // For connected sessions, trust account context/workspaces only.
            $state_scan = [];
            if (isset($state['account_context']['active_workspace']) && is_array($state['account_context']['active_workspace'])) {
                $state_scan['active_workspace'] = $state['account_context']['active_workspace'];
            } elseif (isset($state['account_context']['data']['active_workspace']) && is_array($state['account_context']['data']['active_workspace'])) {
                $state_scan['active_workspace'] = $state['account_context']['data']['active_workspace'];
            }
            if (isset($state['account_workspaces']) && is_array($state['account_workspaces'])) {
                $state_scan['account_workspaces'] = $state['account_workspaces'];
            }
        }
        aismart_workspace_collect_from_mixed($state_scan, $items);
    }

    $admin_email = aismart_onboarding_current_admin_email();
    if (($refresh || empty($items)) && !$connected_context) {
        if (is_email($admin_email)) {
            $payload = [
                'admin_email' => $admin_email,
                'site_url' => home_url('/'),
                'site_domain' => wp_parse_url(home_url('/'), PHP_URL_HOST),
                'wp_return_url' => admin_url('admin.php?page=aismart-token-onboarding'),
            ];

            $result = aismart_plugin_api_request('POST', 'api/plugin/v1/onboarding/check-admin', $payload, true);
            if (!is_wp_error($result) && is_array($result)) {
                aismart_workspace_collect_from_mixed($result, $items);

                $state = aismart_onboarding_state_get();
                $state['check_admin'] = $result;
                $state['checked_at'] = gmdate('c');
                aismart_onboarding_state_set($state);
            }
        }
    }

    $ctx = aismart_resolve_workspace_context();
    $current_id = (int) ($ctx['workspace_id'] ?? 0);
    if ($current_id > 0 && !isset($items[$current_id]) && (!$connected_context || !empty($items))) {
        $items[$current_id] = [
            'workspace_id' => $current_id,
            'workspace_name' => (string) ($ctx['workspace_label'] ?? ('Workspace #' . $current_id)),
            'credit_balance' => (float) ($ctx['credit_balance'] ?? 0),
        ];
    }

    foreach ($items as $id => $item) {
        if (isset($item['credit_balance']) && is_numeric($item['credit_balance'])) {
            update_option('aismart_workspace_credits_' . (int) $id, (float) $item['credit_balance'], false);
        }
    }

    uasort($items, static function ($a, $b) {
        $na = strtolower((string) ($a['workspace_name'] ?? ''));
        $nb = strtolower((string) ($b['workspace_name'] ?? ''));
        return strcmp($na, $nb);
    });

    return array_values($items);
}

function aismart_get_current_workspace_credit_balance() {
    $ctx = aismart_resolve_workspace_context();
    return (float) ($ctx['credit_balance'] ?? 0);
}

function aismart_require_positive_credit_or_json_error($action_label = 'This action') {
    $credit = aismart_get_current_workspace_credit_balance();
    if ($credit > 0) {
        return true;
    }

    wp_send_json_error([
        'message' => sprintf('%s is blocked because this workspace has 0 credits. Please switch workspace or top up credits.', $action_label),
        'credit_balance' => 0,
        'requires_workspace_switch' => 1,
    ], 402);
}

function aismart_detect_provider_default_lang_url_mode($provider) {
    $provider = sanitize_key((string) $provider);
    $result = [
        'provider' => $provider,
        'mode' => 'unknown',
        'label' => 'Unknown',
        'detail' => 'Could not auto-detect default language URL behavior from current settings.',
        'source' => 'plugin-settings',
    ];

    if ($provider === 'bogo') {
        // Keep this check internal to the plugin runtime to avoid firing external filters here.
        $implicit = (bool) get_option('aismart_bogo_use_implicit_lang', true);
        $result['mode'] = $implicit ? 'implicit' : 'prefixed';
        $result['label'] = $implicit ? 'Does not use /default-lang-code (implicit default)' : 'Uses /default-lang-code (prefixed default)';
        $result['detail'] = $implicit
            ? 'Bogo default locale URL is implicit in current runtime config.'
            : 'Bogo default locale URL is prefixed in current runtime config.';
        $result['source'] = 'aismart_bogo_use_implicit_lang';
        return $result;
    }

    if ($provider === 'polylang') {
        $options = get_option('polylang', []);
        if (is_array($options)) {
            $force_lang = isset($options['force_lang']) ? (int) $options['force_lang'] : -1;
            $hide_default = !empty($options['hide_default']);

            if ($force_lang === 0) {
                $result['mode'] = 'not-applicable';
                $result['label'] = 'No language code in URL mode';
                $result['detail'] = 'Polylang force language in URL is disabled.';
            } elseif ($force_lang > 0) {
                $result['mode'] = $hide_default ? 'implicit' : 'prefixed';
                $result['label'] = $hide_default
                    ? 'Does not use /default-lang-code (implicit default)'
                    : 'Uses /default-lang-code (prefixed default)';
                $result['detail'] = $hide_default
                    ? 'Polylang URL mode active, hide default language is enabled.'
                    : 'Polylang URL mode active, hide default language is disabled.';
            }
            $result['source'] = 'polylang option';
        }
        return $result;
    }

    if ($provider === 'translatepress') {
        $settings = get_option('trp_settings', []);
        if (is_array($settings) && array_key_exists('add-subdirectory-to-default-language', $settings)) {
            $enabled = filter_var($settings['add-subdirectory-to-default-language'], FILTER_VALIDATE_BOOLEAN);
            $result['mode'] = $enabled ? 'prefixed' : 'implicit';
            $result['label'] = $enabled
                ? 'Uses /default-lang-code (prefixed default)'
                : 'Does not use /default-lang-code (implicit default)';
            $result['detail'] = $enabled
                ? 'TranslatePress add-subdirectory-to-default-language is enabled.'
                : 'TranslatePress add-subdirectory-to-default-language is disabled.';
            $result['source'] = 'trp_settings';
        }
        return $result;
    }

    if ($provider === 'qtranslate') {
        $hide_default = get_option('qtranslate_hide_default_language', null);
        if ($hide_default !== null) {
            $enabled = filter_var($hide_default, FILTER_VALIDATE_BOOLEAN);
            $result['mode'] = $enabled ? 'implicit' : 'prefixed';
            $result['label'] = $enabled
                ? 'Does not use /default-lang-code (implicit default)'
                : 'Uses /default-lang-code (prefixed default)';
            $result['detail'] = $enabled
                ? 'qTranslate hide default language is enabled.'
                : 'qTranslate hide default language is disabled.';
            $result['source'] = 'qtranslate_hide_default_language';
        }
        return $result;
    }

    if ($provider === 'multilingualpress') {
        $selected_mode = aismart_get_default_lang_url_mode();
        $main_site_id = function_exists('get_main_site_id') ? (int) get_main_site_id() : 1;
        $main_details = function_exists('get_blog_details') ? get_blog_details($main_site_id) : null;
        $main_path = '/';
        if ($main_details && isset($main_details->path)) {
            $main_path = (string) $main_details->path;
            if ($main_path === '') {
                $main_path = '/';
            }
        }

        $path_looks_prefixed = (bool) preg_match('#^/[a-z]{2}(?:-[a-z]{2})?/$#i', $main_path);
        $prefixed = $selected_mode === 'prefixed' || $path_looks_prefixed;

        $result['mode'] = $prefixed ? 'prefixed' : 'implicit';
        $result['label'] = $prefixed
            ? 'Uses /default-lang-code (prefixed default)'
            : 'Does not use /default-lang-code (implicit default)';
        $result['detail'] = $prefixed
            ? 'MultilingualPress default language URL mode is currently configured as prefixed (/default-lang-code) for this workspace.'
            : 'MultilingualPress default language URL mode is currently configured as native/implicit default (no /default-lang-code) for this workspace.';
        $result['source'] = 'aismart_default_lang_url_mode';
        return $result;
    }

    if ($provider === 'wpglobus') {
        $result['mode'] = 'implicit';
        $result['label'] = 'Usually does not use /default-lang-code (implicit default)';
        $result['detail'] = 'WPGlobus commonly keeps default language implicit and prefixes non-default languages; verify in WPGlobus URL settings if customized.';
        $result['source'] = 'provider-default';
        return $result;
    }

    return $result;
}

function aismart_token_dashboard() {
    $ctx = aismart_resolve_workspace_context();
    $credit_runtime = aismart_compute_workspace_live_credit((int) $ctx['workspace_id'], (float) $ctx['credit_balance'], 10);
    $live_credit = isset($credit_runtime['live']) ? (float) $credit_runtime['live'] : (float) $ctx['credit_balance'];
    $url_mode_updated = isset($_GET['url_mode_updated']) && $_GET['url_mode_updated'] === '1';
    $cloud_dashboard_url = add_query_arg([
        'source' => 'wordpress-plugin',
        'workspace' => (int) $ctx['workspace_id'],
    ], 'https://aismartcontent.co');
    $content_manager_page = admin_url('admin.php?page=aismart-token-usage');
    echo '<div class="wrap">';
    echo '<h1>AISmart Content Studio Dashboard</h1>';
    if ($url_mode_updated) {
        echo '<div class="notice notice-success is-dismissible"><p>URL mode updated. Redirected to Dashboard.</p></div>';
    }
    echo '<div style="max-width:920px;background:#fff;border:1px solid #dcdcde;border-radius:8px;padding:18px 20px;">';
    echo '<p style="margin:0 0 12px;">Manage connected workspace and content operations from the links below.</p>';
    echo '<ul style="margin:0 0 14px 18px;list-style:disc;">';
    echo '<li><strong>Workspace ID:</strong> ' . esc_html((string) ((int) $ctx['workspace_id'])) . '</li>';
    echo '<li><strong>Current Credits:</strong> ' . esc_html(number_format_i18n($live_credit, 2)) . '</li>';
    echo '</ul>';
    echo '<p style="display:flex;gap:10px;flex-wrap:wrap;margin:0;">';
    echo '<a class="button button-primary" target="_blank" rel="noopener noreferrer" href="' . esc_url($cloud_dashboard_url) . '">Open AISmart Cloud Dashboard</a>';
    echo '<a class="button" href="' . esc_url($content_manager_page) . '">Open Content Manager Page</a>';
    echo '</p>';
    echo '</div>';
    echo '</div>';
}


// Onboarding page with conditional rendering for "Completed" state

// Onboarding page with conditional rendering for "Completed" state

function aismart_token_onboarding_page() {
    // Check if already connected/ready
    $is_ready_check = aismart_onboarding_is_ready();
    $is_completed = !is_wp_error($is_ready_check);

    // If activation just finished and onboarding is already complete,
    // move admin to URL Mode step automatically.
    $setup = isset($_GET['setup']) ? sanitize_key((string) wp_unslash($_GET['setup'])) : '';
    if ($is_completed && in_array($setup, ['activated', 'recovered'], true)) {
        wp_safe_redirect(admin_url('admin.php?page=aismart-token-url-mode&setup=next'));
        exit;
    }
    
    // Get state for display
    $state = aismart_onboarding_state_get();
    $secret = aismart_plugin_get_signing_secret();
    $admin_email = aismart_onboarding_current_admin_email();
    
    // Detect language for display
    $multilang = aismart_onboarding_detect_multilang_provider();
    $provider = $multilang["primary"];
    $detected_list = implode(", ", $multilang["detected"]);
    $cache_diag = aismart_onboarding_cache_permission_status();
    $cache_ready = !empty($cache_diag['auto_cache_clear_ready']);
    $cache_diag_class = $cache_ready ? 'success' : 'warning';
    $cache_diag_title = $cache_ready
        ? 'Automatic cache clear is ready'
        : 'Automatic cache clear is limited on this server';
    $cache_diag_message = $cache_ready
        ? 'This server can run automatic cache clear steps after translation.'
        : 'Automatic cache clear is limited on this server. Translation still works, but you may need to clear cache manually from your cache/CDN tools.';
    $cache_wp_cli_binary = isset($cache_diag['wp_cli_binary']) ? (string) $cache_diag['wp_cli_binary'] : '';
    $cache_shell_mode = isset($cache_diag['shell_mode']) ? (string) $cache_diag['shell_mode'] : 'none';
    $cache_can_exec = !empty($cache_diag['can_exec']) ? 'Yes' : 'No';
    $cache_can_proc_open = !empty($cache_diag['can_proc_open']) ? 'Yes' : 'No';
    $cache_wp_cli_detected = !empty($cache_diag['wp_cli_detected']) ? 'Yes' : 'No';
    $cache_wp_cli_runnable = !empty($cache_diag['wp_cli_runnable']) ? 'Yes' : 'No';
    $cache_wp_cli_output = isset($cache_diag['wp_cli_output_preview']) ? (string) $cache_diag['wp_cli_output_preview'] : '';
    $cache_exec_ok = !empty($cache_diag['can_exec']);
    $cache_proc_ok = !empty($cache_diag['can_proc_open']);
    $cache_wpcli_ok = !empty($cache_diag['wp_cli_runnable']);
    $cache_summary_line = $cache_ready
        ? 'Great. The plugin can clear cache automatically after translation.'
        : 'No problem. Translation still works. You may need to click Purge Cache manually after translation.';

    // Common CSS
    $onboarding_inline_css = <<<'AISMART_ONBOARDING_CSS'
        .aismart-wrap { max-width: 800px; margin: 40px auto; font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen-Sans, Ubuntu, Cantarell, \"Helvetica Neue\", sans-serif; }
        .aismart-card { background: #fff; padding: 40px; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); text-align: center; }
        .aismart-logo { width: 80px; height: 80px; margin-bottom: 20px; }
        .aismart-title { font-size: 24px; font-weight: 600; margin-bottom: 10px; color: #1d2327; }
        .aismart-desc { font-size: 16px; color: #646970; margin-bottom: 30px; line-height: 1.5; }
        .aismart-btn { display: inline-block; background: #2271b1; color: #fff; padding: 12px 24px; font-size: 16px; font-weight: 500; text-decoration: none; border-radius: 4px; border: none; cursor: pointer; transition: background 0.2s; }
        .aismart-btn:hover { background: #135e96; color: #fff; }
        .aismart-status { margin-top: 20px; font-weight: 500; }
        .aismart-status.success { color: #00a32a; }
        .aismart-account-box { background: #fff; border: 1px solid #c3c4c7; border-radius: 10px; padding: 16px; margin-top: 18px; }
        .aismart-account-email { font-size: 18px; font-weight: 600; text-align: center; margin: 8px 0 4px 0; color: #1d2327; }
        .aismart-account-note { font-size: 13px; text-align: center; margin: 0 0 12px 0; color: #646970; }
        .aismart-account-match { display: inline-block; font-size: 12px; padding: 4px 8px; border-radius: 999px; }
        .aismart-account-match.ok { background: #d4edda; color: #155724; border: 1px solid #b7dfbe; }
        .aismart-account-match.warn { background: #fff4e5; color: #7a4b00; border: 1px solid #f0b429; }
        .aismart-account-match.info { background: #eef4ff; color: #1d3f72; border: 1px solid #b8c7e0; }
        .aismart-account-actions { margin-top: 12px; display: flex; justify-content: center; gap: 10px; flex-wrap: wrap; }
        
        .aismart-success-box { background: #d4edda; color: #155724; padding: 40px; border-radius: 8px; border: 1px solid #c3e6cb; text-align: left; }
        .aismart-success-title { margin-top: 0; font-size: 24px; display: flex; align-items: center; gap: 10px; }
        .aismart-checklist { list-style: none; padding: 0; margin: 20px 0; }
        .aismart-checklist li { margin-bottom: 10px; font-size: 16px; display: flex; align-items: center; gap: 10px; }
        .aismart-info-box { background: #fff; padding: 20px; border: 1px solid #c3c4c7; border-radius: 4px; margin-bottom: 20px; text-align: left; }
        .aismart-plugin-debug-box { background: #fff; padding: 24px; border: 1px solid #c3c4c7; border-radius: 10px; margin-bottom: 20px; text-align: left; }
        .aismart-permission-box { padding: 20px; border-radius: 8px; margin-bottom: 20px; text-align: left; border: 1px solid #c3e6cb; background: #d4edda; color: #155724; }
        .aismart-permission-box.warning { border-color: #f0b429; background: #fff7e6; color: #7a4b00; }
        .aismart-permission-title { margin: 0 0 8px 0; font-size: 18px; }
        .aismart-permission-sub { margin: 0; color: inherit; }
        .aismart-permission-toggle { margin-top: 12px; }
        .aismart-permission-details { margin-top: 12px; padding: 14px; border-radius: 8px; background: #fff; border: 1px solid rgba(0,0,0,.12); color: #1d2327; }
        .aismart-permission-checklist { list-style: none; padding: 0; margin: 0 0 12px 0; }
        .aismart-permission-checklist li { margin-bottom: 8px; }
        .aismart-permission-note { margin-top: 12px; padding: 10px 12px; border-radius: 8px; background: #f6f7f7; border: 1px dashed #c3c4c7; font-size: 13px; color: #1d2327; }
        .aismart-plugin-grid { display: grid; grid-template-columns: repeat(4, minmax(180px, 1fr)); gap: 10px 16px; margin-top: 14px; }
        .aismart-plugin-item { display: flex; align-items: center; gap: 8px; font-size: 14px; color: #1d2327; }
        .aismart-plugin-item input { margin: 0; }
        @media (max-width: 960px) {
            .aismart-plugin-grid { grid-template-columns: repeat(2, minmax(180px, 1fr)); }
            .aismart-permission-details { padding: 12px; }
        }
AISMART_ONBOARDING_CSS;
    aismart_enqueue_inline_style('aismart-onboarding-inline', $onboarding_inline_css);

    echo "<div class=\"aismart-wrap\">";

    echo "<div class=\"aismart-permission-box {$cache_diag_class}\">
        <h3 class=\"aismart-permission-title\">Server Check: " . esc_html($cache_diag_title) . "</h3>
        <p class=\"aismart-permission-sub\">" . esc_html($cache_summary_line) . "</p>
        <div class=\"aismart-permission-toggle\">
            <button type=\"button\" id=\"aismart-cache-readmore\" class=\"button button-secondary\" aria-expanded=\"false\" aria-controls=\"aismart-cache-details\">What does this mean?</button>
        </div>
        <div id=\"aismart-cache-details\" class=\"aismart-permission-details\" hidden>
            <ul class=\"aismart-permission-checklist\">
                <li><strong>" . ($cache_proc_ok ? '✅' : '❌') . " Server allows proc_open():</strong> " . esc_html($cache_can_proc_open) . " — this enables safe automation commands.</li>
                <li><strong>" . ($cache_exec_ok ? '✅' : '❌') . " Server allows exec():</strong> " . esc_html($cache_can_exec) . " — this is needed for WP-CLI checks.</li>
                <li><strong>" . ($cache_wpcli_ok ? '✅' : '❌') . " WP-CLI test passed:</strong> " . esc_html($cache_wp_cli_runnable) . " — confirms cache-clear commands can run correctly.</li>
            </ul>
            <div><strong>Shell mode:</strong> " . esc_html($cache_shell_mode) . "</div>
            <div><strong>WP-CLI detected:</strong> " . esc_html($cache_wp_cli_detected) . "</div>
            <div><strong>WP-CLI binary:</strong> " . esc_html($cache_wp_cli_binary !== '' ? $cache_wp_cli_binary : 'not found') . "</div>
            <div class=\"aismart-permission-note\">
                <strong>Beginner tip:</strong> after you translate content, open your cache plugin and click <strong>Purge Cache</strong> once.
                <br><strong>Why:</strong> your site may still show an old cached page even though the new translation is already saved.
                " . ($cache_wp_cli_output !== '' ? '<br><strong>Last WP-CLI check:</strong> ' . esc_html($cache_wp_cli_output) : '') . "
            </div>
        </div>
    </div>";

    if ($is_completed) {
        $dash_url = esc_url(admin_url("admin.php?page=aismart-token"));
        $prov_e = esc_html($provider);
        $det_e = esc_html($detected_list);
        $sec_e = esc_attr($secret);
        $mail_e = esc_attr($admin_email);
        $connected_email = aismart_onboarding_resolve_connected_email($state);
        $connected_user_id = isset($state['user_id']) ? (int) $state['user_id'] : 0;
        if ($connected_email !== '') {
            $connected_email_e = esc_html($connected_email);
            $emails_match = strcasecmp($connected_email, (string) $admin_email) === 0;
            $match_class = $emails_match ? 'ok' : 'warn';
            $match_text = $emails_match ? 'Connected email matches WordPress admin email' : 'Connected email is different from WordPress admin email';
        } else {
            $connected_email_e = $connected_user_id > 0
                ? esc_html('Email unavailable from API, connected user ID: ' . $connected_user_id)
                : esc_html('Unknown (not returned yet)');
            $match_class = 'info';
            $match_text = 'Connected account email is not provided by API in this response';
        }
        $match_text_e = esc_html($match_text);
        $provider_key = sanitize_key(strtolower((string) $provider));
        if ($provider_key === 'qtranslate-xt') {
            $provider_key = 'qtranslate';
        }
        $is_wpml = $provider_key === 'wpml' ? 'checked' : '';
        $is_polylang = $provider_key === 'polylang' ? 'checked' : '';
        $is_mlp = $provider_key === 'multilingualpress' ? 'checked' : '';
        $is_translatepress = $provider_key === 'translatepress' ? 'checked' : '';
        $is_falang = $provider_key === 'falang' ? 'checked' : '';
        $is_qtranslate = $provider_key === 'qtranslate' ? 'checked' : '';
        $is_wpglobus = $provider_key === 'wpglobus' ? 'checked' : '';
        $is_bogo = $provider_key === 'bogo' ? 'checked' : '';

        $active_url_mode = aismart_detect_provider_default_lang_url_mode($provider_key);
        $active_url_mode_label = esc_html((string) ($active_url_mode['label'] ?? 'Unknown'));
        $active_url_mode_detail = esc_html((string) ($active_url_mode['detail'] ?? ''));
        $active_url_mode_source = esc_html((string) ($active_url_mode['source'] ?? 'plugin-settings'));

        $detected_url_mode_items = '';
        $detected_keys = isset($multilang['detected']) && is_array($multilang['detected']) ? (array) $multilang['detected'] : [];
        foreach ($detected_keys as $detected_provider_raw) {
            $detected_provider = sanitize_key((string) $detected_provider_raw);
            if ($detected_provider === '') {
                continue;
            }
            if ($detected_provider === 'qtranslate-xt') {
                $detected_provider = 'qtranslate';
            }
            $mode_info = aismart_detect_provider_default_lang_url_mode($detected_provider);
            $label = esc_html((string) ($mode_info['label'] ?? 'Unknown'));
            $detail = esc_html((string) ($mode_info['detail'] ?? ''));
            $detected_url_mode_items .= '<li><strong>' . esc_html($detected_provider) . ':</strong> ' . $label . '<br><span style="color:#646970;">' . $detail . '</span></li>';
        }
        if ($detected_url_mode_items === '') {
            $detected_url_mode_items = '<li>No multilingual plugin detected.</li>';
        }
        $url_mode_settings_url = esc_url(admin_url('admin.php?page=aismart-token-url-mode'));
        
        echo "<div class=\"aismart-info-box\">
            <h3 style=\"margin-top:0;\">Detected language plugin: $prov_e</h3>
            <p style=\"margin-bottom:0;\">Found: $det_e</p>
        </div>

        <div class=\"aismart-plugin-debug-box\" id=\"aismart-plugin-debug-box\">
            <h3 style=\"margin:0 0 6px 0;\">Detected language plugin: $prov_e</h3>
            <p style=\"margin:0; color:#646970;\">Found: $det_e</p>
            <div class=\"aismart-plugin-grid\">
                <label class=\"aismart-plugin-item\"><input type=\"radio\" name=\"aismart_lang_debug\" value=\"wpml\" $is_wpml> WPML (The King)</label>
                <label class=\"aismart-plugin-item\"><input type=\"radio\" name=\"aismart_lang_debug\" value=\"polylang\" $is_polylang> Polylang (The Speedster)</label>
                <label class=\"aismart-plugin-item\"><input type=\"radio\" name=\"aismart_lang_debug\" value=\"translatepress\" $is_translatepress> TranslatePress (Hybrid)</label>
                <label class=\"aismart-plugin-item\"><input type=\"radio\" name=\"aismart_lang_debug\" value=\"bogo\" $is_bogo> Bogo (Minimalist)</label>
                <label class=\"aismart-plugin-item\"><input type=\"radio\" name=\"aismart_lang_debug\" value=\"multilingualpress\" $is_mlp> MultilingualPress (Enterprise)</label>
                <label class=\"aismart-plugin-item\"><input type=\"radio\" name=\"aismart_lang_debug\" value=\"falang\" $is_falang> Falang</label>
                <label class=\"aismart-plugin-item\"><input type=\"radio\" name=\"aismart_lang_debug\" value=\"qtranslate\" $is_qtranslate> qTranslate</label>
                <label class=\"aismart-plugin-item\"><input type=\"radio\" name=\"aismart_lang_debug\" value=\"wpglobus\" $is_wpglobus> WPGlobus</label>
            </div>
            <div style=\"margin-top:14px; padding:10px 12px; border:1px solid #dcdcde; border-radius:8px; background:#fff;\">
                <div><strong>Active plugin default-language URL mode:</strong> $active_url_mode_label</div>
                <div style=\"margin-top:4px; color:#646970;\">$active_url_mode_detail</div>
                <div style=\"margin-top:4px; color:#646970; font-size:12px;\">Detected from: $active_url_mode_source</div>
                <div style=\"margin-top:8px;\"><a href=\"$url_mode_settings_url\">Open AISmart URL Mode control</a></div>
            </div>
            <div style=\"margin-top:12px;\">
                <strong>Detected plugins URL behavior summary:</strong>
                <ul style=\"margin:8px 0 0 18px;\">$detected_url_mode_items</ul>
            </div>
        </div>

        <div class=\"aismart-success-box\">
            <h2 class=\"aismart-success-title\">Setup status: ✅ Completed</h2>
            <ul class=\"aismart-checklist\">
                <li>✅ Save Config</li>
                <li>✅ Exchange Code</li>
                <li>✅ Access Token</li>
                <li>✅ Workspace Linked</li>
                <li>✅ Site Registered</li>
            </ul>
            <a href=\"$dash_url\" class=\"button button-primary button-large\" style=\"margin-top: 10px;\">Go to AISmart Dashboard</a>
            <span style=\"margin-left: 15px;\">All required steps are done.</span>
            <div class=\"aismart-account-box\">
                <div style=\"text-align:center;\"><span class=\"aismart-account-match $match_class\">$match_text_e</span></div>
                <div class=\"aismart-account-email\">AISmartContent account: $connected_email_e</div>
                <p class=\"aismart-account-note\">Use this to verify which cloud account is currently linked to this site.</p>
                <div class=\"aismart-account-actions\">
                    <button type=\"button\" id=\"aismart_check_admin\" class=\"button button-primary\">Reconnect Account</button>
                    <button type=\"button\" id=\"aismart_disconnect_account\" class=\"button\">Disconnect</button>
                </div>
            </div>
        </div>

        <div style=\"margin-top: 30px; text-align: left;\">
            <label style=\"display:block; margin-bottom:5px; font-weight:600;\">Signing Secret:</label>
            <input type=\"text\" value=\"$sec_e\" class=\"widefat\" readonly style=\"background:#f0f0f1; color:#666;\">
            
            <label style=\"display:block; margin-top:15px; margin-bottom:5px; font-weight:600;\">Admin Email:</label>
            <input type=\"text\" value=\"$mail_e\" class=\"widefat\" readonly style=\"background:#f0f0f1; color:#666;\">
        </div>";
    } else {
        echo "<div class=\"aismart-card\">
            <svg class=\"aismart-logo\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M12 2L2 7L12 12L22 7L12 2Z\" stroke=\"#2271b1\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M2 17L12 22L22 17\" stroke=\"#2271b1\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M2 12L12 17L22 12\" stroke=\"#2271b1\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>
            <h1 class=\"aismart-title\">Connect to AI Smart Content</h1>
            <p class=\"aismart-desc\">Unlock various AI capabilities for your WordPress site. Connect your site to the cloud platform to get started.</p>
            
            <button id=\"aismart_check_admin\" class=\"aismart-btn\">Sign In / Connect</button> 
            <button id=\"aismart_manual_check\" class=\"aismart-btn\" style=\"display:none; background:#ccc; color:#000; margin-left: 10px;\">Connect Manually</button>
            
            <div id=\"aismart_status\" class=\"aismart-status\"></div>
            <p style=\"margin-top: 10px; font-size: 12px; color: #666;\">Redirecting to secure sign-in...</p>

            <div class=\"aismart-debug\" id=\"aismart_debug_state\" style=\"display:none;\"></div>
        </div>";
    }

    echo "<div style=\"margin-top: 40px; text-align: left; border-top: 1px solid #ddd; padding-top: 20px;\">
        <details>
            <summary style=\"cursor: pointer; color: #2271b1;\">Dev Tools / Debugging</summary>
            <div style=\"margin-top: 10px; border: 1px dashed #ccc; padding: 15px; background: #fafafa;\">
                <button id=\"aismart_save_config\" class=\"button\">Save Config (Reset)</button>
                <button id=\"aismart_signup\" class=\"button\">Direct Signup (Test)</button>
                <button id=\"aismart_connect\" class=\"button\">Direct Connect (Test)</button>
                <button id=\"aismart_exchange\" class=\"button\">Exchange Code</button>
                <button id=\"aismart_site_register\" class=\"button\">Register Site</button>
                <button id=\"aismart_google_signup\" class=\"button\">Google Signup Redirect</button>
                <p style=\"margin-top:10px;\">Exchange Code: <input type=\"text\" id=\"aismart_exchange_code\" class=\"regular-text\" /></p>
                <p><strong>Debug State:</strong></p>
                <pre id=\"aismart_debug_output\" style=\"background:#fff; padding:10px; border:1px solid #ddd; overflow:auto; max-height:200px;\">" . esc_html(print_r($state, true)) . "</pre>
            </div>
        </details>
    </div>";

    echo "</div>"; 

    $nonce = wp_create_nonce("aismart_onboarding_nonce");

                $onboarding_nonce_json = wp_json_encode($nonce);
                $onboarding_ajax_url_json = wp_json_encode(admin_url('admin-ajax.php'));
                $onboarding_inline_js = "
        (function() {
                    const nonce = {$onboarding_nonce_json};
                    const ajaxUrl = {$onboarding_ajax_url_json};
          const stateEl = document.getElementById(\"aismart_debug_state\");
          const outputEl = document.getElementById(\"aismart_debug_output\");
          const statusEl = document.getElementById(\"aismart_status\");
                    const cacheReadMoreBtn = document.getElementById(\"aismart-cache-readmore\");
                    const cacheDetailsEl = document.getElementById(\"aismart-cache-details\");

                    if (cacheReadMoreBtn && cacheDetailsEl) {
                        cacheReadMoreBtn.addEventListener(\"click\", function () {
                            const expanded = cacheReadMoreBtn.getAttribute(\"aria-expanded\") === \"true\";
                            cacheReadMoreBtn.setAttribute(\"aria-expanded\", expanded ? \"false\" : \"true\");
                            cacheReadMoreBtn.textContent = expanded ? \"What does this mean?\" : \"Hide details\";
                            cacheDetailsEl.hidden = expanded;
                        });
                    }
      
          function log(msg, data) {
            console.log(\"[AI Smart]\", msg, data);
            if(outputEl) outputEl.textContent = JSON.stringify(data || {}, null, 2);
          }
      
          function setVal(id, val) {
            const el = document.getElementById(id);
            if (el) el.value = val;
          }
          function selectedMultilangChoice() {
            const checked = document.querySelector('input[name=\"aismart_lang_debug\"]:checked');
            if (!checked || !checked.value) {
              return \"\";
            }
            return String(checked.value).trim();
          }
      
          async function post(action, data = {}) {
            const formData = new FormData();
            formData.append(\"action\", action);
            formData.append(\"nonce\", nonce);
            for (const k in data) {
                formData.append(k, data[k]);
            }
            const res = await fetch(ajaxUrl, { method: \"POST\", body: formData });
            const json = await res.json();
            if (!json.success) throw json;
            return json.data;
          }
      
          let pollingInterval = null;
      
          function stopPolling() {
            if (pollingInterval) {
                clearInterval(pollingInterval);
                pollingInterval = null;
            }
          }
      
          async function checkBootstrapStatus(bootstrapToken) {
              try {
                  const res = await post(\"aismart_onboarding_bootstrap_status\", { bootstrap_token: bootstrapToken });
                  log(\"bootstrap status\", res);
                  if (res.completed || res.auto_completed) {
                      stopPolling();
                      if(statusEl) {
                          statusEl.textContent = \"Connection Successful! Redirecting...\";
                          statusEl.className = \"aismart-status success\";
                      }
                      setTimeout(() => {
                          window.location.reload();
                      }, 2000);
                  } else if (res.ready && statusEl) {
                      statusEl.textContent = \"Authenticated. Finalizing setup...\";
                  }
              } catch (e) {
                  log(\"poll error\", e);
              }
          }
      
          function startBootstrapPolling(bootstrapToken) {
              stopPolling();
              const manualBtn = document.getElementById(\"aismart_manual_check\"); 
              if(manualBtn) { 
                  manualBtn.style.display = \"inline-block\"; 
                  manualBtn.onclick = () => checkBootstrapStatus(bootstrapToken); 
              } 
              pollingInterval = setInterval(() => {
                    checkBootstrapStatus(bootstrapToken);
              }, 3000);
          }
      
          const urlParams = new URLSearchParams(window.location.search);
          const returnedBootstrapToken = urlParams.get(\"plugin_bootstrap_token\") || urlParams.get(\"aismart_bootstrap_token\");
          const bouncerCode = urlParams.get(\"code\") || urlParams.get(\"exchange_code\");
          const bouncerStatus = (urlParams.get(\"status\") || \"\").toLowerCase();
          const legacyBootstrapStatus = (urlParams.get(\"aismart_bootstrap_status\") || \"\").toLowerCase();
          const bouncerSecret = urlParams.get(\"signing_secret\");
      
          const shouldHandleDirectCode = !returnedBootstrapToken && bouncerCode && (bouncerStatus === \"\" || bouncerStatus === \"connected\" || bouncerStatus === \"success\");
          if (shouldHandleDirectCode) {
              if(statusEl) statusEl.textContent = \"Saving credentials...\";
      
              let promiseChain = Promise.resolve();
              if (bouncerSecret) {
                  promiseChain = promiseChain.then(() => {
                      const multilangChoice = selectedMultilangChoice();
                      const payload = { signing_secret: bouncerSecret };
                      if (multilangChoice) {
                          payload.multilang_choice = multilangChoice;
                          payload.aismart_lang_debug = multilangChoice;
                      }
                      return post(\"aismart_onboarding_save_config\", payload);
                  });
              }

              promiseChain
                  .then(function() {
                      if(statusEl) statusEl.textContent = \"Verifying handshake...\";
                      return post(\"aismart_onboarding_exchange_code\", { exchange_code: bouncerCode });
                  })
                  .then(function() {
                      if(statusEl) statusEl.textContent = \"Registering site...\";
                      const multilangChoice = selectedMultilangChoice();
                      const payload = multilangChoice ? { multilang_choice: multilangChoice, aismart_lang_debug: multilangChoice } : {};
                      return post(\"aismart_onboarding_site_register\", payload).catch(function(err) {
                          log(\"site_register optional failed\", err);
                          return null;
                      });
                  })
                  .then(function() {
                      if(statusEl) statusEl.textContent = \"Done! Reloading...\";
                      setTimeout(function() {
                          const cleanUrl = window.location.pathname + \"?page=aismart-token-onboarding\";
                          window.location.href = cleanUrl;
                      }, 1200);
                  })
                  .catch(function(err) {
                      console.error(err);
                      if (statusEl) {
                          const apiMessage = (err && err.data && err.data.meta && err.data.meta.response && err.data.meta.response.message) ? err.data.meta.response.message : \"\";
                          const rawMessage = (err && err.data && err.data.message) ? err.data.message : (err && err.message ? err.message : \"\");
                          const message = (apiMessage || rawMessage || \"Connection failed.\").toString();
                          statusEl.textContent = \"Connection step failed: \" + message + \" Please click Sign In / Connect again.\";
                      }
                  });
          }
      
          const returnedIsReady = urlParams.get(\"ready\") === \"1\" || urlParams.get(\"success\") === \"1\" || bouncerStatus === \"connected\" || bouncerStatus === \"success\" || legacyBootstrapStatus === \"ready\" || legacyBootstrapStatus === \"connected\";
          const hasAccessToken = " . ($is_completed ? "true" : "false") . ";
      
          function ensureBootstrapInitialized() {
              if (returnedBootstrapToken) {
                  if(statusEl) statusEl.textContent = \"Verifying authentication...\";
                  checkBootstrapStatus(returnedBootstrapToken);
                  startBootstrapPolling(returnedBootstrapToken);
              }
          }
        
            const deepReadUrl = (input, keys, depth = 0) => {
                if (!input || typeof input !== \"object\" || depth > 8) return \"\";
                for (const k of keys) {
                    if (Object.prototype.hasOwnProperty.call(input, k)) {
                        const v = input[k];
                        if (typeof v === \"string\" && v.trim()) return v.trim();
                    }
                }
                for (const k of Object.keys(input)) {
                    const v = input[k];
                    if (v && typeof v === \"object\") {
                        const found = deepReadUrl(v, keys, depth + 1);
                        if (found) return found;
                    }
                }
                return \"\";
            };
      
            const withWpReturnUrl = (url) => {
                if (!url) return \"\";
                const wpReturnUrl = window.location.origin + window.location.pathname + \"?page=aismart-token-onboarding\";
                try {
                    const u = new URL(url, window.location.origin);
                    u.searchParams.set(\"wp_return_url\", wpReturnUrl);
                    u.searchParams.set(\"return_url\", wpReturnUrl);
                    u.searchParams.set(\"redirect_url\", wpReturnUrl);
                    u.searchParams.set(\"plugin_return\", \"1\");
                    return u.toString();
                } catch (e) {
                    const sep = url.indexOf(\"?\") === -1 ? \"?\" : \"&\";
                    const ret = encodeURIComponent(wpReturnUrl);
                    return url + sep + \"wp_return_url=\" + ret + \"&return_url=\" + ret + \"&redirect_url=\" + ret + \"&plugin_return=1\";
                }
            };
      
            if (!hasAccessToken && (returnedBootstrapToken || !returnedIsReady)) {
                ensureBootstrapInitialized();
            }
      
          const saveBtn = document.getElementById(\"aismart_save_config\");
          if(saveBtn) saveBtn.addEventListener(\"click\", async () => {
             try {
                const multilangChoice = selectedMultilangChoice();
                const payload = multilangChoice ? { multilang_choice: multilangChoice, aismart_lang_debug: multilangChoice } : {};
                const data = await post(\"aismart_onboarding_save_config\", payload);
                log(\"save_config ok\", data);
             }
             catch(e){ log(\"save_config failed\", e); }
          });
      
          const checkAdminBtn = document.getElementById(\"aismart_check_admin\");
          if(checkAdminBtn) checkAdminBtn.addEventListener(\"click\", async () => {
             try {
                const boot = await post(\"aismart_onboarding_bootstrap_init\");
                log(\"bootstrap init ok\", boot);
            
                const bootPayload = boot && boot.data && typeof boot.data === \"object\" ? boot.data : boot;
                const authUrl = withWpReturnUrl(deepReadUrl(bootPayload, [\"sign_in_url\", \"signin_url\", \"login_url\", \"google_url\", \"google_redirect_url\"]));
            
                if (authUrl) {
                    console.log(\"Redirecting to:\", authUrl); 
                    const popup = window.open(authUrl, \"_blank\", \"noopener,noreferrer\");
                    if(statusEl) {
                        if (popup && !popup.closed) {
                            statusEl.textContent = \"Opened secure sign-in in a new tab. Complete sign-in there, then return to this page.\";
                        } else {
                            statusEl.innerHTML = \"Popup was blocked. <a href=\\\"\" + authUrl + \"\\\" target=\\\"_blank\\\" rel=\\\"noopener noreferrer\\\">Click here to open sign-in in a new tab</a>.\";
                        }
                    }
                    const pollingToken = bootPayload.bootstrap_token || bootPayload.plugin_bootstrap_token; 
                    console.log(\"Starting polling with token:\", pollingToken); 
                    startBootstrapPolling(pollingToken);
                    return;
                }
            
                const pollingToken = bootPayload.bootstrap_token || bootPayload.plugin_bootstrap_token; 
                console.log(\"Starting polling with token:\", pollingToken); 
                startBootstrapPolling(pollingToken);
            
                try {
                    const data = await post(\"aismart_onboarding_check_admin\");
                    log(\"check_admin ok\", data);
                } catch (e2) {
                    log(\"check_admin skipped\", e2);
                }
            }
            catch(e){ log(\"check_admin failed\", e); }
          });
      
             const disconnectBtn = document.getElementById(\"aismart_disconnect_account\");
             if(disconnectBtn) disconnectBtn.addEventListener(\"click\", async () => {
                 const ok = window.confirm(\"Disconnect this site from current AI Smart onboarding credentials? You can reconnect anytime.\");
                 if (!ok) return;
                 try {
                     const data = await post(\"aismart_onboarding_disconnect\");
                     log(\"disconnect ok\", data);
                     window.location.href = window.location.pathname + \"?page=aismart-token-onboarding\";
                 } catch(e) {
                     log(\"disconnect failed\", e);
                     alert(\"Disconnect failed. Please try again.\");
                 }
             });

             // Dev Helpers
          const signupBtn = document.getElementById(\"aismart_signup\");
          if(signupBtn) signupBtn.addEventListener(\"click\", async () => { try { const data = await post(\"aismart_onboarding_signup\"); if (data.exchange_code) setVal(\"aismart_exchange_code\", data.exchange_code); log(\"signup ok\", data); } catch(e){ log(\"signup failed\", e); } });
      
          const connectBtn = document.getElementById(\"aismart_connect\");
          if(connectBtn) connectBtn.addEventListener(\"click\", async () => { try { const data = await post(\"aismart_onboarding_connect_existing\"); if (data.exchange_code) setVal(\"aismart_exchange_code\", data.exchange_code); log(\"connect ok\", data); } catch(e){ log(\"connect failed\", e); } });
      
          const googleBtn = document.getElementById(\"aismart_google_signup\");
          if(googleBtn) googleBtn.addEventListener(\"click\", async () => { try { const data = await post(\"aismart_onboarding_google_redirect\"); log(\"google redirect ok\", data); if (data.redirect_url) { const popup = window.open(data.redirect_url, \"_blank\", \"noopener,noreferrer\"); if(!(popup && !popup.closed) && statusEl) { statusEl.innerHTML = \"Popup was blocked. <a href=\\\"\" + data.redirect_url + \"\\\" target=\\\"_blank\\\" rel=\\\"noopener noreferrer\\\">Click here to open sign-in in a new tab</a>.\"; } } } catch(e){ log(\"google redirect failed\", e); } });
      
          const exchangeBtn = document.getElementById(\"aismart_exchange\");
          if(exchangeBtn) exchangeBtn.addEventListener(\"click\", async () => { try { const data = await post(\"aismart_onboarding_exchange_code\"); log(\"exchange ok\", data); } catch(e){ log(\"exchange failed\", e); } });
      
          const siteRegBtn = document.getElementById(\"aismart_site_register\");
          if(siteRegBtn) siteRegBtn.addEventListener(\"click\", async () => {
             try {
                const multilangChoice = selectedMultilangChoice();
                const payload = multilangChoice ? { multilang_choice: multilangChoice, aismart_lang_debug: multilangChoice } : {};
                const data = await post(\"aismart_onboarding_site_register\", payload);
                log(\"site_register ok\", data);
             } catch(e){
                log(\"site_register failed\", e);
             }
          });
      
        })();
                ";
                aismart_enqueue_inline_script('aismart-onboarding-inline', $onboarding_inline_js);
}


function aismart_canonical_api_base() {
    return 'https://aismartcontent.co';
}

function aismart_plugin_get_api_base() {
    return aismart_canonical_api_base();
}

function aismart_force_api_base_option($pre = null) {
    return aismart_canonical_api_base();
}

function aismart_force_api_base_option_update($new_value, $old_value = null) {
    return aismart_canonical_api_base();
}

add_filter('pre_option_aismart_plugin_api_base', 'aismart_force_api_base_option', 9999, 1);
add_filter('pre_update_option_aismart_plugin_api_base', 'aismart_force_api_base_option_update', 9999, 2);

function aismart_plugin_get_signing_secret() {
    if (defined('AISMART_PLUGIN_SIGNING_SECRET') && (string) AISMART_PLUGIN_SIGNING_SECRET !== '') {
        return (string) AISMART_PLUGIN_SIGNING_SECRET;
    }
    return (string) get_option('aismart_plugin_signing_secret', '');
}

function aismart_onboarding_current_admin_email() {
    $current = wp_get_current_user();
    if ($current instanceof WP_User && $current->exists() && is_email($current->user_email)) {
        return (string) $current->user_email;
    }

    $fallback = (string) get_option('admin_email', '');
    return is_email($fallback) ? $fallback : '';
}

function aismart_onboarding_resolve_connected_email($state) {
    $state = is_array($state) ? $state : [];

    $context = isset($state['account_context']) && is_array($state['account_context']) ? $state['account_context'] : [];
    $payload = isset($context['data']) && is_array($context['data']) ? $context['data'] : $context;
    if (isset($payload['connected_user']) && is_array($payload['connected_user'])) {
        $email = isset($payload['connected_user']['email']) ? trim((string) $payload['connected_user']['email']) : '';
        if (is_email($email)) {
            return (string) $email;
        }
    }

    $email = aismart_onboarding_deep_find_scalar($state, [
        'connected_email',
        'account_email',
        'user_email',
        'email',
    ]);

    if (is_email($email)) {
        return (string) $email;
    }

    return '';
}

function aismart_onboarding_cache_permission_status() {
    $result = [
        'can_exec' => false,
        'can_proc_open' => false,
        'shell_mode' => 'none',
        'wp_cli_binary' => '',
        'wp_cli_detected' => false,
        'wp_cli_runnable' => false,
        'wp_cli_output_preview' => '',
        'auto_cache_clear_ready' => false,
    ];

    $result['can_exec'] = function_exists('aismart_can_use_exec') ? (bool) aismart_can_use_exec() : false;
    $result['can_proc_open'] = function_exists('aismart_can_use_proc_open') ? (bool) aismart_can_use_proc_open() : false;

    if ($result['can_exec']) {
        $result['shell_mode'] = 'exec';
    } elseif ($result['can_proc_open']) {
        $result['shell_mode'] = 'proc_open';
    }

    $candidates = ['/usr/local/bin/wp', '/usr/bin/wp', 'wp'];
    foreach ($candidates as $candidate) {
        if ($candidate === 'wp') {
            if (!$result['can_exec'] && !$result['can_proc_open']) {
                continue;
            }
            $result['wp_cli_binary'] = 'wp';
            $result['wp_cli_detected'] = true;
            break;
        }
        if (is_file($candidate) && is_executable($candidate)) {
            $result['wp_cli_binary'] = $candidate;
            $result['wp_cli_detected'] = true;
            break;
        }
    }

    if (!$result['wp_cli_detected']) {
        return $result;
    }

    if (!function_exists('aismart_shell_run_capture')) {
        return $result;
    }

    $wpPath = rtrim((string) ABSPATH, '/');
    $wpCli = (string) $result['wp_cli_binary'];
    $phpPrefix = aismart_wp_cli_php_env_prefix();
    $base = $phpPrefix . escapeshellcmd($wpCli) . ' --path=' . escapeshellarg($wpPath);

    $output = [];
    $code = 1;
    $ran = aismart_shell_run_capture($base . ' --version 2>&1', $output, $code);
    $result['wp_cli_output_preview'] = substr(preg_replace('/\s+/u', ' ', implode("\n", (array) $output)), 0, 280);

    if ($ran && (int) $code === 0) {
        $result['wp_cli_runnable'] = true;
        $result['auto_cache_clear_ready'] = true;
        return $result;
    }

    $rootHint = strtolower((string) $result['wp_cli_output_preview']);
    if (strpos($rootHint, 'allow-root') !== false || strpos($rootHint, 'run this as root') !== false) {
        $retryOutput = [];
        $retryCode = 1;
        $retryRan = aismart_shell_run_capture($base . ' --allow-root --version 2>&1', $retryOutput, $retryCode);
        $result['wp_cli_output_preview'] = substr(preg_replace('/\s+/u', ' ', implode("\n", (array) $retryOutput)), 0, 280);
        if ($retryRan && (int) $retryCode === 0) {
            $result['wp_cli_runnable'] = true;
            $result['auto_cache_clear_ready'] = true;
            return $result;
        }
    }

    return $result;
}

function aismart_wp_cli_php_env_prefix() {
    $candidates = [
        '/usr/local/bin/php',
        '/opt/cpanel/ea-php82/root/usr/bin/php',
        '/opt/cpanel/ea-php81/root/usr/bin/php',
        '/usr/bin/php',
    ];

    foreach ($candidates as $php) {
        if (is_file($php) && is_executable($php)) {
             // quick check if it is CLI? No, just trust order for now.
            return 'WP_CLI_PHP=' . escapeshellarg($php) . ' ';
        }
    }

    return '';
}

function aismart_onboarding_deep_find_scalar($data, $keys) {
    if (!is_array($keys) || empty($keys)) {
        return '';
    }

    if (is_array($data)) {
        foreach ($keys as $key) {
            if (isset($data[$key]) && !is_array($data[$key])) {
                $value = trim((string) $data[$key]);
                if ($value !== '') {
                    return $value;
                }
            }
        }

        foreach ($data as $item) {
            if (is_array($item)) {
                $value = aismart_onboarding_deep_find_scalar($item, $keys);
                if ($value !== '') {
                    return $value;
                }
            }
        }
    }

    return '';
}

function aismart_onboarding_deep_find_int($data, $keys) {
    $value = aismart_onboarding_deep_find_scalar($data, $keys);
    if ($value === '') {
        return 0;
    }
    return (int) $value;
}

function aismart_onboarding_resolve_state_user_id($state = null) {
    $state = is_array($state) ? $state : aismart_onboarding_state_get();

    if (isset($state['user_id']) && is_numeric($state['user_id'])) {
        return (int) $state['user_id'];
    }

    return 0;
}

function aismart_onboarding_sync_account_context($state = null) {
    $state = is_array($state) ? $state : aismart_onboarding_state_get();
    $resolved_user_id = aismart_onboarding_resolve_state_user_id($state);
    $preferred_workspace_id = isset($state['workspace_id']) ? (int) $state['workspace_id'] : 0;
    if ($preferred_workspace_id <= 0) {
        $preferred_workspace_id = (int) get_option('aismart_workspace_id', 0);
    }
    $preserve_preferred_workspace = $preferred_workspace_id > 0 && !empty($state['workspace_switched_at']);

    $context_payload = [];
    if ($resolved_user_id > 0) {
        $context_payload['user_id'] = $resolved_user_id;
    }

    $context = aismart_plugin_api_request('GET', 'api/plugin/v1/account/context', $context_payload, false);
    if (!is_wp_error($context) && is_array($context)) {
        $state['account_context'] = $context;
        $state['account_context_at'] = gmdate('c');

        $payload = isset($context['data']) && is_array($context['data']) ? $context['data'] : $context;
        $active = isset($payload['active_workspace']) && is_array($payload['active_workspace']) ? $payload['active_workspace'] : [];

        $active_id = isset($active['id']) ? (int) $active['id'] : 0;
        if ($active_id > 0) {
            $state['active_workspace_id'] = $active_id;
            if (!$preserve_preferred_workspace || $preferred_workspace_id <= 0 || $preferred_workspace_id === $active_id) {
                $state['workspace_id'] = $active_id;
                update_option('aismart_workspace_id', $active_id, false);
            }
        }

        $active_name = isset($active['name']) ? sanitize_text_field((string) $active['name']) : '';
        if ($active_name !== '') {
            if (!$preserve_preferred_workspace || $preferred_workspace_id <= 0 || $preferred_workspace_id === $active_id) {
                $state['workspace_name'] = $active_name;
                update_option('aismart_workspace_name', $active_name, false);
            }
        }

        $connected_user = isset($payload['connected_user']) && is_array($payload['connected_user']) ? $payload['connected_user'] : [];
        $connected_user_id = isset($connected_user['id']) ? (int) $connected_user['id'] : 0;
        if ($connected_user_id > 0) {
            $state['user_id'] = $connected_user_id;
            $resolved_user_id = $connected_user_id;
        }

        $word_remaining = null;
        $image_remaining = null;

        if (!empty($connected_user) && $active_id > 0 && isset($payload['member_word_remaining']) && is_numeric($payload['member_word_remaining'])) {
            $word_remaining = (float) $payload['member_word_remaining'];
        }
        if (!empty($connected_user) && $active_id > 0 && isset($payload['member_image_remaining']) && is_numeric($payload['member_image_remaining'])) {
            $image_remaining = (float) $payload['member_image_remaining'];
        }

        if ($word_remaining !== null) {
            $state['member_word_remaining'] = $word_remaining;
            update_option('aismart_credit_balance', $word_remaining, false);
            update_option('aismart_credits_available', $word_remaining, false);
            if ($active_id > 0) {
                update_option('aismart_workspace_credits_' . $active_id, $word_remaining, false);
            }
        }
        if ($image_remaining !== null) {
            $state['member_image_remaining'] = $image_remaining;
        }
    }

    $workspaces_payload = [];
    if ($resolved_user_id > 0) {
        $workspaces_payload['user_id'] = $resolved_user_id;
    }

    $workspaces = aismart_plugin_api_request('GET', 'api/plugin/v1/account/workspaces', $workspaces_payload, false);
    if (!is_wp_error($workspaces) && is_array($workspaces)) {
        $payload = isset($workspaces['data']) && is_array($workspaces['data']) ? $workspaces['data'] : $workspaces;
        $list = isset($payload['workspaces']) && is_array($payload['workspaces'])
            ? $payload['workspaces']
            : (is_array($payload) ? $payload : []);

        $normalized = [];
        foreach ($list as $item) {
            if (!is_array($item)) {
                continue;
            }
            $wid = isset($item['workspace_id']) ? (int) $item['workspace_id'] : (isset($item['id']) ? (int) $item['id'] : 0);
            if ($wid <= 0) {
                continue;
            }
            $wname = isset($item['workspace_name']) ? (string) $item['workspace_name'] : (isset($item['name']) ? (string) $item['name'] : ('Workspace #' . $wid));

            $member_quota = isset($item['member_quota']) && is_array($item['member_quota']) ? $item['member_quota'] : [];
            $word_rem = null;
            if (isset($member_quota['word_remaining']) && is_numeric($member_quota['word_remaining'])) {
                $word_rem = (float) $member_quota['word_remaining'];
            } elseif (isset($member_quota['member_word_remaining']) && is_numeric($member_quota['member_word_remaining'])) {
                $word_rem = (float) $member_quota['member_word_remaining'];
            } elseif (isset($item['member_word_remaining']) && is_numeric($item['member_word_remaining'])) {
                $word_rem = (float) $item['member_word_remaining'];
            }

            $normalized_item = [
                'workspace_id' => $wid,
                'workspace_name' => sanitize_text_field($wname),
            ];
            if ($word_rem !== null) {
                $normalized_item['credit_balance'] = $word_rem;
                update_option('aismart_workspace_credits_' . $wid, $word_rem, false);
            }
            if (!empty($item['is_current']) || !empty($item['is_active'])) {
                $state['active_workspace_id'] = $wid;
                if (!$preserve_preferred_workspace || $preferred_workspace_id <= 0 || $preferred_workspace_id === $wid) {
                    $state['workspace_id'] = $wid;
                    $state['workspace_name'] = sanitize_text_field($wname);
                    update_option('aismart_workspace_id', $wid, false);
                    update_option('aismart_workspace_name', sanitize_text_field($wname), false);
                    if ($word_rem !== null) {
                        update_option('aismart_credit_balance', $word_rem, false);
                        update_option('aismart_credits_available', $word_rem, false);
                    }
                }
            }

            $normalized[] = $normalized_item;
        }

        if (!empty($normalized)) {
            $state['account_workspaces'] = $normalized;
            $state['account_workspaces_at'] = gmdate('c');
        }
    }

    aismart_onboarding_state_set($state);
    return $state;
}

function aismart_onboarding_finalize_bootstrap_from_token($bootstrap_token) {
    $bootstrap_token = is_string($bootstrap_token) ? sanitize_text_field($bootstrap_token) : '';
    if ($bootstrap_token === '') {
        return null;
    }

    $result = aismart_plugin_public_api_request('GET', 'api/plugin/v1/bootstrap/status', [
        'bootstrap_token' => $bootstrap_token,
    ], false);

    if (is_wp_error($result) || !is_array($result)) {
        return null;
    }

    $state = aismart_onboarding_state_get();
    $state['bootstrap_status'] = $result;
    $state['bootstrap_polled_at'] = gmdate('c');

    $bootstrap_payload = isset($result['data']) && is_array($result['data']) ? $result['data'] : $result;
    $bootstrap_state_raw = isset($bootstrap_payload['state']) && is_array($bootstrap_payload['state']) ? $bootstrap_payload['state'] : [];
    $bootstrap_state = !empty($bootstrap_state_raw) ? $bootstrap_state_raw : $bootstrap_payload;
    $status_value = strtolower(trim((string) ($bootstrap_state['status'] ?? $bootstrap_payload['status'] ?? '')));
    $is_ready_flag = !empty($bootstrap_payload['ready']) || !empty($bootstrap_payload['is_ready']) || !empty($bootstrap_state['ready']) || !empty($bootstrap_state['is_ready']);
    $is_ready_status = in_array($status_value, ['ready', 'completed', 'success', 'authenticated', 'connected'], true);
    $is_ready = $is_ready_flag || $is_ready_status;

    if ($is_ready) {
        $signing_secret = aismart_onboarding_deep_find_scalar($bootstrap_state, ['signing_secret', 'secret', 'plugin_signing_secret']);
        if ($signing_secret === '') {
            $signing_secret = aismart_onboarding_deep_find_scalar($bootstrap_payload, ['signing_secret', 'secret', 'plugin_signing_secret']);
        }
        $exchange_code = aismart_onboarding_deep_find_scalar($bootstrap_state, ['exchange_code', 'code', 'plugin_exchange_code']);
        if ($exchange_code === '') {
            $exchange_code = aismart_onboarding_deep_find_scalar($bootstrap_payload, ['exchange_code', 'code', 'plugin_exchange_code']);
        }

        if ($signing_secret !== '') {
            update_option('aismart_plugin_signing_secret', $signing_secret, false);
            $state['signing_secret_auto_saved'] = 1;
        }

        if ($exchange_code !== '') {
            $state['exchange_code'] = $exchange_code;
        }
    }

    aismart_onboarding_state_set($state);
    return $state;
}

function aismart_onboarding_try_auto_complete_state($state) {
    $state = is_array($state) ? $state : [];

    $exchange_code = isset($state['exchange_code']) ? trim((string) $state['exchange_code']) : '';
    if ($exchange_code === '') {
        $exchange_code = aismart_onboarding_deep_find_scalar($state, ['exchange_code', 'code', 'plugin_exchange_code']);
        if ($exchange_code !== '') {
            $state['exchange_code'] = $exchange_code;
        }
    }

    $signing_secret = aismart_plugin_get_signing_secret();
    if ($signing_secret === '') {
        $signing_secret = aismart_onboarding_deep_find_scalar($state, ['signing_secret', 'secret', 'plugin_signing_secret']);
        if ($signing_secret !== '') {
            update_option('aismart_plugin_signing_secret', $signing_secret, false);
            $state['signing_secret_auto_saved'] = 1;
        }
    }

    if ($exchange_code === '' || $signing_secret === '') {
        aismart_onboarding_state_set($state);
        return $state;
    }

    $has_access_token = isset($state['access_token']) && trim((string) $state['access_token']) !== '';
    if (!$has_access_token) {
        $exchange_payload = [
            'exchange_code' => $exchange_code,
            'site_domain' => wp_parse_url(home_url('/'), PHP_URL_HOST),
        ];

        $exchange_result = aismart_plugin_api_request('POST', 'api/plugin/v1/onboarding/exchange-code', $exchange_payload, true);
        if (!is_wp_error($exchange_result) && is_array($exchange_result)) {
            $state['access_token'] = isset($exchange_result['access_token']) ? (string) $exchange_result['access_token'] : '';
            $state['token_type'] = isset($exchange_result['token_type']) ? (string) $exchange_result['token_type'] : 'Bearer';
            $state['workspace_id'] = isset($exchange_result['workspace_id']) ? (int) $exchange_result['workspace_id'] : (isset($state['workspace_id']) ? (int) $state['workspace_id'] : 0);
            $state['user_id'] = isset($exchange_result['user_id']) ? (int) $exchange_result['user_id'] : (isset($state['user_id']) ? (int) $state['user_id'] : 0);
            $state['exchange_result'] = $exchange_result;
            $state['exchange_at'] = gmdate('c');
        }
    }

    if (!empty($state['workspace_id']) && empty($state['site_registered_at'])) {
        $multilang = aismart_onboarding_detect_multilang_provider();
        $site_payload = [
            'workspace_id' => (int) $state['workspace_id'],
            'site_url' => home_url('/'),
            'site_domain' => wp_parse_url(home_url('/'), PHP_URL_HOST),
            'admin_email' => aismart_onboarding_current_admin_email(),
            'plugin_version' => '1.2.0',
            'multilang_provider' => $multilang['primary'],
            'multilang_detected' => $multilang['detected'],
        ];

        $site_result = aismart_plugin_api_request('POST', 'api/plugin/v1/site/register', $site_payload, true);
        if (!is_wp_error($site_result)) {
            $state['site_register'] = $site_result;
            $state['site_registered_at'] = gmdate('c');
        }
    }

    aismart_onboarding_state_set($state);
    return $state;
}

function aismart_onboarding_detect_multilang_provider() {
    $detected = [];

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

    $is_active = static function(array $plugin_files): bool {
        foreach ($plugin_files as $plugin_file) {
            if (function_exists('is_plugin_active') && is_plugin_active($plugin_file)) {
                return true;
            }
            if (function_exists('is_plugin_active_for_network') && is_plugin_active_for_network($plugin_file)) {
                return true;
            }
        }
        return false;
    };

    if (
        $is_active(['sitepress-multilingual-cms/sitepress.php'])
        || $is_active(['wpml-media-translation/plugin.php', 'wpml-string-translation/plugin.php', 'woocommerce-multilingual/wpml-woocommerce.php'])
        || defined('ICL_SITEPRESS_VERSION')
        || class_exists('SitePress', false)
    ) {
        $detected[] = 'wpml';
    }

    if (
        $is_active(['polylang/polylang.php', 'polylang-pro/polylang.php'])
        || defined('POLYLANG_VERSION')
        || function_exists('pll_current_language')
    ) {
        $detected[] = 'polylang';
    }
    if (
        $is_active(['translatepress-multilingual/index.php'])
        || defined('TRP_PLUGIN_VERSION')
        || function_exists('trp_get_languages')
    ) {
        $detected[] = 'translatepress';
    }
    if (
        $is_active(['bogo/bogo.php'])
        || defined('BOGO_VERSION')
    ) {
        $detected[] = 'bogo';
    }
    if (
        $is_active(['multilingual-press/multilingual-press.php', 'multilingual-press/multilingualpress.php', 'multilingualpress/multilingualpress.php'])
        || class_exists('Inpsyde\MultilingualPress\MultilingualPress', false)
        || class_exists('Multilingual_Press', false)
        || function_exists('mlp_init')
    ) {
        $detected[] = 'multilingualpress';
    }
    if (
        $is_active(['qtranslate-x/qtranslate.php', 'qtranslate-xt/qtranslate.php'])
        || defined('QTX_VERSION')
    ) {
        $detected[] = 'qtranslate';
    }
    if (
        $is_active(['wpglobus/wpglobus.php'])
        || class_exists('WPGlobus', false)
    ) {
        $detected[] = 'wpglobus';
    }
    if (
        $is_active(['falang/falang.php'])
        || class_exists('Falang', false)
    ) {
        $detected[] = 'falang';
    }
    if (
        $is_active(['sublanguage/sublanguage.php'])
        || class_exists('Sublanguage_Main', false)
        || class_exists('Sublanguage_core', false)
        || isset($GLOBALS['sublanguage'])
    ) {
        $detected[] = 'sublanguage';
    }

    if (empty($detected)) {
        $detected[] = 'none';
    }

    return [
        'primary' => (string) $detected[0],
        'detected' => array_values(array_unique($detected)),
    ];
}

function aismart_onboarding_prefetch_bootstrap($admin_email) {
    $admin_email = is_string($admin_email) ? sanitize_email($admin_email) : '';
    if (!is_email($admin_email)) {
        return [];
    }

    $payload = [
        'admin_email' => $admin_email,
        'site_url' => home_url('/'),
        'site_domain' => wp_parse_url(home_url('/'), PHP_URL_HOST),
        'wp_return_url' => admin_url('admin.php?page=aismart-token-onboarding'),
    ];

    $result = aismart_plugin_public_api_request('POST', 'api/plugin/v1/bootstrap/init', $payload, true);
    if (is_wp_error($result) || !is_array($result)) {
        return [];
    }

    return $result;
}

function aismart_plugin_api_request($method, $path, $payload = [], $use_idempotency = false, $idempotency_key = '') {
    $method = strtoupper((string) $method);
    $api_base = aismart_plugin_get_api_base();
    $secret = aismart_plugin_get_signing_secret();

    if ($secret === '') {
        return new WP_Error('missing_secret', 'Signing secret is empty. Save config first.');
    }

    $nonce = wp_generate_uuid4();
    $timestamp = (string) time();
    $path = ltrim((string) $path, '/');

    $body = '';
    $url = $api_base . '/' . $path;
    if ($method === 'GET') {
        if (!empty($payload) && is_array($payload)) {
            $url = add_query_arg($payload, $url);
        }
    } else {
        $body = wp_json_encode($payload);
        if (!is_string($body)) {
            $body = '';
        }
    }

    $body_hash = hash('sha256', $body);
    $signature_payload = $method . "\n" . $path . "\n" . $timestamp . "\n" . $nonce . "\n" . $body_hash;
    $signature = hash_hmac('sha256', $signature_payload, $secret);

    $headers = [
        'Content-Type' => 'application/json',
        'Accept' => 'application/json',
        'X-Aismart-Timestamp' => $timestamp,
        'X-Aismart-Nonce' => $nonce,
        'X-Aismart-Signature' => $signature,
    ];

    if ($use_idempotency) {
        $key = trim((string) $idempotency_key);
        if ($key === '') {
            $key = 'wp-' . md5($path . '|' . $timestamp . '|' . wp_rand());
        }
        $headers['X-Idempotency-Key'] = $key;
    }

    $args = [
        'timeout' => 40,
        'redirection' => 0,
        'method' => $method,
        'headers' => $headers,
        'sslverify' => true,
    ];

    if ($method !== 'GET') {
        $args['body'] = $body;
    }

    $response = wp_remote_request($url, $args);
    if (is_wp_error($response)) {
        return $response;
    }

    $code = (int) wp_remote_retrieve_response_code($response);
    $raw = (string) wp_remote_retrieve_body($response);
    $json = json_decode($raw, true);

    if (!is_array($json)) {
        return new WP_Error('invalid_json', 'Invalid API JSON response', ['status' => $code, 'raw' => $raw]);
    }

    if ($code >= 400) {
        return new WP_Error('api_error', 'API request failed', ['status' => $code, 'response' => $json]);
    }

    return $json;
}

function aismart_plugin_public_api_request($method, $path, $payload = [], $use_idempotency = false) {
    $method = strtoupper((string) $method);
    $api_base = aismart_plugin_get_api_base();
    $path = ltrim((string) $path, '/');

    $body = '';
    $url = $api_base . '/' . $path;
    if ($method === 'GET') {
        if (!empty($payload) && is_array($payload)) {
            $url = add_query_arg($payload, $url);
        }
    } else {
        $body = wp_json_encode($payload);
        if (!is_string($body)) {
            $body = '';
        }
    }

    $headers = [
        'Content-Type' => 'application/json',
        'Accept' => 'application/json',
    ];

    if ($use_idempotency) {
        $headers['X-Idempotency-Key'] = 'wp-public-' . md5($path . '|' . time() . '|' . wp_rand());
    }

    $args = [
        'timeout' => 40,
        'redirection' => 0,
        'method' => $method,
        'headers' => $headers,
        'sslverify' => true,
    ];

    if ($method !== 'GET') {
        $args['body'] = $body;
    }

    $response = wp_remote_request($url, $args);
    if (is_wp_error($response)) {
        return $response;
    }

    $code = (int) wp_remote_retrieve_response_code($response);
    $raw = (string) wp_remote_retrieve_body($response);
    $json = json_decode($raw, true);

    if (!is_array($json)) {
        return new WP_Error('invalid_json', 'Invalid API JSON response', ['status' => $code, 'raw' => $raw]);
    }

    if ($code >= 400) {
        return new WP_Error('api_error', 'API request failed', ['status' => $code, 'response' => $json]);
    }

    return $json;
}

function aismart_onboarding_state_get() {
    $state = get_option('aismart_plugin_onboarding_state', []);
    return is_array($state) ? $state : [];
}

function aismart_onboarding_state_set($state) {
    update_option('aismart_plugin_onboarding_state', is_array($state) ? $state : [], false);
}

function aismart_onboarding_is_ready() {
    $state = aismart_onboarding_state_get();

    $workspace_id = isset($state['workspace_id']) ? (int) $state['workspace_id'] : 0;
    if ($workspace_id <= 0) {
        return new WP_Error('onboarding_workspace_missing', 'Plugin onboarding incomplete: workspace is missing.');
    }

    $access_token = isset($state['access_token']) ? (string) $state['access_token'] : '';
    if ($access_token === '') {
        return new WP_Error('onboarding_token_missing', 'Plugin onboarding incomplete: access token is missing.');
    }

    return true;
}

function aismart_onboarding_guard_ajax() {
    if (!current_user_can('manage_options')) {
        wp_send_json_error(['message' => 'Unauthorized'], 403);
    }
    check_ajax_referer('aismart_onboarding_nonce', 'nonce');
}

add_action('wp_ajax_aismart_onboarding_save_config', 'aismart_onboarding_save_config');
function aismart_onboarding_save_config() {
    aismart_onboarding_guard_ajax();

    $api_base = 'https://aismartcontent.co';
    $signing_secret = isset($_POST['signing_secret']) ? sanitize_text_field(wp_unslash($_POST['signing_secret'])) : '';
    $selected_provider = isset($_POST['multilang_choice'])
        ? sanitize_text_field(wp_unslash($_POST['multilang_choice']))
        : (isset($_POST['aismart_lang_debug']) ? sanitize_text_field(wp_unslash($_POST['aismart_lang_debug'])) : '');
    $selected_provider = aismart_normalize_provider_key($selected_provider);
    $allowed_provider = ['wpml', 'polylang', 'multilingualpress', 'translatepress', 'falang', 'qtranslate', 'wpglobus', 'bogo'];
    if (!in_array($selected_provider, $allowed_provider, true)) {
        $selected_provider = '';
    }

    if (defined('AISMART_PLUGIN_SIGNING_SECRET') && (string) AISMART_PLUGIN_SIGNING_SECRET !== '') {
        $signing_secret = (string) AISMART_PLUGIN_SIGNING_SECRET;
    }

    if ($signing_secret === 'AISMART_PLUGIN_SIGNING_SECRET') {
        wp_send_json_error(['message' => 'Please set a real signing secret. Placeholder value is not allowed.'], 422);
    }

    update_option('aismart_plugin_api_base', $api_base, false);
    if ($signing_secret !== '') {
        update_option('aismart_plugin_signing_secret', $signing_secret, false);
    }

    $state = aismart_onboarding_state_get();
    $switch_result = [];
    if ($selected_provider !== '') {
        $switch_result = aismart_onboarding_apply_provider_group_switch($selected_provider);
        $state['multilang_provider'] = $selected_provider;
        $state['multilang_selected_at'] = gmdate('c');
        $state['multilang_switch'] = $switch_result;
    }
    $state['config_saved_at'] = gmdate('c');
    $env_sync = aismart_sync_embedded_env_file();
    if (!empty($env_sync['ok'])) {
        $state['env_synced_at'] = gmdate('c');
        unset($state['env_sync_error']);
    } else {
        $state['env_sync_error'] = isset($env_sync['message']) ? (string) $env_sync['message'] : 'env sync failed';
    }
    aismart_onboarding_state_set($state);

    wp_send_json_success([
        'message' => 'Config saved',
        'state' => $state,
        'selected_provider' => $selected_provider,
        'plugin_switch' => $switch_result,
        'env_sync' => [
            'ok' => !empty($env_sync['ok']),
            'message' => isset($env_sync['message']) ? (string) $env_sync['message'] : '',
        ],
    ]);
}

add_action('wp_ajax_aismart_onboarding_disconnect', 'aismart_onboarding_disconnect');
function aismart_onboarding_disconnect() {
    aismart_onboarding_guard_ajax();

    $state = aismart_onboarding_state_get();
    $workspace_id = isset($state['workspace_id']) ? (int) $state['workspace_id'] : 0;
    $user_id = isset($state['user_id']) ? (int) $state['user_id'] : 0;

    $payload = [
        'site_url' => home_url('/'),
        'site_domain' => wp_parse_url(home_url('/'), PHP_URL_HOST),
    ];
    if ($workspace_id > 0) {
        $payload['workspace_id'] = $workspace_id;
    }
    if ($user_id > 0) {
        $payload['user_id'] = $user_id;
    }

    $unlink_result = aismart_plugin_api_request('POST', 'api/plugin/v1/onboarding/unlink', $payload, true);
    $unlink_error = is_wp_error($unlink_result) ? $unlink_result->get_error_message() : '';

    delete_option('aismart_plugin_signing_secret');
    delete_option('aismart_plugin_onboarding_state');
    delete_option('aismart_workspace_id');
    delete_option('aismart_workspace_name');
    delete_option('aismart_credit_balance');
    delete_option('aismart_credits_available');

    wp_send_json_success([
        'message' => $unlink_error === ''
            ? 'Disconnected and unlinked from cloud. Local onboarding credentials were cleared.'
            : 'Disconnected locally. Cloud unlink returned: ' . $unlink_error,
        'cloud_unlink_ok' => $unlink_error === '',
    ]);
}

add_action('wp_ajax_aismart_onboarding_check_admin', 'aismart_onboarding_check_admin');
function aismart_onboarding_check_admin() {
    aismart_onboarding_guard_ajax();

    $admin_email = aismart_onboarding_current_admin_email();
    if (!is_email($admin_email)) {
        wp_send_json_error(['message' => 'Valid admin email required'], 422);
    }

    $payload = [
        'admin_email' => $admin_email,
        'site_url' => home_url('/'),
        'site_domain' => wp_parse_url(home_url('/'), PHP_URL_HOST),
        'wp_return_url' => admin_url('admin.php?page=aismart-token-onboarding'),
    ];

    $result = aismart_plugin_api_request('POST', 'api/plugin/v1/onboarding/check-admin', $payload, true);
    if (is_wp_error($result)) {
        wp_send_json_error(['message' => $result->get_error_message(), 'meta' => $result->get_error_data()], 500);
    }

    $state = aismart_onboarding_state_get();
    $state['check_admin'] = $result;
    $state['admin_email'] = $admin_email;
    $state['checked_at'] = gmdate('c');
    aismart_onboarding_state_set($state);

    wp_send_json_success(['message' => 'Admin checked', 'result' => $result, 'state' => $state]);
}

add_action('wp_ajax_aismart_onboarding_bootstrap_init', 'aismart_onboarding_bootstrap_init');
function aismart_onboarding_bootstrap_init() {
    aismart_onboarding_guard_ajax();

    $admin_email = aismart_onboarding_current_admin_email();
    if (!is_email($admin_email)) {
        wp_send_json_error(['message' => 'Valid admin email required'], 422);
    }

    $payload = [
        'admin_email' => $admin_email,
        'site_url' => home_url('/'),
        'site_domain' => wp_parse_url(home_url('/'), PHP_URL_HOST),
        'wp_return_url' => admin_url('admin.php?page=aismart-token-onboarding'),
    ];

    $result = aismart_plugin_public_api_request('POST', 'api/plugin/v1/bootstrap/init', $payload, true);
    if (is_wp_error($result)) {
        wp_send_json_error(['message' => $result->get_error_message(), 'meta' => $result->get_error_data()], 500);
    }

    $state = aismart_onboarding_state_get();
    $state['bootstrap'] = $result;
    $state['admin_email'] = $admin_email;
    $bootstrap_init_payload = isset($result['data']) && is_array($result['data']) ? $result['data'] : $result;
    $state['bootstrap_token'] = aismart_onboarding_deep_find_scalar($bootstrap_init_payload, ['bootstrap_token', 'plugin_bootstrap_token']);
    $state['bootstrap_init_at'] = gmdate('c');
    aismart_onboarding_state_set($state);

    $result['state'] = $state;
    wp_send_json_success($result);
}

add_action('wp_ajax_aismart_onboarding_bootstrap_status', 'aismart_onboarding_bootstrap_status');
function aismart_onboarding_bootstrap_status() {
    aismart_onboarding_guard_ajax();

    $posted_token = isset($_POST['bootstrap_token']) ? sanitize_text_field(wp_unslash($_POST['bootstrap_token'])) : '';
    $state = aismart_onboarding_state_get();
    $bootstrap_token = $posted_token !== '' ? $posted_token : (isset($state['bootstrap_token']) ? (string) $state['bootstrap_token'] : '');
    
    if ($bootstrap_token === '') {
        wp_send_json_error(['message' => 'Bootstrap token required'], 422);
    }

    $result = aismart_plugin_public_api_request('GET', 'api/plugin/v1/bootstrap/status', ['bootstrap_token' => $bootstrap_token], false);
    
    if (is_wp_error($result)) {
        wp_send_json_error(['message' => $result->get_error_message(), 'meta' => $result->get_error_data()], 500);
    }

    $state['bootstrap_status'] = $result;
    $state['bootstrap_polled_at'] = gmdate('c');

    $bootstrap_payload = isset($result['data']) && is_array($result['data']) ? $result['data'] : $result;
    $bootstrap_state_raw = isset($bootstrap_payload['state']) && is_array($bootstrap_payload['state']) ? $bootstrap_payload['state'] : [];
    $bootstrap_state = !empty($bootstrap_state_raw) ? $bootstrap_state_raw : $bootstrap_payload;
    $resolved_workspace_id = aismart_onboarding_deep_find_int($bootstrap_state, ['workspace_id', 'workspaceId']);
    if ($resolved_workspace_id <= 0) {
        $resolved_workspace_id = aismart_onboarding_deep_find_int($bootstrap_payload, ['workspace_id', 'workspaceId']);
    }
    $state['workspace_id'] = $resolved_workspace_id > 0 ? $resolved_workspace_id : ($state['workspace_id'] ?? 0);
    
    $status_value = strtolower(trim((string) ($bootstrap_state['status'] ?? $bootstrap_payload['status'] ?? '')));
    $is_ready_flag = !empty($bootstrap_payload['ready']) || !empty($bootstrap_payload['is_ready']) || !empty($bootstrap_state['ready']) || !empty($bootstrap_state['is_ready']);
    $is_ready_status = in_array($status_value, ['ready', 'completed', 'success', 'authenticated', 'connected'], true);
    $is_ready = $is_ready_flag || $is_ready_status;

    $completed = false;

    if ($is_ready) {
        $signing_secret = aismart_onboarding_deep_find_scalar($bootstrap_state, ['signing_secret', 'secret', 'plugin_signing_secret']);
        if ($signing_secret === '') {
            $signing_secret = aismart_onboarding_deep_find_scalar($bootstrap_payload, ['signing_secret', 'secret', 'plugin_signing_secret']);
        }
        $exchange_code = aismart_onboarding_deep_find_scalar($bootstrap_state, ['exchange_code', 'code', 'plugin_exchange_code']);
        if ($exchange_code === '') {
            $exchange_code = aismart_onboarding_deep_find_scalar($bootstrap_payload, ['exchange_code', 'code', 'plugin_exchange_code']);
        }

        if ($signing_secret !== '') {
            update_option('aismart_plugin_signing_secret', $signing_secret, false);
            $state['signing_secret_auto_saved'] = 1;
        }

        if ($exchange_code !== '') {
            $state['exchange_code'] = $exchange_code;
        }

        $resolved_user_id = aismart_onboarding_deep_find_int($bootstrap_state, ['user_id', 'userId']);
        if ($resolved_user_id <= 0) {
            $resolved_user_id = aismart_onboarding_deep_find_int($bootstrap_payload, ['user_id', 'userId']);
        }
        $state['user_id'] = $resolved_user_id > 0 ? $resolved_user_id : ($state['user_id'] ?? 0);
        
        if ($exchange_code !== '' && $signing_secret !== '') {
            $exchange_payload = [
                'exchange_code' => $exchange_code,
                'site_domain' => wp_parse_url(home_url('/'), PHP_URL_HOST),
            ];

            $exchange_result = aismart_plugin_api_request('POST', 'api/plugin/v1/onboarding/exchange-code', $exchange_payload, true);
            
            if (!is_wp_error($exchange_result)) {
                $state['access_token'] = isset($exchange_result['access_token']) ? (string) $exchange_result['access_token'] : '';
                $state['token_type'] = isset($exchange_result['token_type']) ? (string) $exchange_result['token_type'] : 'Bearer';
                $state['workspace_id'] = isset($exchange_result['workspace_id']) ? (int) $exchange_result['workspace_id'] : ($state['workspace_id'] ?? 0);
                $state['user_id'] = isset($exchange_result['user_id']) ? (int) $exchange_result['user_id'] : ($state['user_id'] ?? 0);
                $state['exchange_result'] = $exchange_result;
                $state['exchange_at'] = gmdate('c');

                if (!empty($state['workspace_id'])) {
                    $multilang = aismart_onboarding_detect_multilang_provider();
                    $site_payload = [
                        'workspace_id' => (int) $state['workspace_id'],
                        'site_url' => home_url('/'),
                        'site_domain' => wp_parse_url(home_url('/'), PHP_URL_HOST),
                        'admin_email' => aismart_onboarding_current_admin_email(),
                        'plugin_version' => '1.2.0',
                        'multilang_provider' => $multilang['primary'],
                        'multilang_detected' => $multilang['detected'],
                    ];

                    $site_result = aismart_plugin_api_request('POST', 'api/plugin/v1/site/register', $site_payload, true);
                    
                    if (!is_wp_error($site_result)) {
                        $state['site_register'] = $site_result;
                        $state['site_registered_at'] = gmdate('c');
                        $completed = true;
                    }
                }
            }
        }
    }

    aismart_onboarding_state_set($state);

    wp_send_json_success([
        'message' => $completed ? 'Bootstrap completed and plugin connected.' : ($is_ready ? 'Sign-in completed. Finalizing plugin setup.' : 'Bootstrap status updated.'),
        'ready' => $is_ready,
        'completed' => $completed,
        'auto_completed' => $completed,
        'bootstrap' => $result,
        'state' => $state,
    ]);
}
function aismart_onboarding_signup() {
    aismart_onboarding_guard_ajax();

    $admin_email = aismart_onboarding_current_admin_email();
    $name = isset($_POST['signup_name']) ? sanitize_text_field(wp_unslash($_POST['signup_name'])) : '';
    $password = isset($_POST['signup_password']) ? (string) wp_unslash($_POST['signup_password']) : '';
    
    if (!is_email($admin_email) || $name === '' || strlen($password) < 6) {
        wp_send_json_error(['message' => 'Signup requires valid email, name, and password (min 6).'], 422);
    }

    $payload = [
        'name' => $name,
        'email' => $admin_email,
        'password' => $password,
        'site_url' => home_url('/'),
        'site_domain' => wp_parse_url(home_url('/'), PHP_URL_HOST),
    ];

    $result = aismart_plugin_api_request('POST', 'api/plugin/v1/onboarding/signup', $payload, true);
    if (is_wp_error($result)) {
        wp_send_json_error(['message' => $result->get_error_message(), 'meta' => $result->get_error_data()], 500);
    }

    $state = aismart_onboarding_state_get();
    $state['signup'] = $result;
    $state['exchange_code'] = $result['exchange_code'] ?? '';
    $state['workspace_id'] = isset($result['workspace_id']) ? (int) $result['workspace_id'] : 0;
    $state['signup_at'] = gmdate('c');
    aismart_onboarding_state_set($state);

    wp_send_json_success(['message' => 'Signup success', 'exchange_code' => $state['exchange_code'], 'result' => $result, 'state' => $state]);
}

add_action('wp_ajax_aismart_onboarding_connect_existing', 'aismart_onboarding_connect_existing');
function aismart_onboarding_connect_existing() {
    aismart_onboarding_guard_ajax();

    $admin_email = aismart_onboarding_current_admin_email();
    if (!is_email($admin_email)) {
        wp_send_json_error(['message' => 'Valid admin email required'], 422);
    }

    $payload = [
        'admin_email' => $admin_email,
        'site_url' => home_url('/'),
        'site_domain' => wp_parse_url(home_url('/'), PHP_URL_HOST),
    ];

    $result = aismart_plugin_api_request('POST', 'api/plugin/v1/onboarding/connect', $payload, true);
    if (is_wp_error($result)) {
        wp_send_json_error(['message' => $result->get_error_message(), 'meta' => $result->get_error_data()], 500);
    }

    $state = aismart_onboarding_state_get();
    $state['connect'] = $result;
    $state['exchange_code'] = $result['exchange_code'] ?? '';
    $state['workspace_id'] = isset($result['workspace_id']) ? (int) $result['workspace_id'] : ($state['workspace_id'] ?? 0);
    $state['connect_at'] = gmdate('c');
    aismart_onboarding_state_set($state);

    wp_send_json_success(['message' => 'Connect exchange code issued', 'exchange_code' => $state['exchange_code'], 'result' => $result, 'state' => $state]);
}

add_action('wp_ajax_aismart_onboarding_google_redirect', 'aismart_onboarding_google_redirect');
function aismart_onboarding_google_redirect() {
    aismart_onboarding_guard_ajax();

    $state = aismart_onboarding_state_get();
    $bootstrap_token = isset($state['bootstrap_token']) ? (string) $state['bootstrap_token'] : '';
    if ($bootstrap_token === '' && isset($_POST['bootstrap_token'])) {
        $bootstrap_token = sanitize_text_field(wp_unslash($_POST['bootstrap_token']));
    }

    $query = [
        'wp_return_url' => admin_url('admin.php?page=aismart-token-onboarding'),
    ];
    if ($bootstrap_token !== '') {
        $query['plugin_bootstrap_token'] = $bootstrap_token;
    }

    $result = aismart_plugin_api_request('GET', 'api/plugin/v1/onboarding/google/redirect', $query, true);
    if (is_wp_error($result)) {
        wp_send_json_error(['message' => $result->get_error_message(), 'meta' => $result->get_error_data()], 500);
    }

    $redirect_url = isset($result['redirect_url']) ? (string) $result['redirect_url'] : '';
    if ($redirect_url !== '' && strpos($redirect_url, 'http') !== 0) {
        $api_base = aismart_plugin_get_api_base();
        $redirect_url = rtrim($api_base, '/') . '/' . ltrim($redirect_url, '/');
    }

    if ($redirect_url !== '') {
        $redirect_url = add_query_arg([
            'wp_return_url' => admin_url('admin.php?page=aismart-token-onboarding'),
        ], $redirect_url);
        if ($bootstrap_token !== '') {
            $redirect_url = add_query_arg([
                'plugin_bootstrap_token' => $bootstrap_token,
            ], $redirect_url);
        }
    }

    $state['google_redirect'] = $redirect_url;
    $state['google_redirect_at'] = gmdate('c');
    aismart_onboarding_state_set($state);

    wp_send_json_success([
        'message' => 'Google redirect URL generated',
        'redirect_url' => $redirect_url,
        'result' => $result,
        'state' => $state,
    ]);
}

add_action('wp_ajax_aismart_onboarding_exchange_code', 'aismart_onboarding_exchange_code');
function aismart_onboarding_exchange_code() {
    aismart_onboarding_guard_ajax();

    $exchange_code = isset($_POST['exchange_code']) ? sanitize_text_field(wp_unslash($_POST['exchange_code'])) : '';
    if ($exchange_code === '') {
        wp_send_json_error(['message' => 'Exchange code required'], 422);
    }

    $payload = [
        'exchange_code' => $exchange_code,
        'site_domain' => wp_parse_url(home_url('/'), PHP_URL_HOST),
    ];

    $result = aismart_plugin_api_request('POST', 'api/plugin/v1/onboarding/exchange-code', $payload, true);
    if (is_wp_error($result)) {
        wp_send_json_error(['message' => $result->get_error_message(), 'meta' => $result->get_error_data()], 500);
    }

    $state = aismart_onboarding_state_get();
    $state['access_token'] = isset($result['access_token']) ? (string) $result['access_token'] : '';
    $state['token_type'] = isset($result['token_type']) ? (string) $result['token_type'] : 'Bearer';
    $state['workspace_id'] = isset($result['workspace_id']) ? (int) $result['workspace_id'] : ($state['workspace_id'] ?? 0);
    $state['user_id'] = isset($result['user_id']) ? (int) $result['user_id'] : 0;
    $state['exchange_at'] = gmdate('c');
    aismart_onboarding_state_set($state);

    // Try to sync connected-user context and workspace allocations from cloud.
    $state = aismart_onboarding_sync_account_context($state);

    wp_send_json_success(['message' => 'Exchange success', 'result' => $result, 'state' => $state]);
}

add_action('wp_ajax_aismart_onboarding_site_register', 'aismart_onboarding_site_register');
function aismart_onboarding_site_register() {
    aismart_onboarding_guard_ajax();

    $state = aismart_onboarding_state_get();
    $workspace_id = isset($state['workspace_id']) ? (int) $state['workspace_id'] : 0;
    if ($workspace_id <= 0) {
        wp_send_json_error(['message' => 'Workspace not found. Run signup/connect and exchange first.'], 422);
    }

    $selected = isset($_POST['multilang_choice'])
        ? sanitize_text_field(wp_unslash($_POST['multilang_choice']))
        : (isset($_POST['aismart_lang_debug']) ? sanitize_text_field(wp_unslash($_POST['aismart_lang_debug'])) : '');
    $selected = aismart_normalize_provider_key($selected);
    $allowed = ['wpml', 'polylang', 'multilingualpress', 'translatepress', 'bogo', 'wpglobus', 'qtranslate', 'falang', 'none'];
    $detected = aismart_onboarding_detect_multilang_provider();
    $switch_result = [];
    if (in_array($selected, $allowed, true) && $selected !== 'none') {
        $switch_result = aismart_onboarding_apply_provider_group_switch($selected);
    }

    $provider = in_array($selected, $allowed, true) ? $selected : (string) ($detected['primary'] ?? 'none');

    $payload = [
        'workspace_id' => $workspace_id,
        'site_url' => home_url('/'),
        'site_domain' => wp_parse_url(home_url('/'), PHP_URL_HOST),
        'admin_email' => aismart_onboarding_current_admin_email(),
        'plugin_version' => '1.2.0',
        'multilang_provider' => $provider,
        'multilang_detected' => (array) ($detected['detected'] ?? []),
    ];

    $result = aismart_plugin_api_request('POST', 'api/plugin/v1/site/register', $payload, true);
    if (is_wp_error($result)) {
        wp_send_json_error(['message' => $result->get_error_message(), 'meta' => $result->get_error_data()], 500);
    }

    $state['site_register'] = $result;
    $state['site_registered_at'] = gmdate('c');
    $state['multilang_provider'] = $provider;
    $state['multilang_detected'] = (array) ($detected['detected'] ?? []);
    if (!empty($switch_result)) {
        $state['multilang_switch'] = $switch_result;
    }
    aismart_onboarding_state_set($state);

    wp_send_json_success([
        'message' => 'Site registered',
        'result' => $result,
        'state' => $state,
        'plugin_switch' => $switch_result,
    ]);
}

function aismart_token_usage_page() {
    // Keep Content Manager inside wp-admin without iframe or redirect.
    $ctx = aismart_resolve_workspace_context();
    $workspace_id = isset($ctx['workspace_id']) ? (int) $ctx['workspace_id'] : 0;
    $credit_runtime = aismart_compute_workspace_live_credit($workspace_id, (float) $ctx['credit_balance'], 10);
    $live_credit = isset($credit_runtime['live']) ? (float) $credit_runtime['live'] : (float) $ctx['credit_balance'];

    $manager_url = add_query_arg([
        'cb' => time(),
        'workspace' => $workspace_id,
        'credits_available' => $live_credit,
        'wp_api_units' => $live_credit,
        'wp_ajax_url' => admin_url('admin-ajax.php'),
        'source' => 'wordpress-plugin',
    ], plugins_url('aismart-core/public/admin/token/create', __FILE__));

    $remote = wp_remote_get($manager_url, [
        'timeout' => 45,
        'redirection' => 3,
        'sslverify' => true,
        'headers' => [
            'Accept' => 'text/html,application/xhtml+xml',
        ],
    ]);

    echo '<div class="wrap aismart-admin-wrap">';
    echo '<h1 style="margin:0 0 10px;">Content Manager</h1>';

    if (is_wp_error($remote)) {
        $cloud_manager_url = add_query_arg([
            'source' => 'wordpress-plugin',
            'workspace' => $workspace_id,
            'credits_available' => $live_credit,
        ], 'https://aismartcontent.co');
        echo '<div style="max-width:960px;background:#fff;border:1px solid #dcdcde;border-radius:8px;padding:18px 20px;">';
        echo '<p style="margin:0 0 12px;color:#b32d2e;"><strong>Could not load Content Manager inline.</strong></p>';
        echo '<p style="margin:0 0 12px;color:#1d2327;">' . esc_html($remote->get_error_message()) . '</p>';
        echo '<p style="margin:0;"><a class="button button-primary" target="_blank" rel="noopener noreferrer" href="' . esc_url($cloud_manager_url) . '">Open Content Manager In AISmart Cloud</a></p>';
        echo '</div>';
        echo '</div>';
        return;
    }

    $status_code = (int) wp_remote_retrieve_response_code($remote);
    $html = (string) wp_remote_retrieve_body($remote);
    if ($status_code < 200 || $status_code >= 300 || $html === '') {
        echo '<div style="max-width:960px;background:#fff;border:1px solid #dcdcde;border-radius:8px;padding:18px 20px;">';
        echo '<p style="margin:0 0 12px;color:#b32d2e;"><strong>Content Manager returned an unexpected response.</strong></p>';
        echo '<p style="margin:0;color:#1d2327;">HTTP status: ' . esc_html((string) $status_code) . '</p>';
        echo '</div>';
        echo '</div>';
        return;
    }

    $head_assets = '';
    $body_html = $html;

    if (preg_match('/<head[^>]*>(.*?)<\/head>/is', $html, $head_match)) {
        $head_assets = (string) $head_match[1];
        $head_assets = preg_replace('/<meta[^>]*>/i', '', $head_assets);
        $head_assets = preg_replace('/<title[^>]*>.*?<\/title>/is', '', $head_assets);
        $head_assets = is_string($head_assets) ? $head_assets : '';
    }

    if (preg_match('/<body[^>]*>(.*?)<\/body>/is', $html, $body_match)) {
        $body_html = (string) $body_match[1];
    }

    echo '<div class="aismart-content-manager-inline" style="background:#fff;border:1px solid #dcdcde;border-radius:8px;padding:0;overflow:hidden;">';
    if ($head_assets !== '') {
        echo $head_assets; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- trusted same-site plugin HTML assets
    }
    echo '<div style="padding:0 14px 14px;">';
    echo $body_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- trusted same-site plugin HTML
    echo '</div>';
    echo '</div>';
    echo '</div>';
}

function aismart_token_user_management_page() {
    $ctx = aismart_resolve_workspace_context();
    $workspace_id = isset($ctx['workspace_id']) ? (int) $ctx['workspace_id'] : 0;
    $workspace_label = isset($ctx['workspace_label']) ? sanitize_text_field((string) $ctx['workspace_label']) : '';
    $nonce = wp_create_nonce('aismart_user_management_nonce');
    $workspace_title = $workspace_label !== '' ? $workspace_label : ('Workspace #' . $workspace_id);
    $sync_auto_accept_default = (int) get_option('aismart_user_sync_auto_accept', 1) === 1;
    ?>
    <div class="wrap aismart-admin-wrap">
        <h1 style="margin:0 0 8px;">User Management</h1>
        <p style="margin:0 0 14px;color:#646970;">Sync WordPress users to AISmart workspace team members from this page.</p>

        <div style="background:#fff;border:1px solid #dcdcde;border-radius:6px;padding:12px 14px;margin-bottom:12px;display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;">
            <div>
                <div style="font-weight:600;">Workspace: <?php echo esc_html($workspace_title); ?></div>
                <div style="color:#646970;font-size:12px;">Workspace ID: <?php echo esc_html((string) $workspace_id); ?></div>
                <div style="margin-top:8px;display:flex;align-items:center;gap:8px;flex-wrap:wrap;">
                    <label style="display:flex;align-items:center;gap:6px;font-size:12px;color:#1d2327;cursor:pointer;">
                        <input type="checkbox" id="aismart-sync-auto-accept" <?php checked($sync_auto_accept_default); ?> />
                        <span><strong>Sync mode:</strong> Auto-accept</span>
                    </label>
                    <span id="aismart-sync-mode-label" style="font-size:12px;color:#646970;"></span>
                </div>
            </div>
            <div style="display:flex;gap:8px;flex-wrap:wrap;">
                <button type="button" class="button" id="aismart-sync-selected-users" disabled>Sync Selected</button>
                <button type="button" class="button button-primary" id="aismart-sync-all-users">Sync All Users</button>
                <button type="button" class="button" id="aismart-refresh-users">Refresh List</button>
            </div>
        </div>

        <div id="aismart-user-management-status" style="margin-bottom:10px;color:#1d2327;"></div>

        <div style="background:#fff;border:1px solid #dcdcde;border-radius:6px;overflow:auto;">
            <table class="widefat striped" id="aismart-user-management-table" style="margin:0;">
                <thead>
                    <tr>
                        <th style="width:45px;"><input type="checkbox" id="aismart-select-all-users" /></th>
                        <th style="width:70px;">WP ID</th>
                        <th>Name</th>
                        <th>Email</th>
                        <th style="width:140px;">Role</th>
                        <th style="width:160px;">Registered</th>
                        <th style="width:220px;">Last Sync</th>
                        <th style="width:110px;">Status</th>
                        <th style="width:130px;">Action</th>
                    </tr>
                </thead>
                <tbody id="aismart-user-management-body">
                    <tr><td colspan="9">Loading users...</td></tr>
                </tbody>
            </table>
        </div>

        <?php $user_management_inline_js = <<<'AISMART_USER_MANAGEMENT_JS'
            (function(){
            var ajaxUrl = __AISMART_AJAX_URL__;
            var nonce = __AISMART_USER_MGMT_NONCE__;
                var tbody = document.getElementById('aismart-user-management-body');
                var statusEl = document.getElementById('aismart-user-management-status');
                var syncAllBtn = document.getElementById('aismart-sync-all-users');
                var syncSelectedBtn = document.getElementById('aismart-sync-selected-users');
                var refreshBtn = document.getElementById('aismart-refresh-users');
                var selectAll = document.getElementById('aismart-select-all-users');
                var modeToggle = document.getElementById('aismart-sync-auto-accept');
                var modeLabel = document.getElementById('aismart-sync-mode-label');
                var selectedIds = new Set();

                function getAutoAccept(){
                    return (modeToggle && modeToggle.checked) ? 1 : 0;
                }

                function updateModeLabel(){
                    if(!modeLabel){ return; }
                    if(getAutoAccept() === 1){
                        modeLabel.textContent = 'Auto-accept ON: synced users become active team members.';
                    } else {
                        modeLabel.textContent = 'Invite-style ON: synced users stay waiting with pending invite.';
                    }
                }

                function esc(v){
                    return String(v || '')
                        .replace(/&/g, '&amp;')
                        .replace(/</g, '&lt;')
                        .replace(/>/g, '&gt;')
                        .replace(/"/g, '&quot;')
                        .replace(/'/g, '&#039;');
                }

                function setStatus(msg, type){
                    if(!statusEl) return;
                    statusEl.textContent = msg || '';
                    statusEl.style.color = (type === 'error') ? '#b32d2e' : ((type === 'success') ? '#1f7a1f' : '#1d2327');
                }

                function formBody(action, data){
                    var p = new URLSearchParams();
                    p.set('action', action);
                    p.set('nonce', nonce);
                    Object.keys(data || {}).forEach(function(k){ p.set(k, data[k]); });
                    return p.toString();
                }

                function post(action, data){
                    return fetch(ajaxUrl, {
                        method: 'POST',
                        credentials: 'same-origin',
                        headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
                        body: formBody(action, data || {})
                    }).then(function(r){
                        return r.text().then(function(txt){
                            try {
                                return JSON.parse(txt);
                            } catch (e) {
                                throw new Error('Invalid JSON response: ' + txt.slice(0, 180));
                            }
                        });
                    });
                }

                function updateBulkState(){
                    if(syncSelectedBtn){
                        syncSelectedBtn.disabled = selectedIds.size === 0;
                    }
                    if(selectAll){
                        var checks = tbody ? tbody.querySelectorAll('.aismart-user-check:not([disabled])') : [];
                        if(!checks.length){
                            selectAll.checked = false;
                            selectAll.indeterminate = false;
                            return;
                        }
                        var checked = 0;
                        checks.forEach(function(c){ if(c.checked) checked++; });
                        selectAll.checked = checked > 0 && checked === checks.length;
                        selectAll.indeterminate = checked > 0 && checked < checks.length;
                    }
                }

                function bindSelection(){
                    var checks = tbody ? tbody.querySelectorAll('.aismart-user-check') : [];
                    checks.forEach(function(box){
                        box.addEventListener('change', function(){
                            var id = parseInt(box.getAttribute('data-user-id') || '0', 10) || 0;
                            if(id <= 0){ return; }
                            if(box.checked){ selectedIds.add(id); } else { selectedIds.delete(id); }
                            updateBulkState();
                        });
                    });
                }

                function bindRowSync(){
                    var buttons = document.querySelectorAll('.aismart-sync-user');
                    buttons.forEach(function(btn){
                        btn.addEventListener('click', function(){
                            var userId = parseInt(btn.getAttribute('data-user-id') || '0', 10) || 0;
                            if(userId <= 0 || btn.disabled){ return; }
                            btn.disabled = true;
                            setStatus('Syncing user #' + userId + ' ...');
                            post('aismart_sync_workspace_user', {user_id: userId, auto_accept: getAutoAccept()})
                                .then(function(json){
                                    if(json && json.success){
                                        setStatus((json.data && json.data.message) ? json.data.message : 'User synced', 'success');
                                        loadUsers();
                                    } else {
                                        var msg = (json && json.data && json.data.message) ? json.data.message : 'Sync failed';
                                        setStatus(msg, 'error');
                                        btn.disabled = false;
                                    }
                                })
                                .catch(function(err){
                                    setStatus(err && err.message ? err.message : 'Sync request failed', 'error');
                                    btn.disabled = false;
                                });
                        });
                    });
                }

                function renderRows(users){
                    if(!tbody){ return; }
                    selectedIds = new Set();

                    if(!Array.isArray(users) || !users.length){
                        tbody.innerHTML = '<tr><td colspan="9">No users found.</td></tr>';
                        updateBulkState();
                        return;
                    }

                    tbody.innerHTML = users.map(function(u){
                        var role = (Array.isArray(u.roles) && u.roles.length) ? u.roles[0] : 'subscriber';
                        var isSynced = !!u.is_synced;
                        var lastSync = u.last_sync_at || '-';
                        var statusClass = isSynced ? 'color:#1f7a1f;' : 'color:#b32d2e;';
                        var statusText = isSynced ? 'Synced' : 'Not synced';
                        var btnDisabled = isSynced ? 'disabled' : '';
                        var btnLabel = isSynced ? 'Synced' : 'Sync';
                        var checkboxDisabled = isSynced ? 'disabled' : '';

                        return '' +
                            '<tr>' +
                            '<td><input type="checkbox" class="aismart-user-check" data-user-id="' + esc(u.id) + '" ' + checkboxDisabled + ' /></td>' +
                            '<td>' + esc(u.id) + '</td>' +
                            '<td>' + esc(u.name) + '</td>' +
                            '<td>' + esc(u.email) + '</td>' +
                            '<td>' + esc(role) + '</td>' +
                            '<td>' + esc(u.registered_at || '-') + '</td>' +
                            '<td>' + esc(lastSync) + '<br><span style="color:#646970;font-size:11px;">' + esc(u.sync_message || '') + '</span></td>' +
                            '<td><span style="' + statusClass + 'font-weight:600;">' + esc(statusText) + '</span></td>' +
                            '<td><button type="button" class="button button-small aismart-sync-user" data-user-id="' + esc(u.id) + '" ' + btnDisabled + '>' + esc(btnLabel) + '</button></td>' +
                            '</tr>';
                    }).join('');

                    bindSelection();
                    bindRowSync();
                    updateBulkState();
                }

                function loadUsers(){
                    setStatus('Loading users...');
                    post('aismart_get_user_management_data', {})
                        .then(function(json){
                            if(json && json.success && json.data){
                                renderRows(json.data.users || []);
                                setStatus('Loaded ' + ((json.data.users || []).length) + ' users.');
                            } else {
                                var msg = (json && json.data && json.data.message) ? json.data.message : 'Failed to load users';
                                setStatus(msg, 'error');
                                if(tbody){ tbody.innerHTML = '<tr><td colspan="9">' + esc(msg) + '</td></tr>'; }
                                updateBulkState();
                            }
                        })
                        .catch(function(err){
                            var msg = err && err.message ? err.message : 'Failed to load users';
                            setStatus(msg, 'error');
                            if(tbody){ tbody.innerHTML = '<tr><td colspan="9">' + esc(msg) + '</td></tr>'; }
                            updateBulkState();
                        });
                }

                if(syncAllBtn){
                    syncAllBtn.addEventListener('click', function(){
                        syncAllBtn.disabled = true;
                        setStatus('Syncing all users...');
                        post('aismart_sync_workspace_users', {auto_accept: getAutoAccept()})
                            .then(function(json){
                                if(json && json.success){
                                    var d = json.data || {};
                                    setStatus((d.message || 'Sync done') + ' (ok: ' + (d.success_count || 0) + ', failed: ' + (d.failed_count || 0) + ')', 'success');
                                    loadUsers();
                                } else {
                                    var msg = (json && json.data && json.data.message) ? json.data.message : 'Sync all failed';
                                    setStatus(msg, 'error');
                                }
                            })
                            .catch(function(err){
                                setStatus(err && err.message ? err.message : 'Sync all request failed', 'error');
                            })
                            .finally(function(){ syncAllBtn.disabled = false; });
                    });
                }

                if(syncSelectedBtn){
                    syncSelectedBtn.addEventListener('click', function(){
                        var ids = Array.from(selectedIds);
                        if(!ids.length){
                            setStatus('Select at least one user first.', 'error');
                            return;
                        }

                        syncSelectedBtn.disabled = true;
                        setStatus('Syncing selected users (' + ids.length + ')...');
                        post('aismart_sync_workspace_users', {user_ids: ids.join(','), auto_accept: getAutoAccept()})
                            .then(function(json){
                                if(json && json.success){
                                    var d = json.data || {};
                                    setStatus((d.message || 'Sync done') + ' (ok: ' + (d.success_count || 0) + ', failed: ' + (d.failed_count || 0) + ')', 'success');
                                    loadUsers();
                                } else {
                                    var msg = (json && json.data && json.data.message) ? json.data.message : 'Sync selected failed';
                                    setStatus(msg, 'error');
                                }
                            })
                            .catch(function(err){
                                setStatus(err && err.message ? err.message : 'Sync selected request failed', 'error');
                            })
                            .finally(function(){ syncSelectedBtn.disabled = false; updateBulkState(); });
                    });
                }

                if(selectAll){
                    selectAll.addEventListener('change', function(){
                        var checks = tbody ? tbody.querySelectorAll('.aismart-user-check:not([disabled])') : [];
                        selectedIds = new Set();
                        checks.forEach(function(box){
                            box.checked = !!selectAll.checked;
                            if(selectAll.checked){
                                var id = parseInt(box.getAttribute('data-user-id') || '0', 10) || 0;
                                if(id > 0){ selectedIds.add(id); }
                            }
                        });
                        updateBulkState();
                    });
                }

                if(refreshBtn){
                    refreshBtn.addEventListener('click', function(){ loadUsers(); });
                }

                if(modeToggle){
                    modeToggle.addEventListener('change', function(){
                        updateModeLabel();
                        setStatus(getAutoAccept() === 1 ? 'Sync mode: Auto-accept' : 'Sync mode: Invite-style (waiting/pending).');
                    });
                }

                updateModeLabel();
                loadUsers();
            })();
AISMART_USER_MANAGEMENT_JS;
        aismart_enqueue_inline_script(
            'aismart-user-management-inline',
            str_replace(
                ['__AISMART_AJAX_URL__', '__AISMART_USER_MGMT_NONCE__'],
                [wp_json_encode(admin_url('admin-ajax.php')), wp_json_encode($nonce)],
                $user_management_inline_js
            )
        ); ?>
    </div>
    <?php
}

add_action('wp_ajax_aismart_get_user_management_data', 'aismart_get_user_management_data');
function aismart_get_user_management_data() {
    if (!current_user_can('manage_options')) {
        wp_send_json_error(['message' => 'Unauthorized'], 403);
    }
    check_ajax_referer('aismart_user_management_nonce', 'nonce');

    $ctx = aismart_resolve_workspace_context();
    $active_workspace_id = (int) ($ctx['workspace_id'] ?? 0);
    $users = get_users([
        'orderby' => 'registered',
        'order' => 'DESC',
        'number' => 300,
    ]);

    $rows = [];
    if (is_array($users)) {
        foreach ($users as $user) {
            if (!($user instanceof WP_User)) {
                continue;
            }

            $last_sync_at = (string) get_user_meta($user->ID, '_aismart_user_sync_at', true);
            $sync_status = (string) get_user_meta($user->ID, '_aismart_user_sync_status', true);
            $sync_message = (string) get_user_meta($user->ID, '_aismart_user_sync_message', true);
            $sync_workspace_id = (int) get_user_meta($user->ID, '_aismart_user_sync_workspace_id', true);
            $is_synced = ($sync_status === 'success' && $active_workspace_id > 0 && $sync_workspace_id === $active_workspace_id);

            $rows[] = [
                'id' => (int) $user->ID,
                'name' => (string) $user->display_name,
                'email' => (string) $user->user_email,
                'roles' => array_values((array) $user->roles),
                'registered_at' => (string) $user->user_registered,
                'last_sync_at' => $last_sync_at,
                'sync_status' => $sync_status,
                'sync_message' => $sync_message,
                'sync_workspace_id' => $sync_workspace_id,
                'is_synced' => $is_synced ? 1 : 0,
            ];
        }
    }

    wp_send_json_success([
        'workspace_id' => (int) ($ctx['workspace_id'] ?? 0),
        'workspace_label' => (string) ($ctx['workspace_label'] ?? ''),
        'users' => $rows,
    ]);
}

function aismart_user_management_parse_auto_accept($request_key = 'auto_accept') {
    if (!isset($_POST[$request_key])) {
        return null;
    }

    $raw = wp_unslash($_POST[$request_key]);
    $bool = filter_var($raw, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
    if ($bool === null) {
        return 0;
    }

    return $bool ? 1 : 0;
}

function aismart_user_management_sync_single_user($user_id, $ctx = [], $auto_accept = null) {
    $user_id = (int) $user_id;
    if ($user_id <= 0) {
        return [
            'ok' => false,
            'message' => 'Invalid user id',
        ];
    }

    $user = get_user_by('id', $user_id);
    if (!($user instanceof WP_User)) {
        return [
            'ok' => false,
            'message' => 'User not found',
        ];
    }

    $workspace_id = isset($ctx['workspace_id']) ? (int) $ctx['workspace_id'] : 0;
    if ($workspace_id <= 0) {
        $resolved = aismart_resolve_workspace_context();
        $workspace_id = isset($resolved['workspace_id']) ? (int) $resolved['workspace_id'] : 0;
    }
    if ($workspace_id <= 0) {
        return [
            'ok' => false,
            'message' => 'Workspace is not connected',
        ];
    }

    if ($auto_accept === null) {
        $auto_accept = (int) get_option('aismart_user_sync_auto_accept', 1) === 1 ? 1 : 0;
    } else {
        $auto_accept = ((int) $auto_accept) === 1 ? 1 : 0;
    }

    $auto_accept = apply_filters('aismart_user_sync_auto_accept', $auto_accept === 1, $workspace_id, $user_id) ? 1 : 0;

    $payload = [
        'workspace_id' => $workspace_id,
        'site_url' => home_url('/'),
        'site_domain' => (string) wp_parse_url(home_url('/'), PHP_URL_HOST),
        'auto_accept' => $auto_accept,
        'wp_user' => [
            'id' => (int) $user->ID,
            'email' => (string) $user->user_email,
            'name' => (string) $user->display_name,
            'roles' => array_values((array) $user->roles),
            'registered_at' => (string) $user->user_registered,
        ],
    ];

    $endpoints = [
        'api/plugin/v1/workspace/team/sync-user',
        'api/plugin/v1/team/sync-user',
        'api/plugin/v1/workspace/users/sync-user',
        'api/plugin/v1/user-management/sync-user',
    ];

    $last_error = null;
    foreach ($endpoints as $endpoint) {
        $result = aismart_plugin_api_request('POST', $endpoint, $payload, true);
        if (!is_wp_error($result)) {
            $result_payload = isset($result['data']) && is_array($result['data']) ? $result['data'] : (is_array($result) ? $result : []);
            $succeeded = isset($result_payload['succeeded']) ? (int) $result_payload['succeeded'] : (isset($result_payload['success_count']) ? (int) $result_payload['success_count'] : 0);
            $failed = isset($result_payload['failed']) ? (int) $result_payload['failed'] : (isset($result_payload['failed_count']) ? (int) $result_payload['failed_count'] : 0);
            $ok_flag = array_key_exists('ok', $result_payload) ? (bool) $result_payload['ok'] : null;

            if ($ok_flag === false || ($failed > 0 && $succeeded <= 0)) {
                $message = isset($result_payload['message']) ? (string) $result_payload['message'] : 'Sync request failed on platform';
                $last_error = new WP_Error('sync_user_failed', $message, ['response' => $result]);
                continue;
            }

            $sync_message = isset($result_payload['message']) ? (string) $result_payload['message'] : ('Synced via ' . $endpoint);
            update_user_meta($user_id, '_aismart_user_sync_status', 'success');
            update_user_meta($user_id, '_aismart_user_sync_message', $sync_message);
            update_user_meta($user_id, '_aismart_user_sync_at', gmdate('c'));
            update_user_meta($user_id, '_aismart_user_sync_workspace_id', $workspace_id);

            return [
                'ok' => true,
                'message' => $sync_message,
                'endpoint' => $endpoint,
                'response' => $result,
            ];
        }
        $last_error = $result;
    }

    $error_message = 'User sync endpoint is not available yet.';
    if (is_wp_error($last_error)) {
        $error_message = (string) $last_error->get_error_message();
        $data = $last_error->get_error_data();
        if (is_array($data) && isset($data['status']) && (int) $data['status'] === 404) {
            $error_message = 'User sync endpoint not found on main platform (HTTP 404).';
        }
    }

    update_user_meta($user_id, '_aismart_user_sync_status', 'error');
    update_user_meta($user_id, '_aismart_user_sync_message', $error_message);
    update_user_meta($user_id, '_aismart_user_sync_at', gmdate('c'));
    update_user_meta($user_id, '_aismart_user_sync_workspace_id', $workspace_id);

    return [
        'ok' => false,
        'message' => $error_message,
    ];
}

add_action('wp_ajax_aismart_sync_workspace_user', 'aismart_sync_workspace_user');
function aismart_sync_workspace_user() {
    if (!current_user_can('manage_options')) {
        wp_send_json_error(['message' => 'Unauthorized'], 403);
    }
    check_ajax_referer('aismart_user_management_nonce', 'nonce');

    $user_id = isset($_POST['user_id']) ? (int) $_POST['user_id'] : 0;
    if ($user_id <= 0) {
        wp_send_json_error(['message' => 'Invalid user id'], 422);
    }

    $auto_accept = aismart_user_management_parse_auto_accept('auto_accept');
    if ($auto_accept !== null) {
        update_option('aismart_user_sync_auto_accept', $auto_accept ? 1 : 0, false);
    }

    $ctx = aismart_resolve_workspace_context();
    $result = aismart_user_management_sync_single_user($user_id, $ctx, $auto_accept);
    if (!empty($result['ok'])) {
        wp_send_json_success([
            'message' => 'User #' . $user_id . ' synced successfully.',
            'result' => $result,
        ]);
    }

    wp_send_json_error([
        'message' => isset($result['message']) ? (string) $result['message'] : 'Sync failed',
        'result' => $result,
    ], 500);
}

add_action('wp_ajax_aismart_sync_workspace_users', 'aismart_sync_workspace_users');
function aismart_sync_workspace_users() {
    if (!current_user_can('manage_options')) {
        wp_send_json_error(['message' => 'Unauthorized'], 403);
    }
    check_ajax_referer('aismart_user_management_nonce', 'nonce');

    $auto_accept = aismart_user_management_parse_auto_accept('auto_accept');
    if ($auto_accept !== null) {
        update_option('aismart_user_sync_auto_accept', $auto_accept ? 1 : 0, false);
    }

    $ctx = aismart_resolve_workspace_context();
    $users = [];
    $user_ids_raw = isset($_POST['user_ids']) ? (string) wp_unslash($_POST['user_ids']) : '';
    if ($user_ids_raw !== '') {
        $parts = preg_split('/[^0-9]+/', $user_ids_raw);
        $unique = [];
        if (is_array($parts)) {
            foreach ($parts as $part) {
                $id = (int) $part;
                if ($id > 0) {
                    $unique[$id] = $id;
                }
            }
        }
        $users = array_values($unique);
        if (empty($users)) {
            wp_send_json_error(['message' => 'No valid selected users'], 422);
        }
    } else {
        $users = get_users([
            'orderby' => 'registered',
            'order' => 'DESC',
            'number' => 300,
            'fields' => 'ID',
        ]);
    }

    $success_count = 0;
    $failed_count = 0;
    $errors = [];

    if (is_array($users)) {
        foreach ($users as $user_id_raw) {
            $user_id = (int) $user_id_raw;
            if ($user_id <= 0) {
                continue;
            }

            $result = aismart_user_management_sync_single_user($user_id, $ctx, $auto_accept);
            if (!empty($result['ok'])) {
                $success_count++;
            } else {
                $failed_count++;
                if (count($errors) < 10) {
                    $errors[] = [
                        'user_id' => $user_id,
                        'message' => isset($result['message']) ? (string) $result['message'] : 'Sync failed',
                    ];
                }
            }
        }
    }

    $message = 'Sync complete.';
    if ($failed_count > 0 && $success_count === 0) {
        $message = 'No users synced. Main platform endpoint may be missing.';
    } elseif ($failed_count > 0) {
        $message = 'Partial sync completed.';
    }

    wp_send_json_success([
        'message' => $message,
        'success_count' => $success_count,
        'failed_count' => $failed_count,
        'errors' => $errors,
    ]);
}

// AJAX: Get queued topics list
function aismart_topic_queue_normalize_title($title) {
    $title = sanitize_text_field((string) $title);
    $title = preg_replace('/\s+/u', ' ', $title);
    return trim((string) $title);
}

function aismart_topic_queue_get_items() {
    $items = get_option('aismart_topics_queue_v2', []);
    $legacy_titles = get_option('aismart_topics_cached', []);

    $normalized = [];
    $seen = [];

    if (is_array($items)) {
        foreach ($items as $item) {
            if (is_string($item)) {
                $title = aismart_topic_queue_normalize_title($item);
                if ($title === '') {
                    continue;
                }
                $key = function_exists('mb_strtolower') ? mb_strtolower($title) : strtolower($title);
                if (isset($seen[$key])) {
                    continue;
                }
                $seen[$key] = true;
                $normalized[] = [
                    'title' => $title,
                    'source' => 'legacy',
                    'provider' => '',
                    'written' => 0,
                    'written_post_id' => 0,
                    'created_at' => gmdate('c'),
                ];
                continue;
            }

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

            $title = aismart_topic_queue_normalize_title($item['title'] ?? '');
            if ($title === '') {
                continue;
            }
            $key = function_exists('mb_strtolower') ? mb_strtolower($title) : strtolower($title);
            if (isset($seen[$key])) {
                continue;
            }
            $seen[$key] = true;
            $normalized[] = [
                'title' => $title,
                'source' => sanitize_key((string) ($item['source'] ?? 'manual')),
                'provider' => aismart_normalize_provider_key($item['provider'] ?? ''),
                'written' => !empty($item['written']) ? 1 : 0,
                'written_post_id' => max(0, (int) ($item['written_post_id'] ?? 0)),
                'created_at' => sanitize_text_field((string) ($item['created_at'] ?? gmdate('c'))),
            ];
        }
    }

    if (is_array($legacy_titles)) {
        foreach ($legacy_titles as $legacy_title) {
            $title = aismart_topic_queue_normalize_title($legacy_title);
            if ($title === '') {
                continue;
            }
            $key = function_exists('mb_strtolower') ? mb_strtolower($title) : strtolower($title);
            if (isset($seen[$key])) {
                continue;
            }
            $seen[$key] = true;
            $normalized[] = [
                'title' => $title,
                'source' => 'legacy',
                'provider' => '',
                'written' => 0,
                'written_post_id' => 0,
                'created_at' => gmdate('c'),
            ];
        }
    }

    return $normalized;
}

function aismart_topic_queue_save_items($items) {
    if (!is_array($items)) {
        $items = [];
    }

    $clean = [];
    $titles = [];
    $seen = [];

    foreach ($items as $item) {
        if (!is_array($item)) {
            continue;
        }
        $title = aismart_topic_queue_normalize_title($item['title'] ?? '');
        if ($title === '') {
            continue;
        }
        $key = function_exists('mb_strtolower') ? mb_strtolower($title) : strtolower($title);
        if (isset($seen[$key])) {
            continue;
        }
        $seen[$key] = true;
        $clean[] = [
            'title' => $title,
            'source' => sanitize_key((string) ($item['source'] ?? 'manual')),
            'provider' => aismart_normalize_provider_key($item['provider'] ?? ''),
            'written' => !empty($item['written']) ? 1 : 0,
            'written_post_id' => max(0, (int) ($item['written_post_id'] ?? 0)),
            'created_at' => sanitize_text_field((string) ($item['created_at'] ?? gmdate('c'))),
        ];
        $titles[] = $title;
    }

    update_option('aismart_topics_queue_v2', array_values($clean), false);
    update_option('aismart_topics_cached', array_values($titles), false);
}

function aismart_topic_queue_add_titles($titles, $source = 'manual', $blocked_title_keys = []) {
    $source = sanitize_key((string) $source);
    if ($source === '') {
        $source = 'manual';
    }

    $items = aismart_topic_queue_get_items();
    $index = [];
    foreach ($items as $idx => $item) {
        $title_key = function_exists('mb_strtolower') ? mb_strtolower((string) $item['title']) : strtolower((string) $item['title']);
        $index[$title_key] = $idx;
    }

    $blocked = [];
    $blocked_token_sets = [];
    if (is_array($blocked_title_keys)) {
        foreach ($blocked_title_keys as $key => $value) {
            if (is_int($key)) {
                $normalized = aismart_topic_queue_title_key((string) $value);
                if ($normalized !== '') {
                    $blocked[$normalized] = true;
                    $token_set = aismart_topic_queue_title_tokens($normalized);
                    if (!empty($token_set)) {
                        $blocked_token_sets[] = $token_set;
                    }
                }
            } else {
                $normalized = aismart_topic_queue_title_key((string) $key);
                if ($normalized !== '') {
                    $blocked[$normalized] = true;
                    $token_set = aismart_topic_queue_title_tokens($normalized);
                    if (!empty($token_set)) {
                        $blocked_token_sets[] = $token_set;
                    }
                }
            }
        }
    }

    $added = [];
    foreach ((array) $titles as $raw_title) {
        $title = aismart_topic_queue_normalize_title($raw_title);
        if ($title === '') {
            continue;
        }
        $key = function_exists('mb_strtolower') ? mb_strtolower($title) : strtolower($title);
        if (isset($index[$key])) {
            continue;
        }

        $normalized_key = aismart_topic_queue_title_key($title);
        if ($normalized_key !== '' && isset($blocked[$normalized_key])) {
            continue;
        }

        $candidate_tokens = aismart_topic_queue_title_tokens($title);
        if (aismart_topic_queue_is_near_duplicate_tokens($candidate_tokens, $blocked_token_sets)) {
            continue;
        }

        $items[] = [
            'title' => $title,
            'source' => $source,
            'provider' => '',
            'written' => 0,
            'written_post_id' => 0,
            'created_at' => gmdate('c'),
        ];
        $index[$key] = count($items) - 1;
        if ($normalized_key !== '') {
            $blocked[$normalized_key] = true;
        }
        if (!empty($candidate_tokens)) {
            $blocked_token_sets[] = $candidate_tokens;
        }
        $added[] = $title;
    }

    aismart_topic_queue_save_items($items);
    return $added;
}

function aismart_topic_queue_mark_written($title, $post_id = 0, $provider = '') {
    $title = aismart_topic_queue_normalize_title($title);
    if ($title === '') {
        return;
    }

    $provider = aismart_normalize_provider_key($provider);

    $items = aismart_topic_queue_get_items();
    $target_key = function_exists('mb_strtolower') ? mb_strtolower($title) : strtolower($title);
    $changed = false;
    $matched_index = -1;
    foreach ($items as $index => &$item) {
        $item_key = function_exists('mb_strtolower')
            ? mb_strtolower((string) ($item['title'] ?? ''))
            : strtolower((string) ($item['title'] ?? ''));
        if ($item_key !== $target_key) {
            continue;
        }
        $item['written'] = 1;
        if ((int) $post_id > 0) {
            $item['written_post_id'] = (int) $post_id;
        }
        if ($provider !== '') {
            $item['provider'] = $provider;
        }
        $item['source'] = sanitize_key((string) ($item['source'] ?? 'manual'));
        if ($item['source'] === '') {
            $item['source'] = 'manual';
        }
        $item['updated_at'] = gmdate('c');
        $matched_index = (int) $index;
        $changed = true;
        break;
    }
    unset($item);

    if ($changed) {
        // Keep recently handled topics at the end so the UI reflects latest manual activity.
        if ($matched_index >= 0 && isset($items[$matched_index])) {
            $matched_item = $items[$matched_index];
            array_splice($items, $matched_index, 1);
            $items[] = $matched_item;
        }
        aismart_topic_queue_save_items($items);
    }
}

function aismart_topic_queue_mark_written_by_queue_id($queue_id, $post_id = 0, $provider = '') {
    $queue_id = (int) $queue_id;
    if ($queue_id <= 0) {
        return false;
    }

    $provider = aismart_normalize_provider_key($provider);
    $items = aismart_topic_queue_get_items();
    $index = $queue_id - 1;

    if (!isset($items[$index]) || !is_array($items[$index])) {
        return false;
    }

    $title = aismart_topic_queue_normalize_title($items[$index]['title'] ?? '');
    if ($title === '') {
        return false;
    }

    $items[$index]['title'] = $title;
    $items[$index]['written'] = 1;
    if ((int) $post_id > 0) {
        $items[$index]['written_post_id'] = (int) $post_id;
    }
    if ($provider !== '') {
        $items[$index]['provider'] = $provider;
    }
    $items[$index]['source'] = sanitize_key((string) ($items[$index]['source'] ?? 'manual'));
    if ($items[$index]['source'] === '') {
        $items[$index]['source'] = 'manual';
    }
    $items[$index]['updated_at'] = gmdate('c');

    // Keep recently handled topics at the end so the UI reflects latest manual activity.
    $matched_item = $items[$index];
    array_splice($items, $index, 1);
    $items[] = $matched_item;

    aismart_topic_queue_save_items($items);
    return true;
}

function aismart_topic_queue_title_key($title) {
    $title = aismart_topic_queue_normalize_title($title);
    if ($title === '') {
        return '';
    }

    if (function_exists('mb_strtolower')) {
        $title = mb_strtolower($title);
    } else {
        $title = strtolower($title);
    }

    $title = preg_replace('/[^\p{L}\p{N}]+/u', ' ', (string) $title);
    $title = preg_replace('/\s+/u', ' ', (string) $title);
    return trim((string) $title);
}

function aismart_topic_queue_title_tokens($title) {
    $title = aismart_topic_queue_title_key($title);
    if ($title === '') {
        return [];
    }

    $stop_words = [
        'a', 'an', 'the', 'and', 'or', 'to', 'of', 'in', 'on', 'for', 'with', 'without',
        'how', 'about', 'into', 'from', 'by', 'this', 'that', 'these', 'those', 'than',
    ];
    $stop_index = array_fill_keys($stop_words, true);

    $parts = preg_split('/\s+/u', $title);
    if (!is_array($parts)) {
        return [];
    }

    $tokens = [];
    foreach ($parts as $part) {
        $part = trim((string) $part);
        if ($part === '') {
            continue;
        }
        if (isset($stop_index[$part])) {
            continue;
        }
        if (preg_match('/^\d+$/', $part)) {
            continue;
        }
        if (function_exists('mb_strlen')) {
            if (mb_strlen($part) < 2) {
                continue;
            }
        } elseif (strlen($part) < 2) {
            continue;
        }
        $tokens[$part] = true;
    }

    $unique = array_keys($tokens);
    sort($unique, SORT_STRING);
    return $unique;
}

function aismart_topic_queue_is_near_duplicate_tokens($candidate_tokens, $known_token_sets) {
    if (!is_array($candidate_tokens) || count($candidate_tokens) < 2 || !is_array($known_token_sets)) {
        return false;
    }

    $candidate_map = array_fill_keys($candidate_tokens, true);
    $candidate_count = count($candidate_tokens);

    foreach ($known_token_sets as $known_tokens) {
        if (!is_array($known_tokens) || count($known_tokens) < 2) {
            continue;
        }

        $known_map = array_fill_keys($known_tokens, true);
        $intersection = count(array_intersect_key($candidate_map, $known_map));
        if ($intersection < 2) {
            continue;
        }

        $known_count = count($known_tokens);
        if ($intersection === min($candidate_count, $known_count)) {
            return true;
        }

        $union = $candidate_count + $known_count - $intersection;
        if ($union > 0 && ($intersection / $union) >= 0.72) {
            return true;
        }
    }

    return false;
}

function aismart_topic_queue_context_focuses($context) {
    $context = aismart_topic_queue_title_key($context);
    if ($context === '') {
        return ['business growth'];
    }

    $raw_parts = preg_split('/\s*(?:,|;|\||\/|&|\band\b|\bplus\b)\s*/u', $context);
    if (!is_array($raw_parts)) {
        $raw_parts = [$context];
    }

    if (count($raw_parts) === 1 && strpos($raw_parts[0], ' ') !== false) {
        $tokens = aismart_topic_queue_title_tokens($raw_parts[0]);
        if (count($tokens) >= 2 && count($tokens) <= 4) {
            $raw_parts = $tokens;
        }
    }

    $focuses = [];
    $seen = [];
    foreach ($raw_parts as $part) {
        $part_tokens = aismart_topic_queue_title_tokens((string) $part);
        if (empty($part_tokens)) {
            continue;
        }
        $phrase = implode(' ', array_slice($part_tokens, 0, 3));
        if ($phrase === '' || isset($seen[$phrase])) {
            continue;
        }
        $seen[$phrase] = true;
        $focuses[] = $phrase;
    }

    if (count($focuses) >= 2) {
        $combo = $focuses[0] . ' and ' . $focuses[1];
        if (!isset($seen[$combo])) {
            $focuses[] = $combo;
        }
    }

    if (empty($focuses)) {
        $focuses[] = $context;
    }

    return $focuses;
}

function aismart_topic_queue_collect_blocked_title_keys() {
    global $wpdb;

    $blocked = [];

    $items = aismart_topic_queue_get_items();
    if (is_array($items)) {
        foreach ($items as $item) {
            $key = aismart_topic_queue_title_key($item['title'] ?? '');
            if ($key !== '') {
                $blocked[$key] = true;
            }
        }
    }

    $rows = $wpdb->get_col(
        "SELECT post_title
         FROM {$wpdb->posts}
         WHERE post_type = 'post'
           AND post_status IN ('publish','draft','pending','future','private')
           AND post_title <> ''"
    );
    if (is_array($rows)) {
        foreach ($rows as $title) {
            $key = aismart_topic_queue_title_key($title);
            if ($key !== '') {
                $blocked[$key] = true;
            }
        }
    }

    return $blocked;
}

function aismart_topic_queue_generate_from_context($context, $count, $blocked_title_keys = []) {
    $context = aismart_topic_queue_normalize_title($context);
    $count = (int) $count;
    if ($count <= 0) {
        $count = 10;
    }

    $seed = $context !== '' ? $context : 'General Topic';
    $focuses = aismart_topic_queue_context_focuses($seed);
    $patterns = [
        'Beginner guide to %s',
        'Top 10 questions about %s',
        'Step-by-step guide for %s',
        'Common myths about %s and the facts',
        'Best practices for %s',
        'How to get started with %s',
        'Practical checklist for %s',
        'Frequently asked questions about %s',
        'Beginner mistakes to avoid in %s',
        'Real-world framework for %s',
        'Key trends shaping %s this year',
        'Weekly plan to improve %s',
        '30-day learning plan for %s',
        'How to explain %s in simple terms',
        'What to do first when working on %s',
        'Roadmap from basics to advanced %s',
    ];

    $suffixes = [
        '',
        ' for beginners',
        ' in 2026',
        ' with examples',
        ' step by step',
        ' for content planning',
    ];

    $blocked_phrase_pattern = '/\b(paid\s*ads?|local\s*business)\b/i';

    // Keep output deterministic per site/workspace while avoiding identical lists across installations.
    $ctx = aismart_resolve_workspace_context();
    $state = aismart_onboarding_state_get();
    $site_host = wp_parse_url(home_url('/'), PHP_URL_HOST);
    $workspace_id = (int) ($ctx['workspace_id'] ?? 0);
    $connected_user_id = isset($state['user_id']) ? (int) $state['user_id'] : 0;
    $salt = strtolower(trim((string) $site_host)) . '|' . $workspace_id . '|' . $connected_user_id . '|' . gmdate('oW');

    $stable_sort = static function ($a, $b) use ($salt) {
        $ha = md5($salt . '|' . (string) $a);
        $hb = md5($salt . '|' . (string) $b);
        return strcmp($ha, $hb);
    };
    usort($patterns, $stable_sort);
    usort($suffixes, $stable_sort);
    usort($focuses, $stable_sort);

    $topics = [];
    $seen = [];
    $seen_token_sets = [];

    if (is_array($blocked_title_keys)) {
        foreach ($blocked_title_keys as $key => $value) {
            if (is_int($key)) {
                $normalized = aismart_topic_queue_title_key((string) $value);
                if ($normalized !== '') {
                    $seen[$normalized] = true;
                    $token_set = aismart_topic_queue_title_tokens($normalized);
                    if (!empty($token_set)) {
                        $seen_token_sets[] = $token_set;
                    }
                }
            } else {
                $normalized = aismart_topic_queue_title_key((string) $key);
                if ($normalized !== '') {
                    $seen[$normalized] = true;
                    $token_set = aismart_topic_queue_title_tokens($normalized);
                    if (!empty($token_set)) {
                        $seen_token_sets[] = $token_set;
                    }
                }
            }
        }
    }

    $max_attempts = max(120, $count * 40);
    for ($attempt = 0; $attempt < $max_attempts && count($topics) < $count; $attempt++) {
        $pattern = $patterns[$attempt % count($patterns)];
        $suffix = $suffixes[(int) floor($attempt / count($patterns)) % count($suffixes)];
        $focus = $focuses[$attempt % count($focuses)];

        $base = ucfirst(sprintf($pattern, $focus));
        if ($suffix !== '') {
            $base = rtrim($base, '.') . $suffix;
        }

        $key = aismart_topic_queue_title_key($base);
        if ($key === '' || isset($seen[$key])) {
            continue;
        }
        if (preg_match($blocked_phrase_pattern, $base)) {
            continue;
        }

        $candidate_tokens = aismart_topic_queue_title_tokens($base);
        if (aismart_topic_queue_is_near_duplicate_tokens($candidate_tokens, $seen_token_sets)) {
            continue;
        }

        $seen[$key] = true;
        if (!empty($candidate_tokens)) {
            $seen_token_sets[] = $candidate_tokens;
        }
        $topics[] = $base;
    }

    $fallback_modifiers = [
        'for first-time readers',
        'for non-technical audiences',
        'with simple explanations',
        'with practical examples',
        'with implementation checklist',
        'with myth-vs-fact format',
        'with FAQ structure',
        'with common pitfalls and fixes',
        'with step-by-step actions',
        'with clear next steps',
    ];

    $fallback_attempt = 0;
    $fallback_max_attempts = max(240, $count * 60);
    while (count($topics) < $count && $fallback_attempt < $fallback_max_attempts) {
        $modifier = $fallback_modifiers[$fallback_attempt % count($fallback_modifiers)];
        $series = (int) floor($fallback_attempt / count($fallback_modifiers)) + 1;
        $focus = $focuses[$fallback_attempt % count($focuses)];
        $candidate = ucfirst('Practical guide: ' . $modifier . ' using ' . $focus . ' (part ' . $series . ')');
        $fallback_attempt++;

        $key = aismart_topic_queue_title_key($candidate);
        if ($key === '' || isset($seen[$key])) {
            continue;
        }
        if (preg_match($blocked_phrase_pattern, $candidate)) {
            continue;
        }

        $candidate_tokens = aismart_topic_queue_title_tokens($candidate);
        if (aismart_topic_queue_is_near_duplicate_tokens($candidate_tokens, $seen_token_sets)) {
            continue;
        }

        $seen[$key] = true;
        if (!empty($candidate_tokens)) {
            $seen_token_sets[] = $candidate_tokens;
        }
        $topics[] = $candidate;
    }

    if (count($topics) < $count) {
        $hard_guard = 0;
        while (count($topics) < $count && $hard_guard < 200) {
            $hard_guard++;
            $focus = $focuses[$hard_guard % count($focuses)];
            $candidate = ucfirst('Unique topic angle ' . $hard_guard . ': insights for ' . $focus);
            $key = aismart_topic_queue_title_key($candidate);
            if ($key === '' || isset($seen[$key])) {
                continue;
            }
            if (preg_match($blocked_phrase_pattern, $candidate)) {
                continue;
            }
            $seen[$key] = true;
            $topics[] = $candidate;
        }
    }

    return $topics;
}

function aismart_log_token_event($event, $amount, $meta = [], $message = '') {
    global $wpdb;

    $event = sanitize_key((string) $event);
    $amount = (float) $amount;
    if ($event === '' || $amount <= 0) {
        return false;
    }

    $ctx = aismart_resolve_workspace_context();
    $workspace_id = max(0, (int) ($ctx['workspace_id'] ?? 0));
    $state = aismart_onboarding_state_get();
    $user_id = isset($state['user_id']) ? (int) $state['user_id'] : 0;
    if ($user_id <= 0) {
        $user_id = (int) get_current_user_id();
    }
    if ($user_id <= 0) {
        $user_id = 1;
    }

    $payload = [
        'event' => $event,
        'amount' => $amount,
        'workspace_id' => $workspace_id,
        'user_id' => $user_id,
        'site_url' => rtrim((string) site_url('/'), '/') . '/',
        'site_domain' => (string) wp_parse_url(home_url('/'), PHP_URL_HOST),
        'meta' => is_array($meta) ? $meta : [],
        'logged_at' => gmdate('c'),
        'message' => $message !== '' ? sanitize_text_field($message) : ('Logged event: ' . $event),
    ];

    $cloud_ok = aismart_log_token_event_to_cloud($payload);
    $local_ok = aismart_log_token_event_to_local($payload, $event, $amount);

    return $cloud_ok || $local_ok;
}

function aismart_token_log_table_name() {
    $table = defined('AISMART_TOKEN_LOG_TABLE') ? (string) AISMART_TOKEN_LOG_TABLE : 'token_logs';
    $table = preg_replace('/[^a-zA-Z0-9_]/', '', $table);
    if ($table === '') {
        $table = 'token_logs';
    }

    return $table;
}

function aismart_log_token_event_to_local($payload, $event, $amount) {
    global $wpdb;

    $table = aismart_token_log_table_name();
    $charset_collate = $wpdb->get_charset_collate();
    $created = $wpdb->query(
        "CREATE TABLE IF NOT EXISTS {$table} (
            id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
            workspace_id BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
            user_id BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
            amount DECIMAL(18,4) NOT NULL DEFAULT 0,
            case_log LONGTEXT NULL,
            type VARCHAR(120) NOT NULL DEFAULT '',
            platform VARCHAR(40) NOT NULL DEFAULT 'wordpress',
            created_at DATETIME NULL,
            updated_at DATETIME NULL,
            PRIMARY KEY (id),
            KEY idx_workspace_id (workspace_id),
            KEY idx_user_id (user_id),
            KEY idx_type (type),
            KEY idx_created_at (created_at)
        ) {$charset_collate}"
    );
    if ($created === false) {
        return false;
    }

    $inserted = $wpdb->insert(
        $table,
        [
            'workspace_id' => (int) ($payload['workspace_id'] ?? 0),
            'user_id' => (int) ($payload['user_id'] ?? 0),
            'amount' => $amount,
            'case_log' => wp_json_encode($payload),
            'type' => $event,
            'platform' => 'wordpress',
            'created_at' => current_time('mysql', true),
            'updated_at' => current_time('mysql', true),
        ],
        ['%d', '%d', '%f', '%s', '%s', '%s', '%s', '%s']
    );

    return $inserted !== false;
}

function aismart_usage_log_idempotency_key($request) {
    $request = is_array($request) ? $request : [];

    $fingerprint = [
        'event' => (string) ($request['event'] ?? $request['type'] ?? ''),
        'workspace_id' => (int) ($request['workspace_id'] ?? 0),
        'user_id' => (int) ($request['user_id'] ?? 0),
        'site_domain' => strtolower(trim((string) ($request['site_domain'] ?? ''))),
        'amount' => (float) ($request['amount'] ?? 0),
        'logged_at' => (string) ($request['logged_at'] ?? ''),
    ];

    return 'wp-usage-' . md5(wp_json_encode($fingerprint));
}

function aismart_log_token_event_to_cloud($payload) {
    $payload = is_array($payload) ? $payload : [];
    if (empty($payload['event']) || empty($payload['amount'])) {
        return false;
    }

    $state = aismart_onboarding_state_get();
    if (empty($state['access_token'])) {
        return false;
    }

    $request = [
        'event' => (string) $payload['event'],
        'type' => (string) $payload['event'],
        'amount' => (float) $payload['amount'],
        'workspace_id' => (int) ($payload['workspace_id'] ?? 0),
        'user_id' => (int) ($payload['user_id'] ?? 0),
        'site_url' => (string) ($payload['site_url'] ?? ''),
        'site_domain' => strtolower(trim((string) ($payload['site_domain'] ?? ''))),
        'meta' => isset($payload['meta']) && is_array($payload['meta']) ? $payload['meta'] : [],
        'message' => (string) ($payload['message'] ?? ''),
        'logged_at' => (string) ($payload['logged_at'] ?? gmdate('c')),
        'source' => 'wordpress_plugin',
    ];

    $idempotency_key = aismart_usage_log_idempotency_key($request);
    $result = aismart_plugin_api_request('POST', 'api/plugin/v1/usage/log', $request, true, $idempotency_key);

    return !is_wp_error($result) && is_array($result);
}

add_action('wp_ajax_aismart_queue_topics', 'aismart_queue_topics');
function aismart_queue_topics() {
    if (!current_user_can('manage_options')) {
        wp_send_json_error(['message' => 'Unauthorized'], 403);
    }
    if (!aismart_require_positive_credit_or_json_error('Topic generation')) {
        return;
    }

    $mode = isset($_POST['mode']) ? sanitize_key(wp_unslash($_POST['mode'])) : 'manual';
    $mode = in_array($mode, ['manual', 'ai'], true) ? $mode : 'manual';

    if ($mode === 'manual') {
        $raw_topics = isset($_POST['manual_topics']) ? (string) wp_unslash($_POST['manual_topics']) : '';
        $lines = preg_split('/\r\n|\r|\n/u', $raw_topics);
        $titles = [];
        if (is_array($lines)) {
            foreach ($lines as $line) {
                $line = aismart_topic_queue_normalize_title($line);
                if ($line !== '') {
                    $titles[] = $line;
                }
            }
        }
    } else {
        $context = isset($_POST['topic_context']) ? sanitize_text_field(wp_unslash($_POST['topic_context'])) : '';
        $count = isset($_POST['topic_count']) ? (int) $_POST['topic_count'] : 10;
        if (!in_array($count, [10, 25, 50, 100], true)) {
            $count = 10;
        }

        $blocked_title_keys = aismart_topic_queue_collect_blocked_title_keys();
        $titles = aismart_topic_queue_generate_from_context($context, $count, $blocked_title_keys);
    }

    if (empty($titles)) {
        wp_send_json_error(['message' => 'No valid topics provided'], 422);
    }

    $added = aismart_topic_queue_add_titles(
        $titles,
        $mode === 'ai' ? 'ai' : 'manual',
        $mode === 'ai' ? ($blocked_title_keys ?? []) : []
    );
    $added_count = count($added);

    if ($added_count > 0) {
        aismart_log_token_event(
            'topic_queue_add',
            (float) $added_count,
            [
                'mode' => $mode,
                'added' => $added_count,
                'sample' => array_slice(array_values($added), 0, 10),
            ],
            'Added topics into queue'
        );
    }

    $all_items = aismart_topic_queue_get_items();

    wp_send_json_success([
        'added_count' => $added_count,
        'added_topics' => $added,
        'total_count' => count($all_items),
    ]);
}

function aismart_normalize_provider_key($provider) {
    $provider = sanitize_key((string) $provider);
    if ($provider === 'qtranslate-xt') {
        return 'qtranslate';
    }
    return $provider;
}

function aismart_provider_label($provider) {
    $provider = aismart_normalize_provider_key($provider);
    $labels = [
        'wpml' => 'WPML',
        'polylang' => 'Polylang',
        'translatepress' => 'TranslatePress',
        'multilingualpress' => 'MultilingualPress',
        'falang' => 'Falang',
        'qtranslate' => 'qTranslate',
        'sublanguage' => 'Sublanguage',
        'wpglobus' => 'WPGlobus',
        'bogo' => 'Bogo',
        'legacy-falang-polylang' => 'Legacy (Falang/Polylang)',
    ];

    return isset($labels[$provider]) ? $labels[$provider] : '';
}

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

    $polylang_active = false;
    $conveythis_active = false;

    if (function_exists('is_plugin_active')) {
        $polylang_active = is_plugin_active('polylang/polylang.php')
            || (function_exists('is_plugin_active_for_network') && is_plugin_active_for_network('polylang/polylang.php'));
        $conveythis_active = is_plugin_active('conveythis-translate/conveythis-translate.php')
            || (function_exists('is_plugin_active_for_network') && is_plugin_active_for_network('conveythis-translate/conveythis-translate.php'));
    }

    if (!$polylang_active && function_exists('pll_current_language')) {
        $polylang_active = true;
    }

    if (!$conveythis_active && class_exists('ConveyThis', false)) {
        $conveythis_active = true;
    }

    return $polylang_active && $conveythis_active;
}

function aismart_resolve_selected_provider_key() {
    $state = aismart_onboarding_state_get();
    $saved = aismart_normalize_provider_key($state['multilang_provider'] ?? '');
    $allowed = [
        'wpml',
        'polylang',
        'translatepress',
        'multilingualpress',
        'falang',
        'qtranslate',
        'wpglobus',
        'bogo',
    ];

    if ($saved !== '' && in_array($saved, $allowed, true)) {
        return $saved;
    }

    $detected = aismart_onboarding_detect_multilang_provider();
    $primary = aismart_normalize_provider_key($detected['primary'] ?? '');
    if ($primary !== '' && in_array($primary, $allowed, true)) {
        return $primary;
    }

    return '';
}

function aismart_supported_provider_labels() {
    return [
        'wpml' => 'WPML',
        'polylang' => 'Polylang',
        'translatepress' => 'TranslatePress',
        'multilingualpress' => 'MultilingualPress',
        'falang' => 'Falang',
        'qtranslate' => 'qTranslate',
        'wpglobus' => 'WPGlobus',
        'bogo' => 'Bogo',
    ];
}

function aismart_get_supported_provider_options() {
    $labels = aismart_supported_provider_labels();
    $items = [];
    foreach ($labels as $code => $name) {
        $items[] = [
            'code' => (string) $code,
            'name' => (string) $name,
        ];
    }
    return $items;
}

function aismart_detect_active_provider_key() {
    $labels = aismart_supported_provider_labels();

    $multilang = aismart_onboarding_detect_multilang_provider();
    $primary = aismart_normalize_provider_key($multilang['primary'] ?? '');
    if ($primary !== '' && isset($labels[$primary])) {
        return $primary;
    }

    $selected = aismart_resolve_selected_provider_key();
    if ($selected !== '' && isset($labels[$selected])) {
        return $selected;
    }

    return '';
}

function aismart_guess_previous_provider_key($active_provider = '') {
    global $wpdb;

    $active_provider = aismart_normalize_provider_key($active_provider);
    $labels = aismart_supported_provider_labels();

    $saved = aismart_normalize_provider_key(get_option('aismart_migration_last_source_provider', ''));
    if ($saved !== '' && $saved !== $active_provider && isset($labels[$saved])) {
        return $saved;
    }

    $counts = [];

    $items = aismart_topic_queue_get_items();
    if (is_array($items)) {
        foreach ($items as $item) {
            $provider = aismart_normalize_provider_key($item['provider'] ?? '');
            if ($provider === '' || $provider === $active_provider || !isset($labels[$provider])) {
                continue;
            }
            $counts[$provider] = (int) ($counts[$provider] ?? 0) + 1;
        }
    }

    $post_ids = $wpdb->get_col(
        "SELECT ID
         FROM {$wpdb->posts}
         WHERE post_type='post'
           AND post_status IN ('publish','draft','pending','future','private')
         ORDER BY ID DESC
         LIMIT 250"
    );

    if (is_array($post_ids)) {
        foreach ($post_ids as $id_raw) {
            $post_id = (int) $id_raw;
            if ($post_id <= 0) {
                continue;
            }
            $provider = aismart_detect_provider_from_post($post_id);
            $provider = aismart_normalize_provider_key($provider);
            if ($provider === '' || $provider === $active_provider || !isset($labels[$provider])) {
                continue;
            }
            $counts[$provider] = (int) ($counts[$provider] ?? 0) + 1;
        }
    }

    if (empty($counts)) {
        return '';
    }

    arsort($counts);
    $keys = array_keys($counts);
    return isset($keys[0]) ? (string) $keys[0] : '';
}

function aismart_detect_provider_from_post($post_id) {
    global $wpdb;

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

    $saved = aismart_normalize_provider_key(get_post_meta($post_id, '_aismart_created_provider', true));
    if ($saved !== '') {
        return $saved;
    }

    $saved_last = aismart_normalize_provider_key(get_post_meta($post_id, '_aismart_last_multilang_provider', true));
    if ($saved_last !== '') {
        return $saved_last;
    }

    $postmeta_table = $wpdb->postmeta;
    $has_falang = (int) $wpdb->get_var(
        $wpdb->prepare(
            "SELECT COUNT(meta_id) FROM {$postmeta_table} WHERE post_id = %d AND meta_key LIKE %s",
            $post_id,
            '_aismart_falang_translation_%'
        )
    );
    if ($has_falang > 0) {
        return 'falang';
    }

    $has_trp = (int) $wpdb->get_var(
        $wpdb->prepare(
            "SELECT COUNT(meta_id) FROM {$postmeta_table} WHERE post_id = %d AND (meta_key = %s OR meta_key LIKE %s)",
            $post_id,
            '_aismart_trp_translations',
            '_aismart_trp_translation_%'
        )
    );
    if ($has_trp > 0) {
        return 'translatepress';
    }

    $has_sublanguage = (int) $wpdb->get_var(
        $wpdb->prepare(
            "SELECT COUNT(meta_id) FROM {$postmeta_table} WHERE post_id = %d AND meta_key LIKE %s",
            $post_id,
            '_aismart_sublanguage_translation_%'
        )
    );
    if ($has_sublanguage > 0) {
        return 'sublanguage';
    }

    $has_mlp = (int) $wpdb->get_var(
        $wpdb->prepare(
            "SELECT COUNT(meta_id) FROM {$postmeta_table} WHERE post_id = %d AND meta_key LIKE %s",
            $post_id,
            '_aismart_mlp_translation_blog_%'
        )
    );
    if ($has_mlp > 0) {
        return 'multilingualpress';
    }

    if (function_exists('pll_get_post_translations')) {
        $map = pll_get_post_translations($post_id);
        if (is_array($map) && count($map) > 1) {
            return 'polylang';
        }
    }

    $content = (string) get_post_field('post_content', $post_id);
    if ($content !== '') {
        if (preg_match('/\[:[a-z]{2}(?:[-_][a-zA-Z]{2,5})?\]/u', $content)) {
            return 'qtranslate';
        }
        if (preg_match('/<!--:[a-z]{2}(?:[-_][a-zA-Z]{2,5})?-->/u', $content)) {
            return 'wpglobus';
        }
    }

    $children_count = (int) $wpdb->get_var(
        $wpdb->prepare(
            "SELECT COUNT(pm.meta_id)
             FROM {$wpdb->postmeta} pm
             INNER JOIN {$wpdb->posts} p ON p.ID = pm.post_id
             WHERE pm.meta_key = %s
               AND pm.meta_value = %d
               AND p.post_type = 'post'
               AND p.post_status IN ('publish','draft','pending','future','private')",
            '_aismart_source_post_id',
            $post_id
        )
    );
    if ($children_count > 0) {
        return 'legacy-falang-polylang';
    }

    return '';
}

add_action('wp_ajax_aismart_get_topics', 'aismart_get_topics');
function aismart_get_topics() {
    if (!current_user_can('manage_options')) {
        wp_send_json_error(['message' => 'Unauthorized'], 403);
    }

    $items = aismart_topic_queue_get_items();
    if (!is_array($items)) {
        $items = [];
    }

    global $wpdb;
    $posts_table = $wpdb->posts;

    $is_non_base_language_post = static function ($post_id) {
        $post_id = (int) $post_id;
        if ($post_id <= 0) {
            return false;
        }

        if (function_exists('aismart_is_non_source_translation_post') && aismart_is_non_source_translation_post($post_id)) {
            return true;
        }

        if ((int) get_post_meta($post_id, '_aismart_source_post_id', true) > 0) {
            return true;
        }

        return false;
    };

    $payload = [];
    $payload_title_index = [];
    $changed = false;
    foreach ($items as $index => $item) {
        $topic = aismart_topic_queue_normalize_title($item['title'] ?? '');
        if ($topic === '') {
            continue;
        }

        $topic_key = function_exists('mb_strtolower') ? mb_strtolower($topic) : strtolower($topic);
        $payload_title_index[$topic_key] = true;

        $resume_post_id = (int) ($item['written_post_id'] ?? 0);
        $is_written = !empty($item['written']);

        if ($resume_post_id <= 0 || !get_post($resume_post_id)) {
            $post_rows = $wpdb->get_results(
                $wpdb->prepare(
                    "SELECT ID, post_status
                     FROM {$posts_table}
                     WHERE post_type = 'post'
                       AND post_status IN ('publish','draft','pending','future','private')
                       AND post_title = %s
                     ORDER BY ID DESC
                     LIMIT 12",
                    $topic
                )
            );

            if (is_array($post_rows) && !empty($post_rows)) {
                foreach ($post_rows as $post_row) {
                    $candidate_id = isset($post_row->ID) ? (int) $post_row->ID : 0;
                    if ($candidate_id <= 0) {
                        continue;
                    }
                    if ($is_non_base_language_post($candidate_id)) {
                        continue;
                    }

                    $resume_post_id = $candidate_id;
                    if ((string) ($post_row->post_status ?? '') === 'publish') {
                        $is_written = true;
                    }
                    break;
                }
            }
        }

        if ((int) ($item['written_post_id'] ?? 0) !== $resume_post_id || (int) (!empty($item['written'])) !== (int) ($is_written ? 1 : 0)) {
            $items[$index]['written_post_id'] = $resume_post_id;
            $items[$index]['written'] = $is_written ? 1 : 0;
            $changed = true;
        }

        // Keep Current Topic List source-only: remove translated child posts.
        if ($resume_post_id > 0) {
            $source_post_id = (int) get_post_meta($resume_post_id, '_aismart_source_post_id', true);
            if ($source_post_id > 0) {
                unset($items[$index]);
                $changed = true;
                continue;
            }

            // Safety for legacy rows where _aismart_source_post_id is missing:
            // keep only base-language source posts in Current Topic List.
            if ($is_non_base_language_post($resume_post_id)) {
                unset($items[$index]);
                $changed = true;
                continue;
            }
        }

        $provider_key = '';
        if ($resume_post_id > 0) {
            $provider_key = aismart_detect_provider_from_post($resume_post_id);
        }
        if ($provider_key === '') {
            $provider_key = aismart_normalize_provider_key($item['provider'] ?? '');
        }
        if ($provider_key === '' && $resume_post_id > 0) {
            $provider_key = 'legacy-falang-polylang';
        }
        $provider_label = aismart_provider_label($provider_key);

        $payload[] = [
            'queue_id' => count($payload) + 1,
            'title' => $topic,
            'exists' => $is_written ? 1 : 0,
            'is_written' => $is_written ? 1 : 0,
            'draft_post_id' => 0,
            'resume_post_id' => $resume_post_id > 0 ? $resume_post_id : 0,
            'source' => sanitize_key((string) ($item['source'] ?? 'manual')),
            'provider_key' => $provider_key,
            'provider_label' => $provider_label,
        ];
    }

    // Safety net: if a generated post title is missing from queue storage,
    // append it so manual generation always appears in Current Topic List.
    $generated_rows = $wpdb->get_results(
        "SELECT p.ID, p.post_title, p.post_status
         FROM {$posts_table} p
         INNER JOIN {$wpdb->postmeta} pm
             ON pm.post_id = p.ID
            AND pm.meta_key = '_aismart_generated_post'
            AND pm.meta_value = '1'
                 LEFT JOIN {$wpdb->postmeta} srcpm
                         ON srcpm.post_id = p.ID
                        AND srcpm.meta_key = '_aismart_source_post_id'
         WHERE p.post_type = 'post'
           AND p.post_status IN ('publish','draft','pending','future','private')
                     AND (srcpm.meta_value IS NULL OR srcpm.meta_value = '' OR srcpm.meta_value = '0')
         ORDER BY p.ID DESC
         LIMIT 50"
    );

    if (is_array($generated_rows)) {
        foreach ($generated_rows as $row) {
            $topic = aismart_topic_queue_normalize_title($row->post_title ?? '');
            if ($topic === '') {
                continue;
            }
            $topic_key = function_exists('mb_strtolower') ? mb_strtolower($topic) : strtolower($topic);
            if (isset($payload_title_index[$topic_key])) {
                continue;
            }

            $resume_post_id = (int) ($row->ID ?? 0);
            if ($resume_post_id <= 0) {
                continue;
            }

            // Backfill only source/default-language items; skip translated children.
            if ($is_non_base_language_post($resume_post_id)) {
                continue;
            }

            $provider_key = aismart_detect_provider_from_post($resume_post_id);
            if ($provider_key === '') {
                $provider_key = 'legacy-falang-polylang';
            }

            $items[] = [
                'title' => $topic,
                'source' => 'generated',
                'provider' => $provider_key,
                'written' => ((string) ($row->post_status ?? '') === 'publish') ? 1 : 0,
                'written_post_id' => $resume_post_id,
                'created_at' => gmdate('c'),
            ];
            $changed = true;

            $payload[] = [
                'queue_id' => count($items),
                'title' => $topic,
                'exists' => ((string) ($row->post_status ?? '') === 'publish') ? 1 : 0,
                'is_written' => ((string) ($row->post_status ?? '') === 'publish') ? 1 : 0,
                'draft_post_id' => 0,
                'resume_post_id' => $resume_post_id,
                'source' => 'generated',
                'provider_key' => $provider_key,
                'provider_label' => aismart_provider_label($provider_key),
            ];

            $payload_title_index[$topic_key] = true;
        }
    }

    if ($changed) {
        aismart_topic_queue_save_items($items);
    }

    wp_send_json_success(['topics' => $payload]);
}

// AJAX: Create blog draft via NVL API
function aismart_posts_api_candidates() {
    $configured_base = untrailingslashit((string) aismart_plugin_get_api_base());
    $candidates = [];

    if ($configured_base !== '') {
        $candidates[] = $configured_base . '/api/v2/aismart/posts';
    }

    $candidates[] = 'https://aismartcontent.co/api/v2/aismart/posts';

    $normalized = [];
    foreach ($candidates as $url) {
        $url = trim((string) $url);
        if ($url === '' || !filter_var($url, FILTER_VALIDATE_URL)) {
            continue;
        }
        if (!in_array($url, $normalized, true)) {
            $normalized[] = $url;
        }
    }

    return $normalized;
}

function aismart_request_posts_api(array $payload, $timeout = 60) {
    $timeout = max(10, (int) $timeout);
    $endpoints = aismart_posts_api_candidates();
    $state = aismart_onboarding_state_get();
    $ctx = aismart_resolve_workspace_context();

    $workspace_id = (int) ($ctx['workspace_id'] ?? 0);
    $connected_user_id = isset($state['user_id']) ? (int) $state['user_id'] : 0;
    $access_token = isset($state['access_token']) ? trim((string) $state['access_token']) : '';

    if ($workspace_id > 0 && empty($payload['workspace_id'])) {
        $payload['workspace_id'] = $workspace_id;
    }
    if ($connected_user_id > 0 && empty($payload['user_id'])) {
        $payload['user_id'] = $connected_user_id;
    }
    if (empty($payload['site_url'])) {
        $payload['site_url'] = home_url('/');
    }
    if (empty($payload['site_domain'])) {
        $payload['site_domain'] = (string) wp_parse_url(home_url('/'), PHP_URL_HOST);
    }

    $first_transport_error = '';
    $last_transport_error = '';
    $best_transport_error = '';
    $last_http_error = '';
    $last_status = 0;
    $last_body = '';
    $first_http_error = '';
    $first_http_status = 0;
    $first_http_body = '';
    $attempted = [];

    foreach ($endpoints as $endpoint) {
        $attempted[] = $endpoint;

        $request_timeout = $timeout;
        if (strpos($endpoint, AISMART_API_SLOW_HOST) !== false) {
            // Allow a larger timeout window for image-only generation so it can return a usable image.
            $is_image_only_request = !empty($payload['image_only']) && (int) $payload['image_only'] === 1;
            if ($is_image_only_request) {
                $request_timeout = min($timeout, max(20, (int) ceil($timeout * 0.5)));
            } else {
                // Keep non-image requests conservative on this host.
                $request_timeout = min($timeout, AISMART_API_FALLBACK_HOST_TIMEOUT);
            }
        }

        $request_args = [
            'timeout' => $request_timeout,
            'body' => $payload,
            'headers' => [
                'Accept' => 'application/json',
            ],
        ];
        if ($access_token !== '') {
            $request_args['headers']['Authorization'] = 'Bearer ' . $access_token;
        }

        $response = wp_remote_post($endpoint, $request_args);

        if (is_wp_error($response)) {
            $transport_error = (string) $response->get_error_message();
            if ($first_transport_error === '') {
                $first_transport_error = $transport_error;
            }
            $last_transport_error = $transport_error;
            $is_timeout_error = stripos($transport_error, 'cURL error 28') !== false
                || stripos($transport_error, 'operation timed out') !== false
                || stripos($transport_error, 'timed out') !== false;
            if ($best_transport_error === '') {
                $best_transport_error = $transport_error;
            } else {
                $best_is_timeout = stripos($best_transport_error, 'cURL error 28') !== false
                    || stripos($best_transport_error, 'operation timed out') !== false
                    || stripos($best_transport_error, 'timed out') !== false;
                if ($best_is_timeout && !$is_timeout_error) {
                    $best_transport_error = $transport_error;
                }
            }
            error_log('AISmart API transport error at ' . $endpoint . ': ' . $last_transport_error);
            continue;
        }

        $status = (int) wp_remote_retrieve_response_code($response);
        $body = (string) wp_remote_retrieve_body($response);
        $json = json_decode($body, true);

        $embedded_status = 0;
        if (is_array($json) && isset($json['status']) && is_numeric($json['status'])) {
            $embedded_status = (int) $json['status'];
        }
        $embedded_code = 0;
        if (is_array($json) && isset($json['code']) && is_numeric($json['code'])) {
            $embedded_code = (int) $json['code'];
        }

        // Some upstream responses wrap rate-limit in JSON with HTTP 500.
        $is_rate_limited = $status === 429
            || $embedded_status === 429
            || $embedded_code === 429
            || (is_string($body) && stripos($body, 'rate limit') !== false && $status >= 400);

        if ($is_rate_limited) {
            $msg = 'AI generation rate limit reached. Please try again shortly.';
            if (is_array($json) && !empty($json['message'])) {
                $msg = (string) $json['message'];
            } elseif (is_array($json) && !empty($json['error'])) {
                $msg = (string) $json['error'];
            }
            return [
                'ok' => false,
                'status' => 429,
                'message' => $msg,
                'endpoint' => $endpoint,
                'body' => $body,
                'attempted' => $attempted,
            ];
        }

        if ($status >= 200 && $status < 300 && is_array($json)) {
            return [
                'ok' => true,
                'status' => $status,
                'data' => $json,
                'endpoint' => $endpoint,
            ];
        }

        $last_status = $status;
        $last_body = $body;
        $last_http_error = 'HTTP ' . $status;
        if (is_array($json) && !empty($json['message'])) {
            $last_http_error .= ': ' . sanitize_text_field((string) $json['message']);
        }
        if ($first_http_error === '') {
            $first_http_error = $last_http_error;
            $first_http_status = $status;
            $first_http_body = $body;
        }
        error_log('AISmart API HTTP error at ' . $endpoint . ': status=' . $status . ' body=' . $body);
    }

    $message = $first_http_error !== ''
        ? $first_http_error
        : ($best_transport_error !== ''
            ? $best_transport_error
            : ($first_transport_error !== ''
                ? $first_transport_error
                : ($last_transport_error !== ''
                    ? $last_transport_error
                    : ($last_http_error !== '' ? $last_http_error : 'Upstream API request failed'))));

    $status = $first_http_status > 0
        ? $first_http_status
        : $last_status;

    $body = $first_http_body !== ''
        ? $first_http_body
        : $last_body;

    return [
        'ok' => false,
        'status' => $status,
        'message' => $message,
        'body' => $body,
        'attempted' => $attempted,
    ];
}

function aismart_build_local_fallback_post_data($topic, $manual_content = '') {
    $topic = aismart_normalize_post_title((string) $topic);
    $manual_content = trim((string) $manual_content);

    if ($manual_content !== '') {
        $clean_content = wp_kses_post($manual_content);
        return [
            'title' => $topic,
            'content' => $clean_content,
            'excerpt' => wp_trim_words(wp_strip_all_tags($clean_content), 40, '...'),
            'image_url' => '',
        ];
    }

    $tokens = aismart_topic_queue_title_tokens($topic);
    if (empty($tokens)) {
        $tokens = ['business', 'strategy'];
    }

    $focuses = aismart_topic_queue_context_focuses($topic);
    if (empty($focuses)) {
        $focuses = [implode(' ', array_slice($tokens, 0, 2))];
    }

    $seed = abs(crc32(strtolower($topic)));
    $token_a = (string) $tokens[$seed % count($tokens)];
    $token_b = (string) $tokens[($seed + 2) % count($tokens)];
    $focus_a = (string) $focuses[$seed % count($focuses)];
    $focus_b = (string) $focuses[($seed + 1) % count($focuses)];

    if ($focus_b === '' || strcasecmp($focus_a, $focus_b) === 0) {
        $focus_b = implode(' ', array_slice($tokens, -min(3, count($tokens))));
    }
    if ($focus_b === '' || strcasecmp($focus_a, $focus_b) === 0) {
        $focus_b = (string) $token_b;
    }
    if ($focus_b === '' || strcasecmp($focus_a, $focus_b) === 0) {
        $focus_b = 'execution outcomes';
    }

    $intro_templates = [
        'The AI service is temporarily unavailable, so this draft is generated locally and shaped around your topic intent.',
        'This article draft is built in local fallback mode and adapted from the topic context so you can keep publishing.',
        'Because upstream writing is currently unavailable, this local draft focuses on practical, publish-ready structure.',
        'Local draft mode is active right now, so this version emphasizes clarity, relevance, and actionability for the topic.',
    ];
    $subtopic_templates = [
        'Why %s matters in %s',
        'Practical strategy for %s',
        'Turning %s into measurable progress',
        'Common mistakes in %s and how to avoid them',
        'A weekly plan to improve %s',
        'What to prioritize first in %s',
    ];
    $angle_templates = [
        'focus on audience intent and specific outcomes',
        'connect content decisions to measurable KPIs',
        'reduce complexity and keep execution repeatable',
        'improve relevance with clearer targeting and messaging',
    ];
    $cta_templates = [
        'Start by editing examples and numbers so the article reflects your real workflow and market.',
        'Refine each section with your own cases, screenshots, or data before publishing.',
        'Replace generic points with your team process and recent performance observations.',
        'Add concrete examples from your business context to make the draft fully publish-ready.',
    ];

    $pick = static function ($list, $index) {
        $count = count($list);
        if ($count <= 0) {
            return '';
        }
        return (string) $list[$index % $count];
    };

    $safe_topic = esc_html($topic);
    $safe_focus_a = esc_html($focus_a);
    $safe_focus_b = esc_html($focus_b);
    $safe_token_a = esc_html($token_a);
    $safe_token_b = esc_html($token_b);

    $intro = esc_html($pick($intro_templates, $seed));
    $angle = esc_html($pick($angle_templates, $seed + 1));
    $cta = esc_html($pick($cta_templates, $seed + 2));

    $section_titles = [];
    $used_titles = [];
    for ($i = 0; $i < 3; $i++) {
        $tpl = $pick($subtopic_templates, $seed + $i);
        $base = $i === 0 ? $focus_a : ($i === 1 ? $focus_b : $token_a . ' and ' . $token_b);
        $title = trim(sprintf($tpl, ucfirst($base), gmdate('Y')));
        $title_key = strtolower($title);
        if ($title === '' || isset($used_titles[$title_key])) {
            continue;
        }
        $used_titles[$title_key] = true;
        $section_titles[] = $title;
    }
    if (count($section_titles) < 3) {
        $section_titles[] = 'Execution checklist for ' . ucfirst($token_a);
    }
    if (count($section_titles) < 3) {
        $section_titles[] = 'Key decisions around ' . ucfirst($token_b);
    }

    $safe_section_1 = esc_html((string) $section_titles[0]);
    $safe_section_2 = esc_html((string) $section_titles[1]);
    $safe_section_3 = esc_html((string) $section_titles[2]);

    $content = ''
        . '<p>' . $intro . '</p>'
        . '<p><strong>' . $safe_topic . '</strong> should be approached with two priorities: ' . $safe_focus_a . ' and ' . $safe_focus_b . '. The best early wins usually come when you ' . $angle . '.</p>'
        . '<h2>' . $safe_section_1 . '</h2>'
        . '<p>Set a clear objective and define the audience segment first. For this part of the plan, keep the scope narrow, specify one target result, and remove activities that do not directly support that result.</p>'
        . '<h2>' . $safe_section_2 . '</h2>'
        . '<p>Build a small repeatable workflow: draft, ship, measure, and adjust. Track what changed after each iteration, then keep only the improvements that consistently move the main metric.</p>'
        . '<h2>' . $safe_section_3 . '</h2>'
        . '<p>Use a weekly checklist with owners, deadlines, and review criteria. Small consistent updates outperform large infrequent changes, especially when decisions are tied to real user feedback.</p>'
        . '<p>' . $cta . '</p>';

    $excerpt = wp_trim_words(
        'Local fallback draft for ' . $topic . ': priorities include ' . $focus_a . ' and ' . $focus_b . '.',
        40,
        '...'
    );

    return [
        'title' => $topic,
        'content' => $content,
        'excerpt' => $excerpt,
        'image_url' => '',
    ];
}

function aismart_build_backup_image_query($topic, $category = '', $tags = '', $excerpt = '') {
    $topic = strtolower(trim((string) $topic));
    $category = strtolower(trim((string) $category));
    $tags = strtolower(trim((string) $tags));
    $excerpt = strtolower(trim(wp_strip_all_tags((string) $excerpt)));

    $stop = [
        'the', 'and', 'for', 'with', 'from', 'this', 'that', 'your', 'you', 'are', 'was', 'were', 'into', 'about', 'how', 'why',
        'step', 'steps', 'guide', 'checklist', 'roadmap', 'examples', 'example', 'basics', 'beginner', 'beginners', 'practical',
        'auto', 'post', 'draft', 'now', 'new', 'best', 'top', 'tips', 'plan', 'strategy', 'strategic', 'what', 'when', 'where',
    ];
    $stop_index = array_fill_keys($stop, true);

    $collect = static function ($text) use ($stop_index) {
        $text = preg_replace('/[^a-z0-9\s,\-]/', ' ', (string) $text);
        $parts = preg_split('/[\s,\-]+/', (string) $text);
        if (!is_array($parts)) {
            return [];
        }

        $out = [];
        foreach ($parts as $part) {
            $token = trim((string) $part);
            if ($token === '' || strlen($token) < 3) {
                continue;
            }
            if (isset($stop_index[$token])) {
                continue;
            }
            $out[] = $token;
        }
        return $out;
    };

    // Priority order: explicit tags/category first, then topic, then excerpt cues.
    $token_stream = array_merge(
        $collect($tags),
        $collect($category),
        $collect($topic),
        $collect($excerpt)
    );

    $seen = [];
    $keywords = [];
    foreach ($token_stream as $token) {
        if (isset($seen[$token])) {
            continue;
        }
        $seen[$token] = true;
        $keywords[] = $token;
        if (count($keywords) >= 6) {
            break;
        }
    }

    if (empty($keywords)) {
        $fallback_tokens = aismart_topic_queue_title_tokens((string) $topic);
        foreach ($fallback_tokens as $token) {
            $token = strtolower(trim((string) $token));
            if ($token === '' || strlen($token) < 3 || isset($stop_index[$token])) {
                continue;
            }
            if (isset($seen[$token])) {
                continue;
            }
            $seen[$token] = true;
            $keywords[] = $token;
            if (count($keywords) >= 6) {
                break;
            }
        }
    }

    if (empty($keywords)) {
        return 'healthcare,medical,doctor,clinic';
    }

    return implode(',', $keywords);
}

function aismart_build_backup_image_url($topic, $category = '', $tags = '', $excerpt = '') {
    $query = aismart_build_backup_image_query($topic, $category, $tags, $excerpt);
    if ($query === '') {
        $query = 'healthcare,medical,doctor,clinic';
    }

    // Topic-aware fallback image source to avoid unrelated random landscapes.
    $lock = (string) abs(crc32((string) $query));
    return 'https://loremflickr.com/1200/630/' . rawurlencode($query) . '?lock=' . rawurlencode($lock);
}

function aismart_build_image_prompt($topic, $category = '', $tags = '', $excerpt = '') {
    $topic = trim((string) $topic);
    $category = trim((string) $category);
    $tags = trim((string) $tags);
    $excerpt = trim(wp_strip_all_tags((string) $excerpt));

    $parts = [];
    if ($topic !== '') {
        $parts[] = 'Create a realistic featured image for: ' . $topic;
    }
    if ($category !== '' && strtolower($category) !== 'auto') {
        $parts[] = 'Category context: ' . $category;
    }
    if ($tags !== '') {
        $parts[] = 'Tags: ' . $tags;
    }
    if ($excerpt !== '') {
        $parts[] = 'Visual cues: ' . wp_trim_words($excerpt, 16, '');
    }

    $parts[] = 'Style: editorial photography, clean composition, topic-related, no text, no watermark, no logo.';

    return trim(implode(' ', $parts));
}

function aismart_collect_translation_targets_for_usage($post_id = 0) {
    $post_id = (int) $post_id;
    $all_locales = [];
    $source_language = '';

    if (function_exists('pll_languages_list')) {
        $all_locales = (array) pll_languages_list(['fields' => 'slug']);
        if ($post_id > 0 && function_exists('pll_get_post_language')) {
            $source_language = (string) pll_get_post_language($post_id, 'slug');
        }
        if ($source_language === '' && function_exists('pll_default_language')) {
            $source_language = (string) pll_default_language();
        }
    } elseif (function_exists('icl_get_languages')) {
        $wpml_languages = (array) icl_get_languages('skip_missing=0&orderby=code');
        foreach ($wpml_languages as $row) {
            if (is_array($row) && !empty($row['language_code'])) {
                $all_locales[] = (string) $row['language_code'];
            }
        }
        if ($post_id > 0 && has_filter('wpml_post_language_details')) {
            $details = apply_filters('wpml_post_language_details', null, $post_id);
            if (is_array($details) && !empty($details['language_code'])) {
                $source_language = (string) $details['language_code'];
            }
        }
    }

    $normalized_locales = [];
    foreach ((array) $all_locales as $locale) {
        $locale = sanitize_key((string) $locale);
        if ($locale !== '') {
            $normalized_locales[$locale] = true;
        }
    }

    $source_language = sanitize_key((string) $source_language);
    if ($source_language !== '' && isset($normalized_locales[$source_language])) {
        unset($normalized_locales[$source_language]);
    }

    $targets = array_values(array_keys($normalized_locales));
    return [
        'source_language' => $source_language,
        'locales' => $targets,
        'count' => count($targets),
    ];
}

function aismart_attach_featured_image_from_url($post_id, $image_url, $desc = '') {
    $post_id = (int) $post_id;
    $image_url = trim((string) $image_url);

    if ($post_id <= 0 || $image_url === '' || !filter_var($image_url, FILTER_VALIDATE_URL)) {
        return [
            'saved' => false,
            'attachment_id' => 0,
            'image_url' => $image_url,
            'error' => 'invalid-image-input',
        ];
    }

    if (!function_exists('download_url')) {
        require_once ABSPATH . 'wp-admin/includes/file.php';
    }
    if (!function_exists('media_handle_sideload')) {
        require_once ABSPATH . 'wp-admin/includes/media.php';
    }
    if (!function_exists('wp_generate_attachment_metadata')) {
        require_once ABSPATH . 'wp-admin/includes/image.php';
    }

    $attach_id = media_sideload_image($image_url, $post_id, $desc !== '' ? $desc : 'AISmart generated image', 'id');
    if (is_wp_error($attach_id) || !$attach_id) {
        $tmp_file = download_url($image_url, 30);
        if (!is_wp_error($tmp_file)) {
            $path = (string) wp_parse_url($image_url, PHP_URL_PATH);
            $name = sanitize_file_name((string) wp_basename($path));
            if ($name === '' || strpos($name, '.') === false) {
                $name = 'aismart-image-' . gmdate('Ymd-His') . '.jpg';
            }

            $file_array = [
                'name' => $name,
                'tmp_name' => $tmp_file,
            ];

            $fallback_attach_id = media_handle_sideload($file_array, $post_id, $desc !== '' ? $desc : 'AISmart generated image');
            if (!is_wp_error($fallback_attach_id) && (int) $fallback_attach_id > 0) {
                $attach_id = (int) $fallback_attach_id;
            } else {
                if (file_exists($tmp_file)) {
                    @unlink($tmp_file);
                }
            }
        }
    }

    if (is_wp_error($attach_id) || !$attach_id) {
        return [
            'saved' => false,
            'attachment_id' => 0,
            'image_url' => $image_url,
            'error' => is_wp_error($attach_id) ? $attach_id->get_error_message() : 'media-sideload-failed',
        ];
    }

    set_post_thumbnail($post_id, (int) $attach_id);
    $saved_url = (string) wp_get_attachment_image_url((int) $attach_id, 'full');
    if ($saved_url === '') {
        $saved_url = $image_url;
    }

    return [
        'saved' => true,
        'attachment_id' => (int) $attach_id,
        'image_url' => $saved_url,
        'error' => '',
    ];
}

function aismart_require_media_includes() {
    if (!function_exists('download_url')) {
        require_once ABSPATH . 'wp-admin/includes/file.php';
    }
    if (!function_exists('media_handle_sideload')) {
        require_once ABSPATH . 'wp-admin/includes/media.php';
    }
    if (!function_exists('wp_generate_attachment_metadata')) {
        require_once ABSPATH . 'wp-admin/includes/image.php';
    }
}

add_action('wp_ajax_aismart_create_post', 'aismart_create_post');
function aismart_create_post() {
    if (!current_user_can('manage_options')) {
        wp_send_json_error(['message' => 'Unauthorized'], 403);
    }
    if (!aismart_require_positive_credit_or_json_error('Draft creation')) {
        return;
    }

    aismart_require_media_includes();

    global $wpdb;

    $topic = isset($_POST['topic']) ? sanitize_text_field(wp_unslash($_POST['topic'])) : '';
    $queue_id = isset($_POST['queue_id']) ? (int) $_POST['queue_id'] : 0;
    $post_id = isset($_POST['post_id']) && is_numeric($_POST['post_id']) ? intval($_POST['post_id']) : 0;
    $category_raw = isset($_POST['category']) ? sanitize_text_field(wp_unslash($_POST['category'])) : 'Auto';
    $tags_raw = isset($_POST['tags']) ? sanitize_text_field(wp_unslash($_POST['tags'])) : '';
    $schedule_at_raw = isset($_POST['schedule_at']) ? sanitize_text_field(wp_unslash($_POST['schedule_at'])) : '';
    $manual_content = isset($_POST['content']) ? wp_kses_post(wp_unslash($_POST['content'])) : '';
    $publish_now = isset($_POST['publish_now']) ? (int) $_POST['publish_now'] : 0;
    $force_draft = isset($_POST['force_draft']) ? (int) $_POST['force_draft'] : 0;
    $force_translate = isset($_POST['force_translate']) ? (int) $_POST['force_translate'] : 0;
    $auto_translate_enabled = (bool) get_option('aismart_auto_translate', 0);

    $queue_topic_title = '';
    if ($queue_id > 0) {
        $queue_items = aismart_topic_queue_get_items();
        $queue_index = $queue_id - 1;
        if (isset($queue_items[$queue_index]) && is_array($queue_items[$queue_index])) {
            $queue_topic_title = aismart_topic_queue_normalize_title($queue_items[$queue_index]['title'] ?? '');
            if ($topic === '' && $queue_topic_title !== '') {
                $topic = $queue_topic_title;
            }
        }
    }

    if ($topic === '') {
        wp_send_json_error(['message' => 'Topic required'], 422);
    }

    // Resolve target post: explicit post_id first, otherwise reuse existing post by exact title.
    $target_post_id = 0;
    if ($post_id > 0 && get_post($post_id)) {
        $target_post_id = $post_id;
    } else {
        $existing_id = (int) $wpdb->get_var(
            $wpdb->prepare(
                "SELECT ID FROM {$wpdb->posts}
                 WHERE post_type = 'post'
                   AND post_status IN ('draft','publish','pending','future')
                   AND post_title = %s
                 ORDER BY ID DESC
                 LIMIT 1",
                $topic
            )
        );
        if ($existing_id > 0) {
            $target_post_id = $existing_id;
        }
    }

    $is_update = $target_post_id > 0;
    $manual_update_mode = false;
    $used_local_fallback = false;
    $fallback_reason = '';
    $publish_requested = $publish_now === 1;
    $draft_first_mode = (!$auto_translate_enabled && !$publish_requested) || $force_draft === 1;

    $scheduled_local = '';
    $scheduled_gmt = '';
    $schedule_requested = ($schedule_at_raw !== '');
    if ($schedule_at_raw !== '') {
        $schedule_input = trim((string) $schedule_at_raw);
        $schedule_input = preg_replace('/\s+/u', ' ', str_replace(',', ' ', $schedule_input));

        try {
            $site_tz = function_exists('wp_timezone') ? wp_timezone() : new DateTimeZone('UTC');
            $now_dt = new DateTime('now', $site_tz);
            $scheduled_dt = false;

            $format_candidates = [
                'Y-m-d\\TH:i',
                'Y-m-d\\TH:i:s',
                'Y-m-d H:i',
                'Y-m-d H:i:s',
                'd/m/Y H:i',
                'd/m/Y h:i A',
                'd/m/Y, h:i A',
                'm/d/Y h:i A',
                'm/d/Y, h:i A',
            ];

            foreach ($format_candidates as $format) {
                $candidate = DateTime::createFromFormat($format, $schedule_input, $site_tz);
                if ($candidate instanceof DateTime) {
                    $scheduled_dt = $candidate;
                    break;
                }
            }

            if (!$scheduled_dt && preg_match('/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$/', $schedule_input)) {
                $scheduled_dt = new DateTime($schedule_input, $site_tz);
            }

            // Last-resort parser for ISO variants with timezone offsets/milliseconds.
            if (!$scheduled_dt) {
                try {
                    $generic_dt = new DateTime($schedule_input);
                    $generic_dt->setTimezone($site_tz);
                    $scheduled_dt = $generic_dt;
                } catch (Exception $e) {
                    $scheduled_dt = false;
                }
            }

            if ($scheduled_dt instanceof DateTime && $scheduled_dt > $now_dt) {
                $scheduled_local = $scheduled_dt->format('Y-m-d H:i:s');
                $scheduled_gmt = get_gmt_from_date($scheduled_local);
            }
        } catch (Exception $e) {
            $scheduled_local = '';
            $scheduled_gmt = '';
        }
    }

    if ($schedule_requested && $scheduled_local === '') {
        $site_tz_name = function_exists('wp_timezone_string') ? (string) wp_timezone_string() : '';
        if ($site_tz_name === '') {
            $site_tz_name = (string) get_option('timezone_string', 'UTC');
            if ($site_tz_name === '') {
                $site_tz_name = 'UTC';
            }
        }

        wp_send_json_error([
            'message' => 'Schedule time must be in the future (site timezone: ' . sanitize_text_field($site_tz_name) . ').',
        ], 422);
    }

    if ($is_update && trim((string) $manual_content) !== '') {
        $manual_update_mode = true;
        $data = [
            'title' => $topic,
            'content' => $manual_content,
            'excerpt' => wp_trim_words(wp_strip_all_tags($manual_content), 40, '...'),
        ];
        error_log('AISmart Create Post: using local manual content for update post_id=' . $target_post_id);
    } else {
        error_log("AISmart Create Post: topic={$topic}, post_id={$post_id}, target_post_id={$target_post_id}, is_update=" . ($is_update ? '1' : '0'));

        $api_result = aismart_request_posts_api([
            'site' => 'site2',
            'topic' => $topic,
            'skip_image' => $is_update ? 1 : 0,
            'image_prompt' => aismart_build_image_prompt($topic, $category_raw, $tags_raw, $manual_content),
        ], 60);

        if (empty($api_result['ok'])) {
            $code = isset($api_result['status']) ? (int) $api_result['status'] : 500;
            $msg = !empty($api_result['message']) ? (string) $api_result['message'] : 'Create post failed';
            $body = isset($api_result['body']) ? (string) $api_result['body'] : '';
            error_log('AISmart Create Post failed: status=' . $code . ' message=' . $msg . ' body=' . $body);
            $data = aismart_build_local_fallback_post_data($topic, $manual_content);
            $used_local_fallback = true;
            $fallback_reason = $msg;
        } else {
            $data = (array) $api_result['data'];
        }
    }

    // Publish post or update existing post (no duplicate IDs on repeated Create Now)
    $resolved_title = aismart_normalize_post_title((string) ($data['title'] ?? $topic));
    if ($resolved_title === '') {
        $resolved_title = $topic;
    }

    // Local text fallback should not force draft when user explicitly requested publish/translate flow.
    $force_draft_for_fallback = $used_local_fallback && !$publish_requested;
    $final_post_status = ($force_draft_for_fallback || $draft_first_mode) ? 'draft' : 'publish';
    if ($scheduled_local !== '' && $final_post_status !== 'draft') {
        $final_post_status = 'future';
    }

    if ($schedule_at_raw !== '' && function_exists('aismart_queue_log')) {
        aismart_queue_log(
            'Create post schedule parse topic=' . $topic
            . ' schedule_at_raw=' . sanitize_text_field((string) $schedule_at_raw)
            . ' scheduled_local=' . ($scheduled_local !== '' ? $scheduled_local : '(none)')
            . ' final_post_status=' . $final_post_status
        );
    }

    $post_data = [
        'post_title'    => $resolved_title,
        'post_content'  => aismart_cleanup_translated_post_content((string) ($data['content'] ?? '')),
        'post_excerpt'  => '',
        'post_status'   => $final_post_status,
        'post_author'   => get_current_user_id(),
        'post_type'     => 'post',
    ];
    if ($final_post_status === 'future' && $scheduled_local !== '') {
        $post_data['post_date'] = $scheduled_local;
        if ($scheduled_gmt !== '') {
            $post_data['post_date_gmt'] = $scheduled_gmt;
        }
        // Required on updates so WordPress persists the provided future date.
        // Without this, wp_update_post may keep current post_date and immediately publish.
        if ($is_update) {
            $post_data['edit_date'] = true;
        }
    }
    $resolved_content = (string) ($post_data['post_content'] ?? '');
    $resolved_excerpt = wp_trim_words(wp_strip_all_tags($resolved_content), 40, '...');
    $post_data['post_excerpt'] = $resolved_excerpt;

    if ($is_update) {
        $post_data['ID'] = $target_post_id;
        $result = wp_update_post($post_data, true);
        if (is_wp_error($result)) {
             error_log('AISmart Update Post Failed: ' . $result->get_error_message());
             wp_send_json_error(['message' => 'Failed to update post'], 500);
        }
        $post_id = $target_post_id;
    } else {
        $post_id = wp_insert_post($post_data);
    }
    
    if (is_wp_error($post_id)) {
        wp_send_json_error(['message' => 'Failed to insert post'], 500);
    }

    $created_provider = aismart_resolve_selected_provider_key();
    if ($created_provider !== '') {
        update_post_meta((int) $post_id, '_aismart_created_provider', $created_provider);
        update_post_meta((int) $post_id, '_aismart_last_multilang_provider', $created_provider);
    }

    // Keep queue/list and generated posts in sync.
    // If a topic was manually typed (not already queued), add it first so it appears in Current Topic List.
    aismart_topic_queue_add_titles([$topic], 'manual');
    if ((function_exists('mb_strtolower') ? mb_strtolower($resolved_title) : strtolower($resolved_title)) !== (function_exists('mb_strtolower') ? mb_strtolower($topic) : strtolower($topic))) {
        aismart_topic_queue_add_titles([$resolved_title], 'manual');
    }

    $marked_by_queue_id = false;
    if ($queue_id > 0) {
        $marked_by_queue_id = aismart_topic_queue_mark_written_by_queue_id($queue_id, (int) $post_id, $created_provider);
    }
    if (!$marked_by_queue_id) {
        aismart_topic_queue_mark_written($topic, (int) $post_id, $created_provider);
    }
    if ((function_exists('mb_strtolower') ? mb_strtolower($resolved_title) : strtolower($resolved_title)) !== (function_exists('mb_strtolower') ? mb_strtolower($topic) : strtolower($topic))) {
        aismart_topic_queue_mark_written($resolved_title, (int) $post_id, $created_provider);
    }

    // --- Polylang: Ensure Language is Set for Original Post ---
    if (function_exists('pll_set_post_language') && function_exists('pll_default_language')) {
        $current_lang = pll_get_post_language($post_id);
        if (!$current_lang) {
            $def_lang = pll_default_language();
            pll_set_post_language($post_id, $def_lang);
        }
    }

    update_post_meta((int) $post_id, '_aismart_generated_post', 1);
    update_post_meta((int) $post_id, '_aismart_generated_at', gmdate('c'));
    if ($used_local_fallback) {
        update_post_meta((int) $post_id, '_aismart_local_fallback', 1);
        if ($fallback_reason !== '') {
            update_post_meta((int) $post_id, '_aismart_local_fallback_reason', sanitize_text_field($fallback_reason));
        }
    } else {
        delete_post_meta((int) $post_id, '_aismart_local_fallback');
        delete_post_meta((int) $post_id, '_aismart_local_fallback_reason');
    }

    // Assign category (default Auto)
    $category_name = trim($category_raw);
    if ($category_name === '' || strtolower($category_name) === 'auto') {
        $category_name = 'Auto';
    }
    $category_slug = sanitize_title($category_name);
    $category_term = get_term_by('slug', $category_slug, 'category');
    if (!$category_term) {
        $category_term = get_term_by('name', $category_name, 'category');
    }
    if (!$category_term || is_wp_error($category_term)) {
        $created_category = wp_insert_term($category_name, 'category', ['slug' => $category_slug]);
        if (!is_wp_error($created_category) && !empty($created_category['term_id'])) {
            $category_term = get_term((int) $created_category['term_id'], 'category');
        }
    }
    if ($category_term && !is_wp_error($category_term)) {
        wp_set_post_categories($post_id, [(int) $category_term->term_id], false);
    }

    // Assign tags from user input only.
    $tags = [];
    if ($tags_raw !== '') {
        $tags = array_filter(array_map('trim', explode(',', $tags_raw)));
    }
    $tags = array_values(array_unique(array_map('sanitize_text_field', $tags)));
    wp_set_post_tags($post_id, $tags, false);

    // Handle image on first create; manual resume/update mode should not auto-generate images.
    $image_fallback_used = false;
    $image_fallback_reason = '';
    $image_url = $data['image_url'] ?? '';
    if ($image_url === '' && isset($data['featured_image'])) {
        $image_url = (string) $data['featured_image'];
    }

    $should_generate_image = !$is_update || !has_post_thumbnail((int) $post_id);
    if ($manual_update_mode) {
        // Resume/publish of existing content should only update post metadata/content unless user explicitly regenerates image.
        $should_generate_image = false;
    }

    if ($should_generate_image) {
        if ($image_url === '' || !filter_var($image_url, FILTER_VALIDATE_URL)) {
            $image_only_result = aismart_request_posts_api([
                'site' => 'site2',
                'topic' => $topic,
                'image_only' => 1,
                'image_prompt' => aismart_build_image_prompt($topic, $category_raw, $tags_raw, (string) ($data['excerpt'] ?? '')),
            ], 90);

            if (!empty($image_only_result['ok'])) {
                $image_data = (array) $image_only_result['data'];
                $candidate = isset($image_data['image_url']) ? (string) $image_data['image_url'] : '';
                if ($candidate === '' && isset($image_data['featured_image'])) {
                    $candidate = (string) $image_data['featured_image'];
                }
                if ($candidate !== '' && filter_var($candidate, FILTER_VALIDATE_URL)) {
                    $image_url = $candidate;
                }
            } else {
                $image_fallback_used = true;
                $image_fallback_reason = !empty($image_only_result['message'])
                    ? (string) $image_only_result['message']
                    : 'Image generation failed';
            }
        }

        if ($image_url === '' || !filter_var($image_url, FILTER_VALIDATE_URL)) {
            $image_fallback_used = true;
            if ($image_fallback_reason === '') {
                $image_fallback_reason = 'Upstream image URL missing';
            }

            $backup_image_url = aismart_build_backup_image_url($topic, $category_raw, $tags_raw, $resolved_excerpt);
            if ($backup_image_url !== '' && filter_var($backup_image_url, FILTER_VALIDATE_URL)) {
                $image_url = $backup_image_url;
            }
        }

        if ($image_url !== '' && filter_var($image_url, FILTER_VALIDATE_URL)) {
            $attach_result = aismart_attach_featured_image_from_url($post_id, $image_url, 'Generated image for ' . $topic);
            if (!empty($attach_result['saved'])) {
                $image_url = (string) ($attach_result['image_url'] ?? $image_url);
            } else {
                $image_fallback_used = true;
                $attach_error = (string) ($attach_result['error'] ?? 'image-attach-failed');
                if ($image_fallback_reason === '' || $image_fallback_reason === 'Upstream image URL missing') {
                    $image_fallback_reason = $attach_error;
                }
                error_log('AISmart Image Sideload Failed: ' . $image_fallback_reason);
            }
        }
    }

    if (empty($image_url)) {
        $image_url = get_the_post_thumbnail_url($post_id, 'full') ?: '';
    }

    // If auto-translate is enabled, queue translation for Create Now updates too.
    $translation_queued = false;
    $translation_queued_new = false;
    $translation_queued_background = false;
    $translation_pending_on_publish = false;
    $translation_warning = '';
    $translation_usage_targets = [
        'source_language' => '',
        'locales' => [],
        'count' => 0,
    ];
    if ($final_post_status === 'publish' && ($auto_translate_enabled || $force_translate === 1)) {
        if (aismart_has_polylang_conveythis_conflict()) {
            $translation_warning = 'Auto-translation skipped: Polylang + ConveyThis conflict can cause redirect loops.';
        } else {
            $already_queued = (bool) get_post_meta($post_id, '_aismart_translation_queued', true);
            if ($is_update) {
                delete_post_meta($post_id, '_aismart_translation_queued');
                $already_queued = false;
            }
            if (!$already_queued) {
                $route = aismart_detect_translation_command();
                $queue_engine = isset($route['engine']) ? sanitize_key((string) $route['engine']) : 'unknown';

                // Some native engines can be slow when many locales are enabled.
                // Queue them in background so create/publish response stays fast and JSON-safe.
                if ($queue_engine === 'bogo' || $queue_engine === 'wpml') {
                    $queue_engine_for_background = $queue_engine === 'wpml' ? 'wpml' : 'bogo';
                    $args = [(int) $post_id, $queue_engine_for_background];
                    if (!wp_next_scheduled('aismart_process_translation_event', $args)) {
                        wp_schedule_single_event(time() + 1, 'aismart_process_translation_event', $args);
                    }
                    if (function_exists('spawn_cron')) {
                        @spawn_cron(time());
                    }
                    aismart_defer_background_translation((int) $post_id, $queue_engine_for_background);

                    $translation_queued = true;
                    $translation_queued_new = true;
                    $translation_queued_background = true;
                    update_post_meta($post_id, '_aismart_translation_queued', 1);
                    if ($translation_warning === '') {
                        $translation_warning = $queue_engine_for_background === 'wpml'
                            ? 'Translation queued in background for WPML.'
                            : 'Translation queued in background for Bogo.';
                    }
                    $translation_usage_targets = aismart_collect_translation_targets_for_usage((int) $post_id);
                } else {
                $queue_runtime_noise = '';
                $buffer_started = false;
                try {
                    if (!headers_sent()) {
                        ob_start();
                        $buffer_started = true;
                    }

                    $translation_queued = aismart_queue_translation_for_post($post_id);
                } catch (Throwable $e) {
                    $translation_queued = false;
                    update_post_meta($post_id, '_aismart_translation_last_error', sanitize_text_field($e->getMessage()));
                    error_log('AISmart Translation Queue Exception: post_id=' . (int) $post_id . ' message=' . $e->getMessage());
                } finally {
                    if ($buffer_started) {
                        $queue_runtime_noise = trim((string) ob_get_clean());
                    }
                }

                if ($queue_runtime_noise !== '') {
                    $noise_preview = substr(preg_replace('/\\s+/u', ' ', $queue_runtime_noise), 0, 500);
                    error_log('AISmart Translation Queue Runtime Output: post_id=' . (int) $post_id . ' output=' . $noise_preview);
                }

                if ($translation_queued) {
                    $translation_queued_new = true;
                    update_post_meta($post_id, '_aismart_translation_queued', 1);
                    $translation_usage_targets = aismart_collect_translation_targets_for_usage((int) $post_id);
                    if ($queue_runtime_noise !== '' && $translation_warning === '') {
                        $translation_warning = 'Post published. Translation queued with runtime warnings; review server logs.';
                    }
                } else {
                    $last_translation_error = trim((string) get_post_meta($post_id, '_aismart_translation_last_error', true));
                    if ($translation_warning === '') {
                        if ($last_translation_error !== '') {
                            $translation_warning = 'Auto-translation skipped: ' . sanitize_text_field($last_translation_error);
                        } else {
                            $translation_warning = 'Post published, but translation could not be queued right now.';
                        }
                    }
                }
                }
            } else {
                $translation_queued = true;
            }
        }
    } elseif ($final_post_status === 'future' && ($auto_translate_enabled || $force_translate === 1)) {
        // For scheduled posts, defer translation queue until WordPress publishes the post.
        update_post_meta($post_id, '_aismart_force_translate_on_publish', 1);
        $translation_pending_on_publish = true;
        if ($translation_warning === '') {
            $translation_warning = 'Translation will be queued automatically when this scheduled post is published.';
        }
    } else {
        delete_post_meta($post_id, '_aismart_force_translate_on_publish');
    }

    // Keep WP API unit usage visible to plugin UI (matches backend business-unit model).
    $wp_api_units_post = $manual_update_mode ? 0 : 1;
    $wp_api_units_image = $should_generate_image ? 1 : 0;
    $translation_locale_count = 0;
    if ($translation_queued_new) {
        $translation_locale_count = (int) ($translation_usage_targets['count'] ?? 0);
        if ($translation_locale_count <= 0) {
            $translation_locale_count = 1;
        }
    }
    $wp_api_units_translation = $translation_locale_count > 0 ? ($translation_locale_count * 2) : 0;
    $wp_api_units_total = $wp_api_units_post + $wp_api_units_image + $wp_api_units_translation;

    $token_event_amount = $manual_update_mode ? 0 : 1;

    aismart_log_token_event(
        'post_generate',
        $token_event_amount,
        [
            'topic' => $topic,
            'post_id' => (int) $post_id,
            'is_update' => $is_update ? 1 : 0,
            'manual_update_mode' => $manual_update_mode ? 1 : 0,
            'fallback_used' => $used_local_fallback ? 1 : 0,
            'image_requested' => $should_generate_image ? 1 : 0,
            'image_url' => (string) $image_url,
            'image_fallback_used' => $image_fallback_used ? 1 : 0,
            'translation_queued' => $translation_queued ? 1 : 0,
            'translation_locales' => (array) ($translation_usage_targets['locales'] ?? []),
            'translation_count' => (int) ($translation_usage_targets['count'] ?? 0),
            'source_language' => (string) ($translation_usage_targets['source_language'] ?? ''),
        ],
        'Generated or updated post draft'
    );

    wp_send_json_success([
        'post_id' => $post_id,
        'queue_id' => $queue_id > 0 ? $queue_id : 0,
        'title' => $resolved_title,
        'content' => $resolved_content,
        'excerpt' => $resolved_excerpt,
        'image_url' => $image_url,
        'featured_image' => $image_url,
        'post_status' => $final_post_status,
        'scheduled_at' => $final_post_status === 'future' ? $scheduled_local : '',
        'translation_queued' => $translation_queued ? 1 : 0,
        'translation_queued_background' => $translation_queued_background ? 1 : 0,
        'translation_pending_on_publish' => $translation_pending_on_publish ? 1 : 0,
        'translation_warning' => $translation_warning,
        'auto_translate_enabled' => $auto_translate_enabled ? 1 : 0,
        'draft_first_mode' => $draft_first_mode ? 1 : 0,
        'fallback_used' => $used_local_fallback ? 1 : 0,
        'fallback_reason' => $fallback_reason,
        'fallback_notice' => $used_local_fallback
            ? 'Text AI temporarily unavailable, so local fallback content was used.'
            : '',
        'wp_api_units_estimated_total' => (int) $wp_api_units_total,
        'wp_api_units_breakdown' => [
            'post' => (int) $wp_api_units_post,
            'image' => (int) $wp_api_units_image,
            'translation' => (int) $wp_api_units_translation,
            'translation_locales' => (int) $translation_locale_count,
        ],
        'image_fallback_used' => $image_fallback_used ? 1 : 0,
        'image_fallback_reason' => $image_fallback_reason,
        'edit_link' => get_edit_post_link($post_id, ''),
    ]);
}

// AJAX: Regenerate image via NVL API
add_action('wp_ajax_aismart_regenerate_image', 'aismart_regenerate_image');
function aismart_regenerate_image() {
    if (!current_user_can('manage_options')) {
        wp_send_json_error(['message' => 'Unauthorized'], 403);
    }
    if (!aismart_require_positive_credit_or_json_error('Image regeneration')) {
        return;
    }

    $topic = isset($_POST['topic']) ? sanitize_text_field(wp_unslash($_POST['topic'])) : '';
    $post_id = isset($_POST['post_id']) ? absint($_POST['post_id']) : 0;
    $category_raw = isset($_POST['category']) ? sanitize_text_field(wp_unslash($_POST['category'])) : '';
    $tags_raw = isset($_POST['tags']) ? sanitize_text_field(wp_unslash($_POST['tags'])) : '';
    if ($topic === '') {
        wp_send_json_error(['message' => 'Topic required'], 422);
    }

    error_log('AISmart Regenerate Image: topic=' . $topic);

    $image_fallback_used = false;
    $image_fallback_reason = '';

    $api_result = aismart_request_posts_api([
        'site' => 'site2',
        'topic' => $topic,
        'image_only' => 1,
        'image_prompt' => aismart_build_image_prompt($topic),
    ], 90);

    $image_url = '';
    if (!empty($api_result['ok'])) {
        $data = (array) $api_result['data'];
        $image_url = isset($data['image_url']) ? (string) $data['image_url'] : '';
        if ($image_url === '' && isset($data['featured_image'])) {
            $image_url = (string) $data['featured_image'];
        }
    } else {
        $image_fallback_used = true;
        $image_fallback_reason = !empty($api_result['message']) ? (string) $api_result['message'] : 'Image generation failed';
        error_log('AISmart Regenerate Image failed, keeping existing image: ' . $image_fallback_reason);
    }

    if ($image_url === '' || !filter_var($image_url, FILTER_VALIDATE_URL)) {
        $image_fallback_used = true;
        if ($image_fallback_reason === '') {
            $image_fallback_reason = 'Upstream image URL missing';
        }

        $existing_excerpt = '';
        if ($post_id > 0) {
            $existing_post = get_post($post_id);
            if ($existing_post instanceof WP_Post) {
                $existing_excerpt = wp_trim_words(wp_strip_all_tags((string) $existing_post->post_content), 24, '');
            }
        }

        $backup_image_url = aismart_build_backup_image_url($topic, $category_raw, $tags_raw, $existing_excerpt);
        if ($backup_image_url !== '' && filter_var($backup_image_url, FILTER_VALIDATE_URL)) {
            $image_url = $backup_image_url;
        }

        if (($image_url === '' || !filter_var($image_url, FILTER_VALIDATE_URL)) && $post_id > 0) {
            $image_url = get_the_post_thumbnail_url($post_id, 'full') ?: '';
        }
    }

    $saved_to_post = 0;
    $attachment_id = 0;
    if ($post_id > 0 && get_post($post_id) && $image_url !== '') {
        aismart_require_media_includes();

        $attach_result = aismart_attach_featured_image_from_url($post_id, $image_url, 'AISmart regenerated image');
        if (!empty($attach_result['saved'])) {
            $saved_to_post = 1;
            $attachment_id = (int) ($attach_result['attachment_id'] ?? 0);
            $image_url = (string) ($attach_result['image_url'] ?? $image_url);
        } else {
            $image_fallback_used = true;
            $image_fallback_reason = (string) ($attach_result['error'] ?? 'image-attach-failed');
            error_log('AISmart Regenerate Image save failed: post_id=' . $post_id . ' error=' . $image_fallback_reason);
            $attachment_id = 0;
        }
    }

    aismart_log_token_event(
        'image_regenerate',
        1,
        [
            'topic' => $topic,
            'post_id' => (int) $post_id,
            'saved_to_post' => $saved_to_post,
            'fallback_used' => $image_fallback_used ? 1 : 0,
        ],
        'Regenerated featured image'
    );

    wp_send_json_success([
        'image_url' => $image_url,
        'featured_image' => $image_url,
        'saved_to_post' => $saved_to_post,
        'saved_post_id' => $saved_to_post ? $post_id : 0,
        'attachment_id' => (int) $attachment_id,
        'fallback_used' => $image_fallback_used ? 1 : 0,
        'fallback_reason' => $image_fallback_reason,
    ]);
}

add_action('wp_ajax_aismart_regenerate_image_all_languages', 'aismart_regenerate_image_all_languages');
function aismart_regenerate_image_all_languages() {
    if (!current_user_can('manage_options')) {
        wp_send_json_error(['message' => 'Unauthorized'], 403);
    }
    if (!aismart_require_positive_credit_or_json_error('Image regeneration across languages')) {
        return;
    }

    aismart_require_media_includes();

    $topic = isset($_POST['topic']) ? sanitize_text_field(wp_unslash($_POST['topic'])) : '';
    $post_id = isset($_POST['post_id']) ? absint($_POST['post_id']) : 0;
    $category_raw = isset($_POST['category']) ? sanitize_text_field(wp_unslash($_POST['category'])) : '';
    $tags_raw = isset($_POST['tags']) ? sanitize_text_field(wp_unslash($_POST['tags'])) : '';

    if ($topic === '' || $post_id <= 0) {
        wp_send_json_error(['message' => 'Topic and post_id are required'], 422);
    }

    $image_fallback_used = false;
    $image_fallback_reason = '';

    $api_result = aismart_request_posts_api([
        'site' => 'site2',
        'topic' => $topic,
        'image_only' => 1,
        'image_prompt' => aismart_build_image_prompt($topic),
    ], 90);

    $image_url = '';
    if (!empty($api_result['ok'])) {
        $data = (array) $api_result['data'];
        $image_url = isset($data['image_url']) ? (string) $data['image_url'] : '';
        if ($image_url === '' && isset($data['featured_image'])) {
            $image_url = (string) $data['featured_image'];
        }
    } else {
        $image_fallback_used = true;
        $image_fallback_reason = !empty($api_result['message']) ? (string) $api_result['message'] : 'Image generation failed';
    }

    if ($image_url === '' || !filter_var($image_url, FILTER_VALIDATE_URL)) {
        $image_fallback_used = true;
        if ($image_fallback_reason === '') {
            $image_fallback_reason = 'Upstream image URL missing';
        }

        $existing_excerpt = '';
        $existing_post = get_post($post_id);
        if ($existing_post instanceof WP_Post) {
            $existing_excerpt = wp_trim_words(wp_strip_all_tags((string) $existing_post->post_content), 24, '');
        }

        $backup_image_url = aismart_build_backup_image_url($topic, $category_raw, $tags_raw, $existing_excerpt);
        if ($backup_image_url !== '' && filter_var($backup_image_url, FILTER_VALIDATE_URL)) {
            $image_url = $backup_image_url;
        }

        if ($image_url === '' || !filter_var($image_url, FILTER_VALIDATE_URL)) {
            $existing_image = get_the_post_thumbnail_url($post_id, 'full') ?: '';
            wp_send_json_success([
                'image_url' => $existing_image,
                'featured_image' => $existing_image,
                'updated_post_ids' => [],
                'updated_count' => 0,
                'attachment_id' => 0,
                'fallback_used' => 1,
                'fallback_reason' => $image_fallback_reason,
            ]);
            return;
        }
    }

    $attachment_id = 0;
    $attach_result = aismart_attach_featured_image_from_url($post_id, $image_url, 'AISmart regenerated image');
    if (!empty($attach_result['saved'])) {
        $attachment_id = (int) ($attach_result['attachment_id'] ?? 0);
        $image_url = (string) ($attach_result['image_url'] ?? $image_url);
    } else {
        $image_fallback_used = true;
        $image_fallback_reason = (string) ($attach_result['error'] ?? 'image-attach-failed');
        wp_send_json_success([
            'image_url' => $image_url,
            'featured_image' => $image_url,
            'updated_post_ids' => [],
            'updated_count' => 0,
            'attachment_id' => 0,
            'fallback_used' => 1,
            'fallback_reason' => $image_fallback_reason,
        ]);
    }

    $target_ids = [$post_id];
    if (function_exists('apply_filters')) {
        $trid = apply_filters('wpml_element_trid', null, $post_id, 'post_post');
        if ($trid) {
            $translations = apply_filters('wpml_get_element_translations', null, $trid, 'post_post');
            if (is_array($translations)) {
                foreach ($translations as $translation) {
                    $tid = isset($translation->element_id) ? (int) $translation->element_id : 0;
                    if ($tid > 0) {
                        $target_ids[] = $tid;
                    }
                }
            }
        }
    }

    $target_ids = array_values(array_unique(array_map('intval', $target_ids)));
    $updated_ids = [];
    foreach ($target_ids as $target_id) {
        if ($target_id > 0 && get_post($target_id)) {
            set_post_thumbnail($target_id, (int) $attachment_id);
            $updated_ids[] = $target_id;
        }
    }

    aismart_log_token_event(
        'image_regenerate_multilang',
        max(1, count($updated_ids)),
        [
            'topic' => $topic,
            'source_post_id' => (int) $post_id,
            'updated_count' => count($updated_ids),
            'updated_post_ids' => array_values(array_map('intval', $updated_ids)),
            'fallback_used' => $image_fallback_used ? 1 : 0,
        ],
        'Regenerated featured image and propagated to translations'
    );

    wp_send_json_success([
        'image_url' => $image_url,
        'featured_image' => $image_url,
        'updated_post_ids' => $updated_ids,
        'updated_count' => count($updated_ids),
        'attachment_id' => (int) $attachment_id,
        'fallback_used' => $image_fallback_used ? 1 : 0,
        'fallback_reason' => $image_fallback_reason,
    ]);
}

// AJAX: Get automation settings
function aismart_token_logs_table_name() {
    global $wpdb;

    static $resolved = null;
    if ($resolved !== null) {
        return $resolved;
    }

    $candidates = [
        'token_logs',
        $wpdb->prefix . 'token_logs',
    ];

    foreach ($candidates as $table_name) {
        $exists = $wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $table_name));
        if (is_string($exists) && $exists === $table_name) {
            $resolved = $table_name;
            return $resolved;
        }
    }

    $resolved = '';
    return $resolved;
}

function aismart_plugin_response_data_array($response) {
    if (!is_array($response)) {
        return [];
    }

    if (isset($response['data']) && is_array($response['data'])) {
        return $response['data'];
    }

    return $response;
}

function aismart_snapshot_debug_log($tag, $payload = []) {
    $tag = sanitize_key((string) $tag);
    if ($tag === '') {
        $tag = 'snapshot';
    }

    $record = [
        'ts' => gmdate('c'),
        'tag' => $tag,
        'payload' => is_array($payload) ? $payload : ['value' => (string) $payload],
    ];

    $line = wp_json_encode($record);
    if (!is_string($line) || $line === '') {
        return;
    }

    $upload_dir = wp_upload_dir();
    $base_dir = isset($upload_dir['basedir']) ? (string) $upload_dir['basedir'] : '';
    if ($base_dir === '') {
        return;
    }

    $log_dir = trailingslashit($base_dir) . 'aismart-debug';
    if (!is_dir($log_dir)) {
        wp_mkdir_p($log_dir);
    }
    if (!is_dir($log_dir) || !is_writable($log_dir)) {
        return;
    }

    $log_file = trailingslashit($log_dir) . 'snapshot-sync.log';
    // Keep file size bounded to avoid unbounded growth during polling.
    if (file_exists($log_file) && filesize($log_file) > 5 * 1024 * 1024) {
        @rename($log_file, $log_file . '.1');
    }

    @file_put_contents($log_file, $line . "\n", FILE_APPEND | LOCK_EX);
}

function aismart_snapshot_truncate_json($value, $limit = 1800) {
    $limit = (int) $limit;
    if ($limit <= 0) {
        $limit = 1800;
    }

    $json = wp_json_encode($value);
    if (!is_string($json)) {
        return '';
    }

    if (strlen($json) <= $limit) {
        return $json;
    }

    return substr($json, 0, $limit) . '...TRUNCATED';
}

function aismart_cloud_usage_date_window() {
    $tz = function_exists('wp_timezone_string') ? (string) wp_timezone_string() : '';
    if ($tz !== '' && preg_match('/^[+-]\d{2}:\d{2}$/', $tz)) {
        $tz = 'UTC';
    }
    if ($tz === '') {
        $tz = 'UTC';
    }

    return [
        'from' => '2000-01-01',
        'to' => gmdate('Y-m-d'),
        'timezone' => $tz,
    ];
}

function aismart_cloud_workspace_usage_snapshot($workspace_id, $limit = 50, $filters = []) {
    $workspace_id = (int) $workspace_id;
    $limit = (int) $limit;
    if ($workspace_id <= 0) {
        return ['ok' => false];
    }

    if ($limit <= 0) {
        $limit = 50;
    }
    if ($limit > 500) {
        $limit = 500;
    }

    $window = aismart_cloud_usage_date_window();
    $state_user_id = (int) aismart_onboarding_resolve_state_user_id();
    $base_payload = [
        'workspace_id' => $workspace_id,
        'from' => $window['from'],
        'to' => $window['to'],
        'timezone' => $window['timezone'],
    ];
    if ($state_user_id > 0) {
        $base_payload['user_id'] = $state_user_id;
    }

    $summary = [
        'total_logs' => 0,
        'unique_users' => 0,
        'total_amount' => 0,
    ];
    $credit = [
        'live' => null,
        'quota' => null,
        'used' => null,
        'updated_at' => '',
    ];
    $transactions = [];
    $ok = false;

    $credit_payload_req = ['workspace_id' => $workspace_id];
    if ($state_user_id > 0) {
        $credit_payload_req['user_id'] = $state_user_id;
    }
    $credit_res = aismart_plugin_api_request('GET', 'api/plugin/v1/credits/balance', $credit_payload_req, false);
    if (!is_wp_error($credit_res) && is_array($credit_res)) {
        $ok = true;
        $credit_payload = aismart_plugin_response_data_array($credit_res);
        $credit['live'] = (float) aismart_onboarding_deep_find_scalar($credit_payload, ['credit_balance_live', 'credit_balance', 'balance']);
        $credit['quota'] = (float) aismart_onboarding_deep_find_scalar($credit_payload, ['credit_quota', 'quota']);
        $credit['used'] = (float) aismart_onboarding_deep_find_scalar($credit_payload, ['credit_used', 'used']);
        $credit['updated_at'] = sanitize_text_field((string) aismart_onboarding_deep_find_scalar($credit_payload, ['updated_at', 'updatedAt']));
    }

    $tx_payload = [
        'workspace_id' => $workspace_id,
        'page' => 1,
        'per_page' => $limit,
        'from' => $window['from'],
        'to' => $window['to'],
        'timezone' => $window['timezone'],
    ];
    if ($state_user_id > 0) {
        $tx_payload['user_id'] = $state_user_id;
    }

    if (isset($filters['type']) && is_string($filters['type'])) {
        $type = sanitize_key($filters['type']);
        if ($type !== '' && $type !== 'all') {
            $tx_payload['type'] = $type;
        }
    }
    if (isset($filters['user_id']) && is_numeric($filters['user_id'])) {
        $uid = (int) $filters['user_id'];
        if ($uid > 0) {
            $tx_payload['user_id'] = $uid;
        }
    }
    if (isset($filters['source']) && is_string($filters['source'])) {
        $source = sanitize_key($filters['source']);
        if ($source !== '' && $source !== 'all') {
            $tx_payload['source'] = $source;
        }
    }

    $tx_res = aismart_plugin_api_request('GET', 'api/plugin/v1/usage/transactions-compat', $tx_payload, false);
    if (is_wp_error($tx_res)) {
        $tx_res = aismart_plugin_api_request('GET', 'api/plugin/v1/usage/transactions', $tx_payload, false);
    }
    if (!is_wp_error($tx_res) && is_array($tx_res)) {
        $ok = true;
        $tx_summary = isset($tx_res['summary']) && is_array($tx_res['summary']) ? $tx_res['summary'] : [];
        if (!empty($tx_summary)) {
            $summary['total_logs'] = (int) aismart_onboarding_deep_find_scalar($tx_summary, ['total_logs', 'total']);
            $summary['unique_users'] = (int) aismart_onboarding_deep_find_scalar($tx_summary, ['unique_users', 'users_count']);
            $total_usage_units = (float) aismart_onboarding_deep_find_scalar($tx_summary, ['total_usage_units', 'usage_units', 'total_amount']);
            $total_cost = (float) aismart_onboarding_deep_find_scalar($tx_summary, ['total_cost', 'cost']);
            $summary['total_amount'] = $total_usage_units > 0 ? $total_usage_units : $total_cost;
        }

        $tx_data = aismart_plugin_response_data_array($tx_res);
        $rows = [];
        if (isset($tx_data['transactions']) && is_array($tx_data['transactions'])) {
            $rows = $tx_data['transactions'];
        } elseif (isset($tx_data['items']) && is_array($tx_data['items'])) {
            $rows = $tx_data['items'];
        } elseif (isset($tx_data['data']) && is_array($tx_data['data'])) {
            $rows = $tx_data['data'];
        } elseif (array_keys($tx_data) === range(0, count($tx_data) - 1)) {
            $rows = $tx_data;
        }

        foreach ($rows as $row) {
            if (!is_array($row)) {
                continue;
            }

            $amount = 0.0;
            if (isset($row['usage_units']) && is_numeric($row['usage_units'])) {
                $amount = (float) $row['usage_units'];
            } elseif (isset($row['amount']) && is_numeric($row['amount'])) {
                $amount = (float) $row['amount'];
            } elseif (isset($row['cost']) && is_numeric($row['cost'])) {
                $amount = (float) $row['cost'];
            }

            $created_at = '';
            if (isset($row['created_at'])) {
                $created_at = (string) $row['created_at'];
            } elseif (isset($row['logged_at'])) {
                $created_at = (string) $row['logged_at'];
            }

            $raw_type = sanitize_text_field((string) ($row['type'] ?? ''));
            if ($raw_type !== '' && stripos($raw_type, 'AISmartWPUnit-') !== 0) {
                $raw_type = 'AISmartWPUnit-' . $raw_type;
            }

            $transactions[] = [
                'id' => isset($row['id']) ? (int) $row['id'] : 0,
                'user_id' => isset($row['user_id']) ? (int) $row['user_id'] : 0,
                'type' => $raw_type,
                'platform' => 'wordpress',
                'amount' => $amount,
                'case_log' => sanitize_textarea_field((string) ($row['case_log'] ?? '')),
                'created_at' => sanitize_text_field($created_at),
                'created_at_display' => !empty($created_at)
                    ? mysql2date('Y-m-d H:i', $created_at)
                    : '-',
            ];
        }

        if ($summary['total_logs'] <= 0) {
            if (isset($tx_data['total']) && is_numeric($tx_data['total'])) {
                $summary['total_logs'] = (int) $tx_data['total'];
            } else {
                $summary['total_logs'] = count($transactions);
            }
        }

        if ($summary['unique_users'] <= 0 && !empty($transactions)) {
            $user_ids = [];
            foreach ($transactions as $trow) {
                if (isset($trow['user_id']) && (int) $trow['user_id'] > 0) {
                    $user_ids[(int) $trow['user_id']] = true;
                }
            }
            $summary['unique_users'] = count($user_ids);
        }

        if ($summary['total_amount'] <= 0 && !empty($transactions)) {
            $sum_amount = 0.0;
            foreach ($transactions as $trow) {
                $sum_amount += (float) ($trow['amount'] ?? 0);
            }
            $summary['total_amount'] = $sum_amount;
        }
    }

    if ($summary['total_logs'] <= 0 && $summary['total_amount'] <= 0) {
        $summary_res = aismart_plugin_api_request('GET', 'api/plugin/v1/usage/summary', $base_payload, false);
        if (!is_wp_error($summary_res) && is_array($summary_res)) {
            $ok = true;
            $summary_payload = aismart_plugin_response_data_array($summary_res);
            $summary['total_logs'] = (int) aismart_onboarding_deep_find_scalar($summary_payload, ['total_logs', 'total']);
            $summary['unique_users'] = (int) aismart_onboarding_deep_find_scalar($summary_payload, ['unique_users', 'users_count']);
            $total_usage_units = (float) aismart_onboarding_deep_find_scalar($summary_payload, ['total_usage_units', 'usage_units']);
            $total_cost = (float) aismart_onboarding_deep_find_scalar($summary_payload, ['total_cost', 'cost']);
            $summary['total_amount'] = $total_usage_units > 0 ? $total_usage_units : $total_cost;
        }
    }

    return [
        'ok' => $ok,
        'summary' => $summary,
        'transactions' => $transactions,
        'credit' => $credit,
    ];
}

function aismart_cloud_workspace_usage_snapshot_direct($workspace_id, $limit = 50, $filters = []) {
    $workspace_id = (int) $workspace_id;
    $limit = (int) $limit;
    if ($workspace_id <= 0) {
        return ['ok' => false, 'summary' => ['total_logs' => 0, 'unique_users' => 0, 'total_amount' => 0], 'transactions' => [], 'credit' => ['live' => null, 'quota' => null, 'used' => null, 'updated_at' => '']];
    }

    if ($limit <= 0) {
        $limit = 50;
    }
    if ($limit > 500) {
        $limit = 500;
    }

    $window = aismart_cloud_usage_date_window();
    $state_user_id = (int) aismart_onboarding_resolve_state_user_id();

    $tx_payload = [
        'workspace_id' => $workspace_id,
        'page' => 1,
        'per_page' => $limit,
        'from' => $window['from'],
        'to' => $window['to'],
        'timezone' => $window['timezone'],
    ];
    if ($state_user_id > 0) {
        $tx_payload['user_id'] = $state_user_id;
    }

    if (isset($filters['user_id']) && is_numeric($filters['user_id'])) {
        $uid = (int) $filters['user_id'];
        if ($uid > 0) {
            $tx_payload['user_id'] = $uid;
        }
    }
    if (isset($filters['type']) && is_string($filters['type'])) {
        $type = sanitize_key($filters['type']);
        if ($type !== '' && $type !== 'all') {
            $tx_payload['type'] = $type;
        }
    }
    if (isset($filters['source']) && is_string($filters['source'])) {
        $source = sanitize_key($filters['source']);
        if ($source !== '' && $source !== 'all') {
            $tx_payload['source'] = $source;
        }
    }

    $debug = [
        'endpoint' => 'api/plugin/v1/usage/transactions-compat',
        'request' => $tx_payload,
        'tx_error' => '',
        'tx_response_keys' => [],
        'tx_summary_total' => 0,
        'tx_data_count' => 0,
        'mapped_count' => 0,
        'credit_error' => '',
        'credit_response_keys' => [],
    ];

    $tx_res = aismart_plugin_api_request('GET', 'api/plugin/v1/usage/transactions-compat', $tx_payload, false);
    if (is_wp_error($tx_res)) {
        $tx_res = aismart_plugin_api_request('GET', 'api/plugin/v1/usage/transactions', $tx_payload, false);
        $debug['endpoint'] = 'api/plugin/v1/usage/transactions';
    }

    if (!is_wp_error($tx_res) && is_array($tx_res)) {
        $debug['tx_raw_preview'] = aismart_snapshot_truncate_json($tx_res, 2500);
    }

    $summary = [
        'total_logs' => 0,
        'unique_users' => 0,
        'total_amount' => 0,
    ];
    $transactions = [];
    $ok = false;

    if (!is_wp_error($tx_res) && is_array($tx_res)) {
        $ok = true;
        $debug['tx_response_keys'] = array_values(array_slice(array_keys($tx_res), 0, 15));
        if (isset($tx_res['pagination']['total']) && is_numeric($tx_res['pagination']['total'])) {
            $debug['tx_summary_total'] = (int) $tx_res['pagination']['total'];
        }
        $tx_summary = isset($tx_res['summary']) && is_array($tx_res['summary']) ? $tx_res['summary'] : [];
        if (!empty($tx_summary)) {
            $summary['total_logs'] = (int) aismart_onboarding_deep_find_scalar($tx_summary, ['total_logs', 'total']);
            $summary['unique_users'] = (int) aismart_onboarding_deep_find_scalar($tx_summary, ['unique_users', 'users_count']);
            $total_usage_units = (float) aismart_onboarding_deep_find_scalar($tx_summary, ['total_usage_units', 'usage_units', 'total_amount']);
            $total_cost = (float) aismart_onboarding_deep_find_scalar($tx_summary, ['total_cost', 'cost']);
            $summary['total_amount'] = $total_usage_units > 0 ? $total_usage_units : $total_cost;
        }

        $tx_data = aismart_plugin_response_data_array($tx_res);
        $rows = [];
        if (isset($tx_data['transactions']) && is_array($tx_data['transactions'])) {
            $rows = $tx_data['transactions'];
        } elseif (isset($tx_data['items']) && is_array($tx_data['items'])) {
            $rows = $tx_data['items'];
        } elseif (isset($tx_data['data']) && is_array($tx_data['data'])) {
            $rows = $tx_data['data'];
        } elseif (is_array($tx_data) && array_keys($tx_data) === range(0, count($tx_data) - 1)) {
            $rows = $tx_data;
        }
        $debug['tx_data_count'] = is_array($rows) ? count($rows) : 0;

        foreach ($rows as $row) {
            if (!is_array($row)) {
                continue;
            }

            $amount = 0.0;
            if (isset($row['usage_units']) && is_numeric($row['usage_units'])) {
                $amount = (float) $row['usage_units'];
            } elseif (isset($row['amount']) && is_numeric($row['amount'])) {
                $amount = (float) $row['amount'];
            } elseif (isset($row['cost']) && is_numeric($row['cost'])) {
                $amount = (float) $row['cost'];
            }

            $created_at = '';
            if (isset($row['created_at'])) {
                $created_at = (string) $row['created_at'];
            } elseif (isset($row['logged_at'])) {
                $created_at = (string) $row['logged_at'];
            }

            $raw_type = sanitize_text_field((string) ($row['type'] ?? ''));
            if ($raw_type !== '' && stripos($raw_type, 'AISmartWPUnit-') !== 0) {
                $raw_type = 'AISmartWPUnit-' . $raw_type;
            }

            $transactions[] = [
                'id' => isset($row['id']) ? (int) $row['id'] : 0,
                'user_id' => isset($row['user_id']) ? (int) $row['user_id'] : 0,
                'type' => $raw_type,
                'platform' => 'wordpress',
                'amount' => $amount,
                'case_log' => sanitize_textarea_field((string) ($row['case_log'] ?? '')),
                'created_at' => sanitize_text_field($created_at),
                'created_at_display' => !empty($created_at)
                    ? mysql2date('Y-m-d H:i', $created_at)
                    : '-',
            ];
        }

        if ($summary['total_logs'] <= 0) {
            if (isset($tx_res['pagination']['total']) && is_numeric($tx_res['pagination']['total'])) {
                $summary['total_logs'] = (int) $tx_res['pagination']['total'];
            } else {
                $summary['total_logs'] = count($transactions);
            }
        }
        if ($summary['unique_users'] <= 0 && !empty($transactions)) {
            $unique = [];
            foreach ($transactions as $trow) {
                if (!empty($trow['user_id'])) {
                    $unique[(int) $trow['user_id']] = true;
                }
            }
            $summary['unique_users'] = count($unique);
        }
        if ($summary['total_amount'] <= 0 && !empty($transactions)) {
            $sum_amount = 0.0;
            foreach ($transactions as $trow) {
                $sum_amount += (float) ($trow['amount'] ?? 0);
            }
            $summary['total_amount'] = $sum_amount;
        }
        $debug['mapped_count'] = count($transactions);
    } elseif (is_wp_error($tx_res)) {
        $debug['tx_error'] = $tx_res->get_error_code() . ': ' . $tx_res->get_error_message();
    }

    $credit = ['live' => null, 'quota' => null, 'used' => null, 'updated_at' => ''];
    $credit_payload_req = ['workspace_id' => $workspace_id];
    if (isset($tx_payload['user_id']) && (int) $tx_payload['user_id'] > 0) {
        $credit_payload_req['user_id'] = (int) $tx_payload['user_id'];
    }
    $credit_res = aismart_plugin_api_request('GET', 'api/plugin/v1/credits/balance', $credit_payload_req, false);
    if (!is_wp_error($credit_res) && is_array($credit_res)) {
        $ok = true;
        $debug['credit_response_keys'] = array_values(array_slice(array_keys($credit_res), 0, 15));
        $debug['credit_raw_preview'] = aismart_snapshot_truncate_json($credit_res, 1200);
        $credit_payload = aismart_plugin_response_data_array($credit_res);
        $credit['live'] = (float) aismart_onboarding_deep_find_scalar($credit_payload, ['credit_balance_live', 'credit_balance', 'balance']);
        $credit['quota'] = (float) aismart_onboarding_deep_find_scalar($credit_payload, ['credit_quota', 'quota']);
        $credit['used'] = (float) aismart_onboarding_deep_find_scalar($credit_payload, ['credit_used', 'used']);
        $credit['updated_at'] = sanitize_text_field((string) aismart_onboarding_deep_find_scalar($credit_payload, ['updated_at', 'updatedAt']));
    } elseif (is_wp_error($credit_res)) {
        $debug['credit_error'] = $credit_res->get_error_code() . ': ' . $credit_res->get_error_message();
    }

    return [
        'ok' => $ok,
        'summary' => $summary,
        'transactions' => $transactions,
        'credit' => $credit,
        '_debug' => $debug,
    ];
}

function aismart_get_workspace_usage_snapshot($workspace_id, $limit = 10) {
    global $wpdb;

    $workspace_id = (int) $workspace_id;
    $limit = (int) $limit;
    if ($workspace_id <= 0) {
        return [
            'summary' => [
                'total_logs' => 0,
                'unique_users' => 0,
                'total_amount' => 0,
            ],
            'transactions' => [],
        ];
    }

    if ($limit <= 0) {
        $limit = 50;
    }
    if ($limit > 500) {
        $limit = 500;
    }

    $table = aismart_token_logs_table_name();
    if ($table === '') {
        return [
            'summary' => [
                'total_logs' => 0,
                'unique_users' => 0,
                'total_amount' => 0,
            ],
            'transactions' => [],
        ];
    }

    $summary = [
        'total_logs' => 0,
        'unique_users' => 0,
        'total_amount' => 0,
    ];

    $summary_row = $wpdb->get_row(
        $wpdb->prepare(
            "SELECT COUNT(*) AS total_logs, COUNT(DISTINCT user_id) AS unique_users, COALESCE(SUM(amount), 0) AS total_amount
             FROM {$table}
             WHERE workspace_id = %d",
            $workspace_id
        )
    );

    if ($summary_row) {
        $summary['total_logs'] = (int) ($summary_row->total_logs ?? 0);
        $summary['unique_users'] = (int) ($summary_row->unique_users ?? 0);
        $summary['total_amount'] = (float) ($summary_row->total_amount ?? 0);
    }

    $rows = $wpdb->get_results(
        $wpdb->prepare(
            "SELECT id, user_id, type, platform, amount, case_log, created_at
             FROM {$table}
             WHERE workspace_id = %d
             ORDER BY id DESC
             LIMIT %d",
            $workspace_id,
            $limit
        )
    );

    $transactions = [];
    if (is_array($rows)) {
        foreach ($rows as $row) {
            $raw_type = sanitize_text_field((string) ($row->type ?? ''));
            if ($raw_type !== '' && stripos($raw_type, 'AISmartWPUnit-') !== 0) {
                $raw_type = 'AISmartWPUnit-' . $raw_type;
            }

            $transactions[] = [
                'id' => (int) ($row->id ?? 0),
                'user_id' => (int) ($row->user_id ?? 0),
                'type' => $raw_type,
                'platform' => sanitize_text_field((string) ($row->platform ?? '')),
                'amount' => (float) ($row->amount ?? 0),
                'case_log' => sanitize_textarea_field((string) ($row->case_log ?? '')),
                'created_at' => sanitize_text_field((string) ($row->created_at ?? '')),
                'created_at_display' => !empty($row->created_at)
                    ? mysql2date('Y-m-d H:i', (string) $row->created_at)
                    : '-',
            ];
        }
    }

    return [
        'summary' => $summary,
        'transactions' => $transactions,
    ];
}

function aismart_compute_workspace_live_credit($workspace_id, $quota_hint = 0.0, $limit = 10) {
    $workspace_id = (int) $workspace_id;
    $quota_hint = (float) $quota_hint;
    $limit = (int) $limit;
    if ($limit <= 0) {
        $limit = 10;
    }
    if ($limit > 500) {
        $limit = 500;
    }

    $empty_summary = [
        'total_logs' => 0,
        'unique_users' => 0,
        'total_amount' => 0,
    ];

    if ($workspace_id <= 0) {
        return [
            'live' => max(0.0, $quota_hint),
            'quota' => max(0.0, $quota_hint),
            'used' => 0.0,
            'summary' => $empty_summary,
            'source' => 'none',
        ];
    }

    $local_snapshot = aismart_get_workspace_usage_snapshot($workspace_id, $limit);
    $local_summary = isset($local_snapshot['summary']) && is_array($local_snapshot['summary'])
        ? $local_snapshot['summary']
        : $empty_summary;

    $cloud_snapshot = aismart_cloud_workspace_usage_snapshot_direct($workspace_id, $limit, []);
    $cloud_summary = isset($cloud_snapshot['summary']) && is_array($cloud_snapshot['summary'])
        ? $cloud_snapshot['summary']
        : $empty_summary;

    $cloud_has_payload = ((int) ($cloud_summary['total_logs'] ?? 0) > 0)
        || ((float) ($cloud_summary['total_amount'] ?? 0) > 0)
        || (!empty($cloud_snapshot['transactions']) && is_array($cloud_snapshot['transactions']))
        || ((isset($cloud_snapshot['credit']['updated_at']) && (string) $cloud_snapshot['credit']['updated_at'] !== ''))
        || ((isset($cloud_snapshot['credit']['live']) && $cloud_snapshot['credit']['live'] !== null && (float) $cloud_snapshot['credit']['live'] > 0));

    $source = (!empty($cloud_snapshot['ok']) && $cloud_has_payload) ? 'cloud' : 'local';
    $summary = $source === 'cloud' ? $cloud_summary : $local_summary;

    $summary_used = (float) ($summary['total_amount'] ?? 0);
    $quota = isset($cloud_snapshot['credit']['quota']) && $cloud_snapshot['credit']['quota'] !== null
        ? (float) $cloud_snapshot['credit']['quota']
        : 0.0;
    $used = isset($cloud_snapshot['credit']['used']) && $cloud_snapshot['credit']['used'] !== null
        ? (float) $cloud_snapshot['credit']['used']
        : $summary_used;
    $live = isset($cloud_snapshot['credit']['live']) && $cloud_snapshot['credit']['live'] !== null
        ? (float) $cloud_snapshot['credit']['live']
        : 0.0;

    if ($summary_used > 0 && $used <= 0) {
        $used = $summary_used;
    }

    if ($quota <= 0) {
        $quota = $quota_hint;
    }
    if ($quota <= 0) {
        $quota = (float) get_option('aismart_workspace_credits_' . $workspace_id, 0);
    }
    if ($quota <= 0) {
        $quota = (float) get_option('aismart_credit_balance', 0);
    }

    if ($summary_used > 0 && $quota > 0) {
        $derived_live = max(0.0, $quota - max(0.0, $used));
        if ($live <= 0 || $live >= $quota) {
            $live = $derived_live;
        }
    }

    if ($live <= 0 && $quota > 0 && $used >= 0 && $quota >= $used) {
        $live = max(0.0, $quota - $used);
    }

    if ($live <= 0 && $quota > 0 && $used <= 0) {
        $live = $quota;
    }

    return [
        'live' => max(0.0, (float) $live),
        'quota' => max(0.0, (float) $quota),
        'used' => max(0.0, (float) $used),
        'summary' => $summary,
        'source' => $source,
    ];
}

add_action('wp_ajax_aismart_get_credit_snapshot', 'aismart_get_credit_snapshot');
function aismart_get_credit_snapshot() {
    if (!current_user_can('manage_options')) {
        wp_send_json_error(['message' => 'Unauthorized'], 403);
    }

    $requested_workspace_id = isset($_POST['workspace_id']) ? (int) wp_unslash($_POST['workspace_id']) : 0;
    $limit = isset($_POST['limit']) ? (int) wp_unslash($_POST['limit']) : 10;
    $requested_type = isset($_POST['type']) ? sanitize_key((string) wp_unslash($_POST['type'])) : '';
    $requested_source = isset($_POST['source']) ? sanitize_key((string) wp_unslash($_POST['source'])) : '';
    $requested_user_id = isset($_POST['user_id']) ? (int) wp_unslash($_POST['user_id']) : 0;

    $workspace_options = aismart_workspace_get_available(true);
    $ctx = aismart_resolve_workspace_context();
    $selected_workspace = null;

    $workspace_id = (int) ($ctx['workspace_id'] ?? 0);
    if ($requested_workspace_id > 0) {
        foreach ($workspace_options as $workspace) {
            $wid = isset($workspace['workspace_id']) ? (int) $workspace['workspace_id'] : 0;
            if ($wid !== $requested_workspace_id) {
                continue;
            }

            $selected_workspace = $workspace;
            $workspace_id = $wid;
            update_option('aismart_workspace_id', $workspace_id, false);
            $workspace_name = sanitize_text_field((string) ($workspace['workspace_name'] ?? ('Workspace #' . $workspace_id)));
            update_option('aismart_workspace_name', $workspace_name, false);
            if (isset($workspace['credit_balance']) && is_numeric($workspace['credit_balance'])) {
                update_option('aismart_workspace_credits_' . $workspace_id, (float) $workspace['credit_balance'], false);
                update_option('aismart_credit_balance', (float) $workspace['credit_balance'], false);
                update_option('aismart_credits_available', (float) $workspace['credit_balance'], false);
            }
            $ctx = aismart_resolve_workspace_context();
            break;
        }
    }

    if ($selected_workspace === null && $workspace_id > 0) {
        foreach ($workspace_options as $workspace) {
            $wid = isset($workspace['workspace_id']) ? (int) $workspace['workspace_id'] : 0;
            if ($wid === $workspace_id) {
                $selected_workspace = $workspace;
                break;
            }
        }
    }

    $cloud_snapshot = aismart_cloud_workspace_usage_snapshot_direct($workspace_id, $limit, [
        'type' => $requested_type,
        'source' => $requested_source,
        'user_id' => $requested_user_id,
    ]);

    $cloud_empty = empty($cloud_snapshot['transactions'])
        && (int) ($cloud_snapshot['summary']['total_logs'] ?? 0) <= 0
        && (float) ($cloud_snapshot['summary']['total_amount'] ?? 0) <= 0;

    $direct_rescue_used = false;
    if ($cloud_empty) {
        $window = aismart_cloud_usage_date_window();
        $state_user_id = (int) aismart_onboarding_resolve_state_user_id();
        $direct_payload = [
            'workspace_id' => $workspace_id,
            'page' => 1,
            'per_page' => max(1, min(500, (int) $limit)),
            'from' => $window['from'],
            'to' => $window['to'],
            'timezone' => $window['timezone'],
        ];
        if ($state_user_id > 0) {
            $direct_payload['user_id'] = $state_user_id;
        }
        if ($requested_user_id > 0) {
            $direct_payload['user_id'] = $requested_user_id;
        }
        if ($requested_type !== '' && $requested_type !== 'all') {
            $direct_payload['type'] = $requested_type;
        }
        if ($requested_source !== '' && $requested_source !== 'all') {
            $direct_payload['source'] = $requested_source;
        }

        $direct_res = aismart_plugin_api_request('GET', 'api/plugin/v1/usage/transactions-compat', $direct_payload, false);
        if (!is_wp_error($direct_res) && is_array($direct_res)) {
            $direct_rows = [];
            if (isset($direct_res['data']) && is_array($direct_res['data'])) {
                $direct_rows = $direct_res['data'];
            }

            $mapped_rows = [];
            foreach ($direct_rows as $row) {
                if (!is_array($row)) {
                    continue;
                }
                $amount = 0.0;
                if (isset($row['usage_units']) && is_numeric($row['usage_units'])) {
                    $amount = (float) $row['usage_units'];
                } elseif (isset($row['amount']) && is_numeric($row['amount'])) {
                    $amount = (float) $row['amount'];
                } elseif (isset($row['cost']) && is_numeric($row['cost'])) {
                    $amount = (float) $row['cost'];
                }

                $created_at = isset($row['created_at']) ? (string) $row['created_at'] : (isset($row['logged_at']) ? (string) $row['logged_at'] : '');
                $raw_type = sanitize_text_field((string) ($row['type'] ?? ''));
                if ($raw_type !== '' && stripos($raw_type, 'AISmartWPUnit-') !== 0) {
                    $raw_type = 'AISmartWPUnit-' . $raw_type;
                }

                $mapped_rows[] = [
                    'id' => isset($row['id']) ? (int) $row['id'] : 0,
                    'user_id' => isset($row['user_id']) ? (int) $row['user_id'] : 0,
                    'type' => $raw_type,
                    'platform' => 'wordpress',
                    'amount' => $amount,
                    'case_log' => sanitize_textarea_field((string) ($row['case_log'] ?? '')),
                    'created_at' => sanitize_text_field($created_at),
                    'created_at_display' => !empty($created_at) ? mysql2date('Y-m-d H:i', $created_at) : '-',
                ];
            }

            if (!empty($mapped_rows)) {
                $direct_rescue_used = true;
                $cloud_snapshot['ok'] = true;
                $cloud_snapshot['transactions'] = $mapped_rows;
                $summary_payload = isset($direct_res['summary']) && is_array($direct_res['summary']) ? $direct_res['summary'] : [];
                $cloud_snapshot['summary'] = [
                    'total_logs' => (int) aismart_onboarding_deep_find_scalar($summary_payload, ['total_logs', 'total']),
                    'unique_users' => (int) aismart_onboarding_deep_find_scalar($summary_payload, ['unique_users', 'users_count']),
                    'total_amount' => (float) aismart_onboarding_deep_find_scalar($summary_payload, ['total_usage_units', 'usage_units', 'total_amount', 'total_cost', 'cost']),
                ];
                if ((int) $cloud_snapshot['summary']['total_logs'] <= 0) {
                    $cloud_snapshot['summary']['total_logs'] = count($mapped_rows);
                }
            }
        }
    }

    $usage = [];
    $quota_credit = 0.0;
    $used_credit = 0.0;
    $live_credit = 0.0;

    $local_usage_snapshot = aismart_get_workspace_usage_snapshot($workspace_id, $limit);
    $local_has_payload = ((int) ($local_usage_snapshot['summary']['total_logs'] ?? 0) > 0)
        || ((float) ($local_usage_snapshot['summary']['total_amount'] ?? 0) > 0)
        || (!empty($local_usage_snapshot['transactions']) && is_array($local_usage_snapshot['transactions']));

    $cloud_has_payload = ((int) ($cloud_snapshot['summary']['total_logs'] ?? 0) > 0)
        || ((float) ($cloud_snapshot['summary']['total_amount'] ?? 0) > 0)
        || (!empty($cloud_snapshot['transactions']) && is_array($cloud_snapshot['transactions']))
        || ((isset($cloud_snapshot['credit']['updated_at']) && (string) $cloud_snapshot['credit']['updated_at'] !== ''))
        || ((isset($cloud_snapshot['credit']['live']) && $cloud_snapshot['credit']['live'] !== null && (float) $cloud_snapshot['credit']['live'] > 0));

    if (!empty($cloud_snapshot['ok']) && ($cloud_has_payload || !$local_has_payload)) {
        $usage = [
            'summary' => isset($cloud_snapshot['summary']) && is_array($cloud_snapshot['summary']) ? $cloud_snapshot['summary'] : [
                'total_logs' => 0,
                'unique_users' => 0,
                'total_amount' => 0,
            ],
            'transactions' => isset($cloud_snapshot['transactions']) && is_array($cloud_snapshot['transactions']) ? $cloud_snapshot['transactions'] : [],
        ];

        $credit = isset($cloud_snapshot['credit']) && is_array($cloud_snapshot['credit']) ? $cloud_snapshot['credit'] : [];
        $quota_credit = isset($credit['quota']) && $credit['quota'] !== null ? (float) $credit['quota'] : 0.0;
        $used_credit = isset($credit['used']) && $credit['used'] !== null ? (float) $credit['used'] : (float) ($usage['summary']['total_amount'] ?? 0);
        $live_credit = isset($credit['live']) && $credit['live'] !== null ? (float) $credit['live'] : 0.0;

        $summary_used = (float) ($usage['summary']['total_amount'] ?? 0);
        // Some cloud responses report used/live as 0/full even when usage rows exist.
        // Prefer summary-derived usage when cloud values look stale.
        if ($summary_used > 0 && $used_credit <= 0) {
            $used_credit = $summary_used;
        }

        if ($quota_credit <= 0 && is_array($selected_workspace) && isset($selected_workspace['credit_balance']) && is_numeric($selected_workspace['credit_balance'])) {
            $quota_credit = (float) $selected_workspace['credit_balance'];
        }

        if ($summary_used > 0 && $quota_credit > 0) {
            $derived_live = max(0.0, $quota_credit - max(0.0, $used_credit));
            if ($live_credit <= 0 || $live_credit >= $quota_credit) {
                $live_credit = $derived_live;
            }
        }

        if ($live_credit <= 0 && $quota_credit > 0 && $used_credit >= 0 && $quota_credit >= $used_credit) {
            $live_credit = max(0.0, $quota_credit - $used_credit);
        }
    } else {
        $usage = $local_usage_snapshot;

        if (is_array($selected_workspace) && isset($selected_workspace['credit_balance']) && is_numeric($selected_workspace['credit_balance'])) {
            $quota_credit = (float) $selected_workspace['credit_balance'];
        } else {
            $quota_credit = (float) ($ctx['credit_balance'] ?? 0);
        }

        $used_credit = (float) (($usage['summary']['total_amount'] ?? 0));
        $live_credit = $quota_credit;
        if ($quota_credit > 0 && $used_credit > 0 && $quota_credit >= $used_credit) {
            $live_credit = max(0.0, $quota_credit - $used_credit);
        }
    }

    $debug = [
        'requested' => [
            'workspace_id' => $workspace_id,
            'limit' => $limit,
            'type' => $requested_type,
            'source' => $requested_source,
            'user_id' => $requested_user_id,
        ],
        'selected_source' => (!empty($cloud_snapshot['ok']) && ($cloud_has_payload || !$local_has_payload)) ? 'cloud' : 'local',
        'cloud_ok' => !empty($cloud_snapshot['ok']) ? 1 : 0,
        'cloud_has_payload' => $cloud_has_payload ? 1 : 0,
        'cloud_summary_logs' => (int) ($cloud_snapshot['summary']['total_logs'] ?? 0),
        'cloud_tx_count' => is_array($cloud_snapshot['transactions'] ?? null) ? count($cloud_snapshot['transactions']) : 0,
        'local_has_payload' => $local_has_payload ? 1 : 0,
        'local_summary_logs' => (int) ($local_usage_snapshot['summary']['total_logs'] ?? 0),
        'local_tx_count' => is_array($local_usage_snapshot['transactions'] ?? null) ? count($local_usage_snapshot['transactions']) : 0,
        'direct_rescue_used' => $direct_rescue_used ? 1 : 0,
        'cloud_debug' => isset($cloud_snapshot['_debug']) && is_array($cloud_snapshot['_debug']) ? $cloud_snapshot['_debug'] : [],
    ];

    aismart_snapshot_debug_log('snapshot_result', $debug);

    if (defined('WP_DEBUG') && WP_DEBUG) {
        error_log('AISmart snapshot debug: ' . wp_json_encode($debug));
    }

    wp_send_json_success([
        'workspace_id' => (int) ($ctx['workspace_id'] ?? 0),
        'workspace_label' => (string) ($ctx['workspace_label'] ?? ''),
        'credit_balance' => (float) $live_credit,
        'wp_api_units' => (float) $live_credit,
        'credit_quota' => (float) $quota_credit,
        'credit_used' => (float) $used_credit,
        'workspaces' => $workspace_options,
        'summary' => $usage['summary'],
        'transactions' => $usage['transactions'],
        'debug' => $debug,
    ]);
}

add_action('wp_ajax_aismart_get_settings', 'aismart_get_settings');
function aismart_get_settings() {
    if (!current_user_can('manage_options')) {
        wp_send_json_error(['message' => 'Unauthorized'], 403);
    }

    global $wpdb;

    $auto_blog = (int) get_option('aismart_auto_blog', 0);
    $auto_translate = (int) get_option('aismart_auto_translate', 0);
    $schedule = sanitize_text_field((string) get_option('aismart_schedule_preset', '3-per-day'));
    $schedule_time_daily = aismart_normalize_schedule_clock((string) get_option('aismart_schedule_time_daily', '09:30'), '09:30');
    $schedule_times_three_raw = get_option('aismart_schedule_times_three', '09:30,13:30,19:30');
    $schedule_times_three = aismart_parse_schedule_times_three($schedule_times_three_raw);
    $default_lang_url_mode = aismart_get_default_lang_url_mode();
    $workspace_options = aismart_workspace_get_available(true);
    $ctx = aismart_resolve_workspace_context();
    $workspace_id = (int) $ctx['workspace_id'];
    $workspace_label = (string) $ctx['workspace_label'];
    $credit_balance = (float) $ctx['credit_balance'];
    $credit_runtime = aismart_compute_workspace_live_credit($workspace_id, $credit_balance, 10);
    $credit_balance = isset($credit_runtime['live']) ? (float) $credit_runtime['live'] : $credit_balance;
    $multilang = aismart_onboarding_detect_multilang_provider();
    $provider = sanitize_key((string) ($multilang['primary'] ?? 'none'));
    $translation_conflict_active = aismart_has_polylang_conveythis_conflict();
    $state = aismart_onboarding_state_get();

    $categories = [];
    $category_query_args = [
        'taxonomy' => 'category',
        'hide_empty' => false,
        'orderby' => 'name',
        'order' => 'ASC',
    ];
    // Ask multilingual plugins (Polylang/WPML compatible args) for all language terms.
    $category_query_args['lang'] = '';
    $category_query_args['suppress_filter'] = true;
    $category_terms = get_terms($category_query_args);
    if (!is_wp_error($category_terms) && is_array($category_terms)) {
        foreach ($category_terms as $term) {
            if (!($term instanceof WP_Term)) {
                continue;
            }
            $categories[] = [
                'id' => (int) $term->term_id,
                'name' => sanitize_text_field((string) $term->name),
                'slug' => sanitize_text_field((string) $term->slug),
            ];
        }
    }

    if (empty($categories)) {
        $cat_rows = $wpdb->get_results(
            "SELECT t.term_id, t.name, t.slug
             FROM {$wpdb->terms} t
             INNER JOIN {$wpdb->term_taxonomy} tt ON t.term_id = tt.term_id
             WHERE tt.taxonomy = 'category'
             ORDER BY t.name ASC"
        );
        if (is_array($cat_rows)) {
            foreach ($cat_rows as $row) {
                $categories[] = [
                    'id' => (int) ($row->term_id ?? 0),
                    'name' => sanitize_text_field((string) ($row->name ?? '')),
                    'slug' => sanitize_text_field((string) ($row->slug ?? '')),
                ];
            }
        }
    }

    $tags = [];
    $tag_query_args = [
        'taxonomy' => 'post_tag',
        'hide_empty' => false,
        'orderby' => 'count',
        'order' => 'DESC',
        'number' => 300,
    ];
    $tag_query_args['lang'] = '';
    $tag_query_args['suppress_filter'] = true;
    $tag_terms = get_terms($tag_query_args);
    if (!is_wp_error($tag_terms) && is_array($tag_terms)) {
        $seen_tag_names = [];
        foreach ($tag_terms as $term) {
            if (!($term instanceof WP_Term)) {
                continue;
            }
            $name = sanitize_text_field((string) $term->name);
            if ($name === '') {
                continue;
            }
            $key = function_exists('mb_strtolower') ? mb_strtolower($name) : strtolower($name);
            if (isset($seen_tag_names[$key])) {
                continue;
            }
            $seen_tag_names[$key] = true;
            $tags[] = [
                'id' => (int) $term->term_id,
                'name' => $name,
                'slug' => sanitize_text_field((string) $term->slug),
                'count' => (int) $term->count,
            ];
        }
    }

    if (empty($tags)) {
        $tag_rows = $wpdb->get_results(
            "SELECT t.term_id, t.name, t.slug, tt.count
             FROM {$wpdb->terms} t
             INNER JOIN {$wpdb->term_taxonomy} tt ON t.term_id = tt.term_id
             WHERE tt.taxonomy = 'post_tag'
             ORDER BY tt.count DESC, t.name ASC
             LIMIT 300"
        );
        if (is_array($tag_rows)) {
            $seen_tag_names = [];
            foreach ($tag_rows as $row) {
                $name = sanitize_text_field((string) ($row->name ?? ''));
                if ($name === '') {
                    continue;
                }
                $key = function_exists('mb_strtolower') ? mb_strtolower($name) : strtolower($name);
                if (isset($seen_tag_names[$key])) {
                    continue;
                }
                $seen_tag_names[$key] = true;
                $tags[] = [
                    'id' => (int) ($row->term_id ?? 0),
                    'name' => $name,
                    'slug' => sanitize_text_field((string) ($row->slug ?? '')),
                    'count' => (int) ($row->count ?? 0),
                ];
            }
        }
    }

    $member_word_remaining = isset($state['member_word_remaining']) && is_numeric($state['member_word_remaining'])
        ? (float) $state['member_word_remaining']
        : null;
    $member_image_remaining = isset($state['member_image_remaining']) && is_numeric($state['member_image_remaining'])
        ? (float) $state['member_image_remaining']
        : null;
    $credit_summary_parts = [];
    $credit_summary_parts[] = 'WP API Units left: ' . number_format_i18n($credit_balance, 0);
    if ($member_image_remaining !== null) {
        $credit_summary_parts[] = 'Image credits (reference): ' . number_format_i18n($member_image_remaining, 0);
    }
    if ($member_word_remaining !== null) {
        $credit_summary_parts[] = 'Text credits (reference): ' . number_format_i18n($member_word_remaining, 0);
    }
    $credit_summary = implode(' | ', $credit_summary_parts);

    global $wpdb;
    $languages = [];
    if ($provider === 'falang' || function_exists('falang_languages_list') || class_exists('Falang', false)) {
        if (function_exists('falang_languages_list')) {
            $falang_languages = (array) falang_languages_list(['hide_empty' => false]);
            foreach ($falang_languages as $language) {
                $code = '';
                $name = '';

                if (is_object($language)) {
                    $code = isset($language->locale) ? (string) $language->locale : (isset($language->slug) ? (string) $language->slug : '');
                    $name = isset($language->name) ? (string) $language->name : '';
                } elseif (is_array($language)) {
                    $code = isset($language['locale']) ? (string) $language['locale'] : (isset($language['slug']) ? (string) $language['slug'] : '');
                    $name = isset($language['name']) ? (string) $language['name'] : '';
                } elseif (is_string($language)) {
                    $code = $language;
                    $name = $language;
                }

                $code = sanitize_text_field($code);
                if ($code === '') {
                    continue;
                }

                $languages[] = [
                    'code' => $code,
                    'name' => $name !== '' ? sanitize_text_field($name) : $code,
                ];
            }
        }

        if (empty($languages) && taxonomy_exists('language')) {
            $terms = get_terms([
                'taxonomy' => 'language',
                'hide_empty' => false,
            ]);

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

                    $code = sanitize_text_field((string) $term->slug);
                    if ($code === '') {
                        continue;
                    }

                    $languages[] = [
                        'code' => $code,
                        'name' => sanitize_text_field((string) ($term->name ?: $code)),
                    ];
                }
            }
        }
    } elseif (
        $provider === 'sublanguage'
        || class_exists('Sublanguage_core', false)
        || class_exists('Sublanguage_site', false)
        || class_exists('Sublanguage_admin', false)
        || isset($GLOBALS['sublanguage'])
    ) {
        $lang_posts = get_posts([
            'post_type' => 'language',
            'post_status' => ['publish', 'draft'],
            'posts_per_page' => -1,
            'orderby' => 'menu_order',
            'order' => 'ASC',
            'suppress_filters' => true,
        ]);

        if (is_array($lang_posts)) {
            foreach ($lang_posts as $lang_post) {
                if (!($lang_post instanceof WP_Post)) {
                    continue;
                }

                $code = strtolower(sanitize_text_field((string) $lang_post->post_name));
                if ($code === '') {
                    continue;
                }

                $name = sanitize_text_field((string) $lang_post->post_title);
                if ($name === '') {
                    $name = strtoupper($code);
                }

                $languages[] = [
                    'code' => $code,
                    'name' => $name,
                ];
            }
        }
    } elseif (function_exists('pll_languages_list')) {
        $codes = pll_languages_list();
        $names = pll_languages_list(['fields' => 'name']);
        if (is_array($codes)) {
            foreach ($codes as $index => $code) {
                $name = is_array($names) && isset($names[$index]) ? $names[$index] : $code;
                $languages[] = [
                    'code' => (string) $code,
                    'name' => (string) $name,
                ];
            }
        }
    } elseif (function_exists('trp_get_languages') || defined('TRP_PLUGIN_VERSION')) {
        $trp_languages = [];

        if (function_exists('trp_get_languages')) {
            $trp_languages = (array) trp_get_languages();
        }

        if (empty($trp_languages)) {
            $trp_settings = get_option('trp_settings', []);
            $trp_codes = [];
            if (is_array($trp_settings) && !empty($trp_settings['translation-languages']) && is_array($trp_settings['translation-languages'])) {
                $trp_codes = $trp_settings['translation-languages'];
            }
            foreach ($trp_codes as $code) {
                $code = sanitize_text_field((string) $code);
                if ($code === '') {
                    continue;
                }
                $trp_languages[$code] = $code;
            }
        }

        foreach ($trp_languages as $code => $name) {
            if (is_int($code)) {
                $code = (string) $name;
            }
            $code = sanitize_text_field((string) $code);
            if ($code === '') {
                continue;
            }
            $label = is_scalar($name) ? (string) $name : $code;
            if ($label === '') {
                $label = $code;
            }

            $languages[] = [
                'code' => $code,
                'name' => $label,
            ];
        }

        if (!empty($languages)) {
            $languages = array_values(array_map('unserialize', array_unique(array_map('serialize', $languages))));
        }
    } elseif (
        defined('QTX_VERSION')
        || function_exists('qtranxf_getSortedLanguages')
        || function_exists('qtrans_getSortedLanguages')
        || function_exists('qtrans_getLanguage')
    ) {
        $enabled = get_option('qtranslate_enabled_languages', []);
        if (!is_array($enabled)) {
            $enabled = [];
        }

        if (empty($enabled)) {
            $cfg_enabled = [];
            if (!empty($GLOBALS['q_config']) && is_array($GLOBALS['q_config']) && !empty($GLOBALS['q_config']['enabled_languages']) && is_array($GLOBALS['q_config']['enabled_languages'])) {
                $cfg_enabled = (array) $GLOBALS['q_config']['enabled_languages'];
            }
            if (!empty($cfg_enabled)) {
                $enabled = $cfg_enabled;
            }
        }

        $names = get_option('qtranslate_language_names', []);
        $locales = get_option('qtranslate_locales', []);
        if (!is_array($names)) {
            $names = [];
        }
        if (!is_array($locales)) {
            $locales = [];
        }

        foreach ((array) $enabled as $code_raw) {
            $code = sanitize_text_field((string) $code_raw);
            if ($code === '') {
                continue;
            }

            $label = '';
            if (isset($names[$code]) && is_scalar($names[$code])) {
                $label = (string) $names[$code];
            } elseif (isset($locales[$code]) && is_scalar($locales[$code])) {
                $label = (string) $locales[$code];
            }

            if ($label === '') {
                $label = strtoupper(str_replace('-', '_', $code));
            }

            $languages[] = [
                'code' => $code,
                'name' => sanitize_text_field($label),
            ];
        }

        if (empty($languages) && !empty($GLOBALS['q_config']) && is_array($GLOBALS['q_config'])) {
            $cfg_enabled = !empty($GLOBALS['q_config']['enabled_languages']) && is_array($GLOBALS['q_config']['enabled_languages'])
                ? (array) $GLOBALS['q_config']['enabled_languages']
                : [];
            foreach ($cfg_enabled as $code_raw) {
                $code = sanitize_text_field((string) $code_raw);
                if ($code === '') {
                    continue;
                }
                $label = '';
                if (!empty($GLOBALS['q_config']['language_name'][$code])) {
                    $label = (string) $GLOBALS['q_config']['language_name'][$code];
                } elseif (!empty($GLOBALS['q_config']['locale'][$code])) {
                    $label = (string) $GLOBALS['q_config']['locale'][$code];
                }
                if ($label === '') {
                    $label = strtoupper(str_replace('-', '_', $code));
                }
                $languages[] = [
                    'code' => $code,
                    'name' => sanitize_text_field($label),
                ];
            }
        }
    } elseif (
        $provider === 'multilingualpress'
        || is_multisite()
            && (
                is_plugin_active('multilingual-press/multilingual-press.php')
                || is_plugin_active_for_network('multilingual-press/multilingual-press.php')
                || is_plugin_active('multilingual-press/multilingualpress.php')
                || is_plugin_active_for_network('multilingual-press/multilingualpress.php')
                || is_plugin_active('multilingualpress/multilingualpress.php')
                || is_plugin_active_for_network('multilingualpress/multilingualpress.php')
            )
    ) {
        $mlp_sites = (array) get_site_option('inpsyde_multilingual', []);
        $name_by_code = [
            'en' => 'English',
            'th' => 'Thai',
            'ja' => 'Japanese',
        ];

        foreach ($mlp_sites as $site_id => $site_lang) {
            if (!is_array($site_lang)) {
                continue;
            }

            $raw_locale = sanitize_text_field((string) ($site_lang['lang'] ?? ''));
            if ($raw_locale === '' || $raw_locale === '-1') {
                continue;
            }

            $code = aismart_mlp_lang_code_from_locale($raw_locale);
            if ($code === '') {
                continue;
            }

            $label = sanitize_text_field((string) ($site_lang['text'] ?? ''));
            if ($label === '') {
                $label = $name_by_code[$code] ?? strtoupper(str_replace('-', '_', $code));
            }

            $languages[] = [
                'code' => $code,
                'name' => $label,
            ];
        }
    } elseif (
        $provider === 'bogo'
        || function_exists('bogo_available_languages')
        || class_exists('Bogo', false)
    ) {
        $bogo_languages = [];
        if (function_exists('bogo_available_languages')) {
            $bogo_languages = (array) bogo_available_languages([
                'orderby' => 'key',
                'order' => 'ASC',
                'exclude_enus_if_inactive' => true,
            ]);
        }

        foreach ($bogo_languages as $locale => $name) {
            $locale = sanitize_text_field((string) $locale);
            if ($locale === '') {
                continue;
            }

            $code = aismart_bogo_locale_to_lang_code($locale);
            if ($code === '') {
                continue;
            }

            $label = is_scalar($name) ? (string) $name : '';
            if ($label === '') {
                $label = strtoupper(str_replace('-', '_', $code));
            }

            $languages[] = [
                'code' => $code,
                'name' => sanitize_text_field($label),
            ];
        }

        if (empty($languages) && function_exists('bogo_available_locales')) {
            $bogo_locales = (array) bogo_available_locales([
                'exclude_enus_if_inactive' => true,
            ]);

            foreach ($bogo_locales as $locale) {
                $locale = sanitize_text_field((string) $locale);
                if ($locale === '') {
                    continue;
                }

                $code = aismart_bogo_locale_to_lang_code($locale);
                if ($code === '') {
                    continue;
                }

                $languages[] = [
                    'code' => $code,
                    'name' => strtoupper(str_replace('-', '_', $code)),
                ];
            }
        }
    } elseif (
        $provider === 'wpglobus'
        || class_exists('WPGlobus', false)
        || defined('WPGLOBUS_VERSION')
    ) {
        $wpglobus_option = get_option('wpglobus_option', []);
        $enabled_raw = is_array($wpglobus_option) && isset($wpglobus_option['enabled_languages']) && is_array($wpglobus_option['enabled_languages'])
            ? (array) $wpglobus_option['enabled_languages']
            : [];

        $english_names = get_option('wpglobus_option_en_language_names', []);
        $native_names = get_option('wpglobus_option_language_names', []);
        if (!is_array($english_names)) {
            $english_names = [];
        }
        if (!is_array($native_names)) {
            $native_names = [];
        }

        foreach ($enabled_raw as $lang_key => $lang_value) {
            $code = is_string($lang_key) ? $lang_key : (string) $lang_value;
            $code = strtolower(sanitize_text_field($code));
            if ($code === '') {
                continue;
            }

            if (empty($lang_value) && !is_string($lang_key)) {
                continue;
            }

            $label = '';
            if (!empty($english_names[$code]) && is_scalar($english_names[$code])) {
                $label = (string) $english_names[$code];
            } elseif (!empty($native_names[$code]) && is_scalar($native_names[$code])) {
                $label = (string) $native_names[$code];
            }
            if ($label === '') {
                $label = strtoupper(str_replace('-', '_', $code));
            }

            $languages[] = [
                'code' => $code,
                'name' => sanitize_text_field($label),
            ];
        }
    } else {
        $languages_table = $wpdb->prefix . 'icl_languages';
        $languages_exists = $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $languages_table));
        if ($languages_exists) {
            $rows = $wpdb->get_results("SELECT code, english_name FROM {$languages_table} WHERE active = 1");
            foreach ($rows as $row) {
                $languages[] = [
                    'code' => (string) $row->code,
                    'name' => (string) ($row->english_name ?: $row->code),
                ];
            }
        }
    }

    if (!empty($languages)) {
        $languages = array_values(array_map('unserialize', array_unique(array_map('serialize', $languages))));
    }

    $migration_active = aismart_detect_active_provider_key();
    $migration_source = aismart_guess_previous_provider_key($migration_active);
    $migration_last_run = get_option('aismart_migration_bridge_last_run', []);
    if (!is_array($migration_last_run)) {
        $migration_last_run = [];
    }

    $site_timezone_name = function_exists('wp_timezone_string') ? (string) wp_timezone_string() : '';
    if ($site_timezone_name === '') {
        $site_timezone_name = (string) get_option('timezone_string', '');
    }
    if ($site_timezone_name === '') {
        $site_timezone_name = 'UTC';
    }
    $site_gmt_offset = (float) get_option('gmt_offset', 0);
    $site_timezone_label = $site_timezone_name;
    if ($site_gmt_offset >= 0) {
        $site_timezone_label .= ' (UTC+' . rtrim(rtrim(number_format($site_gmt_offset, 2, '.', ''), '0'), '.') . ')';
    } else {
        $site_timezone_label .= ' (UTC' . rtrim(rtrim(number_format($site_gmt_offset, 2, '.', ''), '0'), '.') . ')';
    }

    wp_send_json_success([
        'auto_blog' => $auto_blog ? 1 : 0,
        'auto_translate' => $auto_translate ? 1 : 0,
        'schedule' => $schedule,
        'schedule_time_daily' => $schedule_time_daily,
        'schedule_times_three' => $schedule_times_three,
        'default_lang_url_mode' => $default_lang_url_mode,
        'languages' => $languages,
        'multilang_provider' => $provider,
        'multilang_detected' => (array) ($multilang['detected'] ?? []),
        'workspace_id' => $workspace_id,
        'workspace_label' => $workspace_label,
        'credit_balance' => $credit_balance,
        'wp_api_units' => $credit_balance,
        'credit_summary' => $credit_summary,
        'member_word_remaining' => $member_word_remaining,
        'member_image_remaining' => $member_image_remaining,
        'workspaces' => $workspace_options,
        'categories' => $categories,
        'tags' => $tags,
        'site_timezone' => $site_timezone_name,
        'site_timezone_label' => $site_timezone_label,
        'site_gmt_offset' => $site_gmt_offset,
        'translation_conflict' => [
            'active' => $translation_conflict_active ? 1 : 0,
            'message' => $translation_conflict_active
                ? 'Polylang and ConveyThis are both active. This can cause language redirect loops. Deactivate ConveyThis (or keep only one multilingual plugin) before queuing new translations.'
                : '',
        ],
        'migration_providers' => aismart_get_supported_provider_options(),
        'migration_active_provider' => $migration_active,
        'migration_suggested_source' => $migration_source,
        'migration_last_run' => $migration_last_run,
    ]);
}

function aismart_normalize_schedule_clock($value, $fallback = '09:30') {
    $value = sanitize_text_field((string) $value);
    if (preg_match('/^([01]?\d|2[0-3]):([0-5]\d)$/', $value, $m)) {
        return str_pad((string) $m[1], 2, '0', STR_PAD_LEFT) . ':' . $m[2];
    }

    return $fallback;
}

function aismart_parse_schedule_times_three($raw) {
    $defaults = ['09:30', '13:30', '19:30'];
    $times = [];

    if (is_array($raw)) {
        foreach ($raw as $entry) {
            $times[] = sanitize_text_field((string) $entry);
        }
    } else {
        $raw = sanitize_text_field((string) $raw);
        $parts = array_map('trim', explode(',', $raw));
        foreach ($parts as $entry) {
            if ($entry !== '') {
                $times[] = $entry;
            }
        }
    }

    $normalized = [];
    foreach ($times as $entry) {
        if (preg_match('/^([01]?\d|2[0-3]):([0-5]\d)$/', (string) $entry, $m)) {
            $normalized[] = str_pad((string) $m[1], 2, '0', STR_PAD_LEFT) . ':' . $m[2];
        }
    }

    $normalized = array_values(array_unique($normalized));
    for ($i = 0; $i < 3; $i++) {
        if (!isset($normalized[$i])) {
            $normalized[$i] = $defaults[$i];
        }
    }

    return array_slice($normalized, 0, 3);
}

function aismart_auto_blog_due_slot_now() {
    $enabled = (int) get_option('aismart_auto_blog', 0);
    if ($enabled !== 1) {
        return null;
    }

    $schedule = sanitize_text_field((string) get_option('aismart_schedule_preset', '3-per-day'));
    if (!in_array($schedule, ['1-per-day', '3-per-day', '5-per-week'], true)) {
        $schedule = '3-per-day';
    }

    $daily_time = aismart_normalize_schedule_clock((string) get_option('aismart_schedule_time_daily', '09:30'), '09:30');
    $times_three = aismart_parse_schedule_times_three((string) get_option('aismart_schedule_times_three', '09:30,13:30,19:30'));

    $tz = function_exists('wp_timezone') ? wp_timezone() : new DateTimeZone('UTC');
    $now = new DateTime('now', $tz);
    $hhmm = $now->format('H:i');
    $date_key = $now->format('Y-m-d');
    $weekday = (int) $now->format('N');

    $allowed_times = [];
    if ($schedule === '1-per-day') {
        $allowed_times[] = $daily_time;
    } elseif ($schedule === '3-per-day') {
        $allowed_times = $times_three;
    } else {
        if ($weekday <= 5) {
            $allowed_times[] = $daily_time;
        }
    }

    if (!in_array($hhmm, $allowed_times, true)) {
        return null;
    }

    return [
        'slot_key' => $date_key . '|' . $schedule . '|' . $hhmm,
        'date' => $date_key,
        'time' => $hhmm,
        'schedule' => $schedule,
    ];
}

function aismart_auto_blog_pick_next_queue_topic() {
    $items = aismart_topic_queue_get_items();
    if (!is_array($items) || empty($items)) {
        return null;
    }

    foreach ($items as $index => $item) {
        if (!is_array($item)) {
            continue;
        }

        $title = aismart_topic_queue_normalize_title($item['title'] ?? '');
        if ($title === '') {
            continue;
        }

        if (!empty($item['written'])) {
            continue;
        }

        return [
            'queue_id' => (int) $index + 1,
            'title' => $title,
        ];
    }

    return null;
}

function aismart_auto_blog_resolve_author_id() {
    $current = (int) get_current_user_id();
    if ($current > 0) {
        return $current;
    }

    $admin_users = get_users([
        'role' => 'administrator',
        'number' => 1,
        'fields' => ['ID'],
        'orderby' => 'ID',
        'order' => 'ASC',
    ]);
    if (is_array($admin_users) && !empty($admin_users[0]->ID)) {
        return (int) $admin_users[0]->ID;
    }

    return 1;
}

function aismart_auto_blog_create_post_from_queue_topic($topic, $queue_id = 0) {
    global $wpdb;

    $topic = aismart_topic_queue_normalize_title($topic);
    if ($topic === '') {
        return new WP_Error('empty_topic', 'Queue topic is empty');
    }

    if (aismart_get_current_workspace_credit_balance() <= 0) {
        return new WP_Error('no_credit', 'Workspace has no credits');
    }

    aismart_require_media_includes();

    $api_result = aismart_request_posts_api([
        'site' => 'site2',
        'topic' => $topic,
        'skip_image' => 0,
        'image_prompt' => aismart_build_image_prompt($topic, 'Auto', '', ''),
    ], 60);

    $used_local_fallback = false;
    $fallback_reason = '';
    if (empty($api_result['ok'])) {
        $data = aismart_build_local_fallback_post_data($topic, '');
        $used_local_fallback = true;
        $fallback_reason = !empty($api_result['message']) ? (string) $api_result['message'] : 'posts-api-failed';
    } else {
        $data = (array) $api_result['data'];
    }

    $resolved_title = aismart_normalize_post_title((string) ($data['title'] ?? $topic));
    if ($resolved_title === '') {
        $resolved_title = $topic;
    }

    $target_post_id = (int) $wpdb->get_var(
        $wpdb->prepare(
            "SELECT ID FROM {$wpdb->posts}
             WHERE post_type = 'post'
               AND post_status IN ('draft','publish','pending','future','private')
               AND post_title = %s
             ORDER BY ID DESC
             LIMIT 1",
            $resolved_title
        )
    );

    $post_content = aismart_cleanup_translated_post_content((string) ($data['content'] ?? ''));
    $post_excerpt = wp_trim_words(wp_strip_all_tags($post_content), 40, '...');
    $post_data = [
        'post_title' => $resolved_title,
        'post_content' => $post_content,
        'post_excerpt' => $post_excerpt,
        'post_status' => 'publish',
        'post_author' => aismart_auto_blog_resolve_author_id(),
        'post_type' => 'post',
    ];

    if ($target_post_id > 0) {
        $post_data['ID'] = $target_post_id;
        $post_id = wp_update_post($post_data, true);
    } else {
        $post_id = wp_insert_post($post_data, true);
    }
    if (is_wp_error($post_id) || (int) $post_id <= 0) {
        return new WP_Error('insert_failed', is_wp_error($post_id) ? $post_id->get_error_message() : 'Failed to create post');
    }

    $provider = aismart_resolve_selected_provider_key();
    if ($provider !== '') {
        update_post_meta((int) $post_id, '_aismart_created_provider', $provider);
        update_post_meta((int) $post_id, '_aismart_last_multilang_provider', $provider);
    }

    update_post_meta((int) $post_id, '_aismart_generated_post', 1);
    update_post_meta((int) $post_id, '_aismart_generated_at', gmdate('c'));
    if ($used_local_fallback) {
        update_post_meta((int) $post_id, '_aismart_local_fallback', 1);
        if ($fallback_reason !== '') {
            update_post_meta((int) $post_id, '_aismart_local_fallback_reason', sanitize_text_field($fallback_reason));
        }
    } else {
        delete_post_meta((int) $post_id, '_aismart_local_fallback');
        delete_post_meta((int) $post_id, '_aismart_local_fallback_reason');
    }

    $category_name = 'Auto';
    $category_slug = sanitize_title($category_name);
    $category_term = get_term_by('slug', $category_slug, 'category');
    if (!$category_term) {
        $category_term = get_term_by('name', $category_name, 'category');
    }
    if (!$category_term || is_wp_error($category_term)) {
        $created_category = wp_insert_term($category_name, 'category', ['slug' => $category_slug]);
        if (!is_wp_error($created_category) && !empty($created_category['term_id'])) {
            $category_term = get_term((int) $created_category['term_id'], 'category');
        }
    }
    if ($category_term && !is_wp_error($category_term)) {
        wp_set_post_categories((int) $post_id, [(int) $category_term->term_id], false);
    }

    $image_url = isset($data['image_url']) ? (string) $data['image_url'] : '';
    if ($image_url === '' && isset($data['featured_image'])) {
        $image_url = (string) $data['featured_image'];
    }
    if ($image_url === '' || !filter_var($image_url, FILTER_VALIDATE_URL)) {
        $image_url = aismart_build_backup_image_url($resolved_title, $category_name, '', $post_excerpt);
    }
    if ($image_url !== '' && filter_var($image_url, FILTER_VALIDATE_URL)) {
        aismart_attach_featured_image_from_url((int) $post_id, $image_url, 'Generated image for ' . $resolved_title);
    }

    $queue_marked = false;
    if ((int) $queue_id > 0) {
        $queue_marked = aismart_topic_queue_mark_written_by_queue_id((int) $queue_id, (int) $post_id, $provider);
    }
    if (!$queue_marked) {
        aismart_topic_queue_mark_written($topic, (int) $post_id, $provider);
    }

    if ((function_exists('mb_strtolower') ? mb_strtolower($resolved_title) : strtolower($resolved_title)) !== (function_exists('mb_strtolower') ? mb_strtolower($topic) : strtolower($topic))) {
        aismart_topic_queue_mark_written($resolved_title, (int) $post_id, $provider);
    }

    return [
        'post_id' => (int) $post_id,
        'title' => $resolved_title,
        'fallback' => $used_local_fallback ? 1 : 0,
        'fallback_reason' => $fallback_reason,
    ];
}

function aismart_auto_blog_maybe_run($source = 'cron') {
    static $running = false;
    if ($running) {
        return;
    }
    $running = true;

    try {
        $due = aismart_auto_blog_due_slot_now();
        if (!is_array($due) || empty($due['slot_key'])) {
            return;
        }

        $slot_key = sanitize_text_field((string) $due['slot_key']);
        $last_slot_key = sanitize_text_field((string) get_option('aismart_auto_blog_last_slot_key', ''));
        if ($slot_key !== '' && $slot_key === $last_slot_key) {
            return;
        }

        if (get_transient('aismart_auto_blog_worker_lock')) {
            return;
        }
        set_transient('aismart_auto_blog_worker_lock', 1, 55);

        try {
            $next = aismart_auto_blog_pick_next_queue_topic();
            if (!is_array($next) || empty($next['title'])) {
                if (function_exists('aismart_queue_log')) {
                    aismart_queue_log('Auto-blog skip: no pending queue topic for slot=' . $slot_key . ' source=' . sanitize_key((string) $source));
                }
            } else {
                $result = aismart_auto_blog_create_post_from_queue_topic((string) $next['title'], (int) ($next['queue_id'] ?? 0));
                if (is_wp_error($result)) {
                    if (function_exists('aismart_queue_log')) {
                        aismart_queue_log(
                            'Auto-blog failed slot=' . $slot_key
                            . ' source=' . sanitize_key((string) $source)
                            . ' topic=' . sanitize_text_field((string) $next['title'])
                            . ' error=' . sanitize_text_field($result->get_error_message())
                        );
                    }
                } else {
                    if (function_exists('aismart_queue_log')) {
                        aismart_queue_log(
                            'Auto-blog created slot=' . $slot_key
                            . ' source=' . sanitize_key((string) $source)
                            . ' topic=' . sanitize_text_field((string) ($next['title'] ?? ''))
                            . ' post_id=' . (int) ($result['post_id'] ?? 0)
                            . ' fallback=' . (int) ($result['fallback'] ?? 0)
                        );
                    }
                }
            }

            update_option('aismart_auto_blog_last_slot_key', $slot_key, false);
            update_option('aismart_auto_blog_last_run', [
                'slot_key' => $slot_key,
                'ran_at' => gmdate('c'),
                'source' => sanitize_key((string) $source),
            ], false);
        } finally {
            delete_transient('aismart_auto_blog_worker_lock');
        }
    } finally {
        $running = false;
    }
}

add_action('aismart_auto_blog_cron_event', 'aismart_auto_blog_cron_event_handler');
function aismart_auto_blog_cron_event_handler() {
    aismart_auto_blog_maybe_run('cron');
}

function aismart_repair_missed_schedule_worker($source = 'cron') {
    static $running = false;
    if ($running) {
        return;
    }

    if (get_transient('aismart_missed_schedule_repair_lock')) {
        return;
    }

    $running = true;
    set_transient('aismart_missed_schedule_repair_lock', 1, 55);

    try {
        $now_gmt = current_time('timestamp', true);
        $publish_hook = 'publish_future_post';
        $window_seconds = 120;
        $batch_limit = 20;

        $query = new WP_Query([
            'post_type' => 'any',
            'post_status' => 'future',
            'posts_per_page' => $batch_limit,
            'orderby' => 'date',
            'order' => 'ASC',
            'fields' => 'ids',
            'no_found_rows' => true,
            'cache_results' => false,
            'update_post_meta_cache' => false,
            'update_post_term_cache' => false,
        ]);

        if (empty($query->posts) || !is_array($query->posts)) {
            return;
        }

        $published = 0;
        $requeued = 0;

        foreach ($query->posts as $post_id) {
            $post_id = (int) $post_id;
            if ($post_id <= 0) {
                continue;
            }

            $post = get_post($post_id);
            if (!$post || $post->post_status !== 'future') {
                continue;
            }

            $gmt_date = (string) $post->post_date_gmt;
            if ($gmt_date === '' || $gmt_date === '0000-00-00 00:00:00') {
                $gmt_date = get_gmt_from_date((string) $post->post_date);
            }

            if ($gmt_date === '' || $gmt_date === '0000-00-00 00:00:00') {
                continue;
            }

            $target_ts = strtotime($gmt_date . ' GMT');
            if (!$target_ts) {
                continue;
            }

            $args = [$post_id];
            $scheduled_ts = wp_next_scheduled($publish_hook, $args);

            if ($target_ts <= ($now_gmt - 30)) {
                if ($scheduled_ts) {
                    wp_clear_scheduled_hook($publish_hook, $args);
                }

                wp_publish_post($post_id);
                $published++;
                continue;
            }

            if ($target_ts <= ($now_gmt + $window_seconds)) {
                if (!$scheduled_ts || abs((int) $scheduled_ts - (int) $target_ts) > $window_seconds) {
                    if ($scheduled_ts) {
                        wp_clear_scheduled_hook($publish_hook, $args);
                    }
                    wp_schedule_single_event($target_ts, $publish_hook, $args);
                    $requeued++;
                }
            }
        }

        if (($published > 0 || $requeued > 0) && function_exists('aismart_queue_log')) {
            aismart_queue_log(
                'Missed-schedule repair source=' . sanitize_key((string) $source)
                . ' published=' . (int) $published
                . ' requeued=' . (int) $requeued
            );
        }
    } finally {
        delete_transient('aismart_missed_schedule_repair_lock');
        $running = false;
    }
}

add_action('aismart_repair_missed_schedule_event', 'aismart_repair_missed_schedule_cron_handler');
function aismart_repair_missed_schedule_cron_handler() {
    aismart_repair_missed_schedule_worker('cron');
}

add_action('init', 'aismart_auto_blog_inline_event_handler', 50);
function aismart_auto_blog_inline_event_handler() {
    if (defined('DOING_CRON') && DOING_CRON) {
        return;
    }
    aismart_auto_blog_maybe_run('inline');
}

add_action('wp_ajax_aismart_switch_workspace', 'aismart_switch_workspace');
function aismart_switch_workspace() {
    if (!current_user_can('manage_options')) {
        wp_send_json_error(['message' => 'Unauthorized'], 403);
    }

    $workspace_id = isset($_POST['workspace_id']) ? (int) $_POST['workspace_id'] : 0;
    if ($workspace_id <= 0) {
        wp_send_json_error(['message' => 'Invalid workspace id'], 422);
    }

    $workspaces = aismart_workspace_get_available(true);
    $selected = null;
    foreach ($workspaces as $workspace) {
        if ((int) ($workspace['workspace_id'] ?? 0) === $workspace_id) {
            $selected = $workspace;
            break;
        }
    }

    if (!$selected) {
        wp_send_json_error(['message' => 'Workspace not found for this account'], 404);
    }

    $workspace_name = sanitize_text_field((string) ($selected['workspace_name'] ?? ('Workspace #' . $workspace_id)));
    update_option('aismart_workspace_id', $workspace_id, false);
    update_option('aismart_workspace_name', $workspace_name, false);

    if (isset($selected['credit_balance']) && is_numeric($selected['credit_balance'])) {
        update_option('aismart_workspace_credits_' . $workspace_id, (float) $selected['credit_balance'], false);
        update_option('aismart_credit_balance', (float) $selected['credit_balance'], false);
        update_option('aismart_credits_available', (float) $selected['credit_balance'], false);
    }

    $state = aismart_onboarding_state_get();
    if (!is_array($state)) {
        $state = [];
    }
    $state['workspace_id'] = $workspace_id;
    $state['workspace_name'] = $workspace_name;
    $state['workspace_switched_at'] = gmdate('c');
    aismart_onboarding_state_set($state);

    $ctx = aismart_resolve_workspace_context();
    wp_send_json_success([
        'message' => 'Workspace switched',
        'workspace_id' => (int) $ctx['workspace_id'],
        'workspace_label' => (string) $ctx['workspace_label'],
        'credit_balance' => (float) $ctx['credit_balance'],
        'workspaces' => $workspaces,
    ]);
}

// AJAX: Update automation settings
add_action('wp_ajax_aismart_update_settings', 'aismart_update_settings');
function aismart_update_settings() {
    if (!current_user_can('manage_options')) {
        error_log('AISmart Update Settings: Unauthorized access attempt');
        wp_send_json_error(['message' => 'Unauthorized'], 403);
    }

    $auto_blog_val = isset($_POST['auto_blog']) ? wp_unslash($_POST['auto_blog']) : 0;
    $auto_translate_val = isset($_POST['auto_translate']) ? wp_unslash($_POST['auto_translate']) : 0;
    $schedule_val = isset($_POST['schedule']) ? wp_unslash($_POST['schedule']) : '3-per-day';
    $schedule_time_daily_val = isset($_POST['schedule_time_daily']) ? wp_unslash($_POST['schedule_time_daily']) : '09:30';
    $schedule_times_three_val = isset($_POST['schedule_times_three']) ? wp_unslash($_POST['schedule_times_three']) : ['09:30', '13:30', '19:30'];
    $default_lang_url_mode_val = isset($_POST['default_lang_url_mode']) ? wp_unslash($_POST['default_lang_url_mode']) : null;

    // Use filter_var for robust boolean conversion (handles "1", "true", "on", 1, true)
    $auto_blog = filter_var($auto_blog_val, FILTER_VALIDATE_BOOLEAN) ? 1 : 0;
    $auto_translate = filter_var($auto_translate_val, FILTER_VALIDATE_BOOLEAN) ? 1 : 0;
    $schedule = sanitize_text_field(wp_unslash($schedule_val));
    $schedule_time_daily = aismart_normalize_schedule_clock(wp_unslash((string) $schedule_time_daily_val), '09:30');
    $schedule_times_three = aismart_parse_schedule_times_three(
        is_array($schedule_times_three_val) ? wp_unslash($schedule_times_three_val) : wp_unslash((string) $schedule_times_three_val)
    );

    if ($default_lang_url_mode_val !== null) {
        $mode = sanitize_key((string) $default_lang_url_mode_val);
        if (!in_array($mode, ['native', 'prefixed'], true)) {
            $mode = 'native';
        }
        update_option('aismart_default_lang_url_mode', $mode, false);
    }

    update_option('aismart_auto_blog', $auto_blog, false);
    update_option('aismart_auto_translate', $auto_translate, false);
    update_option('aismart_schedule_preset', $schedule, false);
    update_option('aismart_schedule_time_daily', $schedule_time_daily, false);
    update_option('aismart_schedule_times_three', implode(',', $schedule_times_three), false);

    error_log("AISmart Saved: Blog=$auto_blog, Trans=$auto_translate, Sched=$schedule");

    wp_send_json_success([
        'message' => 'Settings updated',
        'saved' => [
            'blog' => $auto_blog,
            'trans' => $auto_translate,
            'default_lang_url_mode' => aismart_get_default_lang_url_mode(),
        ],
    ]);
}

function aismart_get_default_lang_url_mode() {
    $mode = sanitize_key((string) get_option('aismart_default_lang_url_mode', 'native'));
    if (!in_array($mode, ['native', 'prefixed'], true)) {
        $mode = 'native';
    }

    return $mode;
}

function aismart_should_force_default_lang_prefix($provider = '') {
    if (aismart_get_default_lang_url_mode() !== 'prefixed') {
        return false;
    }

    $provider = sanitize_key((string) $provider);
    if ($provider === '') {
        $route = aismart_detect_translation_command();
        $provider = isset($route['engine']) ? sanitize_key((string) $route['engine']) : '';
    }

    $supported = ['bogo'];
    return in_array($provider, $supported, true);
}

function aismart_migration_parse_selected_ids($raw, $allowed_ids = []) {
    $allowed_lookup = [];
    foreach ((array) $allowed_ids as $id) {
        $id = (int) $id;
        if ($id > 0) {
            $allowed_lookup[$id] = true;
        }
    }

    $pieces = preg_split('/[^0-9]+/', (string) $raw);
    if (!is_array($pieces)) {
        return [];
    }

    $ids = [];
    foreach ($pieces as $piece) {
        $id = (int) $piece;
        if ($id <= 0) {
            continue;
        }
        if (!empty($allowed_lookup) && empty($allowed_lookup[$id])) {
            continue;
        }
        $ids[$id] = $id;
    }

    return array_values($ids);
}

function aismart_migration_preview_posts($post_ids, $limit = 60) {
    $limit = (int) $limit;
    if ($limit <= 0) {
        $limit = 60;
    }
    if ($limit > 200) {
        $limit = 200;
    }

    $preview = [];
    foreach ((array) $post_ids as $id_raw) {
        if (count($preview) >= $limit) {
            break;
        }

        $post_id = (int) $id_raw;
        if ($post_id <= 0) {
            continue;
        }

        $post = get_post($post_id);
        if (!$post || $post->post_type !== 'post') {
            continue;
        }

        $preview[] = [
            'id' => $post_id,
            'title' => (string) $post->post_title,
            'date' => mysql2date('Y-m-d', (string) $post->post_date),
            'status' => (string) $post->post_status,
            'provider' => aismart_detect_provider_from_post($post_id),
        ];
    }

    return $preview;
}

function aismart_migration_collect_polylang_family($post_id) {
    $post_id = (int) $post_id;
    if ($post_id <= 0) {
        return [];
    }
    $translations = [];
    $default_lang = function_exists('pll_default_language') ? (string) pll_default_language('slug') : 'en';

    if (function_exists('pll_get_post_translations')) {
        $translations = (array) pll_get_post_translations($post_id);
        if (empty($translations)) {
            $lang = function_exists('pll_get_post_language') ? (string) pll_get_post_language($post_id, 'slug') : '';
            if ($lang !== '') {
                $translations[$lang] = $post_id;
            }
        }
    }

    $family_ids = [];
    $nodes = [];

    if (!empty($translations)) {
        foreach ($translations as $lang_code => $translation_id_raw) {
            $translation_id = (int) $translation_id_raw;
            if ($translation_id <= 0) {
                continue;
            }
            $translation_post = get_post($translation_id);
            if (!$translation_post || $translation_post->post_type !== 'post') {
                continue;
            }

            $lang = strtolower(sanitize_text_field((string) $lang_code));
            if ($lang === '') {
                $lang = function_exists('pll_get_post_language') ? (string) pll_get_post_language($translation_id, 'slug') : '';
                $lang = strtolower(sanitize_text_field($lang));
            }
            if ($lang === '') {
                continue;
            }

            $family_ids[] = $translation_id;
            $nodes[$lang] = [
                'post_id' => $translation_id,
                'lang' => $lang,
                'title' => (string) $translation_post->post_title,
                'excerpt' => (string) $translation_post->post_excerpt,
                'content' => (string) $translation_post->post_content,
            ];
        }
    }

    if (empty($nodes)) {
        global $wpdb;

        $root_id = (int) get_post_meta($post_id, '_aismart_source_post_id', true);
        if ($root_id <= 0) {
            $root_id = $post_id;
        }

        $legacy_ids = [$post_id, $root_id];
        $child_ids = $wpdb->get_col(
            $wpdb->prepare(
                "SELECT post_id
                 FROM {$wpdb->postmeta}
                 WHERE meta_key = %s
                   AND meta_value = %d",
                '_aismart_source_post_id',
                $root_id
            )
        );
        if (is_array($child_ids)) {
            foreach ($child_ids as $child_id_raw) {
                $legacy_ids[] = (int) $child_id_raw;
            }
        }

        $legacy_ids = array_values(array_unique(array_filter(array_map('intval', $legacy_ids))));
        foreach ($legacy_ids as $legacy_id) {
            $translation_post = get_post($legacy_id);
            if (!$translation_post || $translation_post->post_type !== 'post') {
                continue;
            }

            $text_for_detect = (string) $translation_post->post_title . "\n" . (string) $translation_post->post_content;
            $lang = 'en';
            if (preg_match('/\p{Thai}/u', $text_for_detect)) {
                $lang = 'th';
            } elseif (preg_match('/[\p{Hiragana}\p{Katakana}\p{Han}]/u', $text_for_detect)) {
                $lang = 'ja';
            }

            if (isset($nodes[$lang])) {
                $existing_len = strlen((string) ($nodes[$lang]['content'] ?? ''));
                $candidate_len = strlen((string) $translation_post->post_content);
                if ($candidate_len <= $existing_len) {
                    continue;
                }
            }

            $family_ids[] = $legacy_id;
            $nodes[$lang] = [
                'post_id' => $legacy_id,
                'lang' => $lang,
                'title' => (string) $translation_post->post_title,
                'excerpt' => (string) $translation_post->post_excerpt,
                'content' => (string) $translation_post->post_content,
            ];
        }
    }

    if (empty($nodes) || empty($family_ids)) {
        return [];
    }

    sort($family_ids);
    $canonical_id = (int) $family_ids[0];
    if ($default_lang !== '' && isset($translations[$default_lang])) {
        $candidate = (int) $translations[$default_lang];
        if ($candidate > 0) {
            $canonical_id = $candidate;
        }
    }

    return [
        'canonical_id' => $canonical_id,
        'default_lang' => $default_lang !== '' ? $default_lang : 'en',
        'nodes' => $nodes,
        'family_ids' => $family_ids,
    ];
}

function aismart_migration_qtranslate_parity_mismatches($nodes, $wrapped_title, $wrapped_excerpt, $wrapped_content) {
    $mismatches = 0;
    foreach ((array) $nodes as $lang => $node) {
        $lang = strtolower(sanitize_text_field((string) $lang));
        if ($lang === '') {
            continue;
        }

        $src_title = aismart_normalize_compare_text((string) ($node['title'] ?? ''));
        $dst_title = aismart_normalize_compare_text(aismart_qtranslate_extract_segment($wrapped_title, $lang));
        if ($src_title !== '' && $dst_title !== '' && $src_title !== $dst_title) {
            $mismatches++;
        }

        $src_excerpt = aismart_normalize_compare_text((string) ($node['excerpt'] ?? ''));
        $dst_excerpt = aismart_normalize_compare_text(aismart_qtranslate_extract_segment($wrapped_excerpt, $lang));
        if ($src_excerpt !== '' && $dst_excerpt !== '' && $src_excerpt !== $dst_excerpt) {
            $mismatches++;
        }

        $src_content = aismart_normalize_compare_text((string) ($node['content'] ?? ''));
        $dst_content = aismart_normalize_compare_text(aismart_qtranslate_extract_segment($wrapped_content, $lang));
        if ($src_content !== '' && $dst_content !== '' && $src_content !== $dst_content) {
            $mismatches++;
        }
    }

    return $mismatches;
}

function aismart_migration_retire_legacy_posts($post_ids, $reason = '') {
    $retired = 0;
    foreach ((array) $post_ids as $id_raw) {
        $post_id = (int) $id_raw;
        if ($post_id <= 0) {
            continue;
        }
        $post = get_post($post_id);
        if (!$post || $post->post_type !== 'post') {
            continue;
        }
        if ((string) $post->post_status !== 'draft') {
            wp_update_post([
                'ID' => $post_id,
                'post_status' => 'draft',
            ]);
        }
        update_post_meta($post_id, '_aismart_migration_legacy_retired', 1);
        update_post_meta($post_id, '_aismart_migration_legacy_retired_at', gmdate('c'));
        if ($reason !== '') {
            update_post_meta($post_id, '_aismart_migration_legacy_reason', sanitize_text_field($reason));
        }
        $retired++;
    }
    return $retired;
}

function aismart_migration_execute_polylang_to_qtranslate($selected_ids, $mode = 'preserve', $retire_legacy = false) {
    $mode = sanitize_key((string) $mode);
    if (!in_array($mode, ['preserve', 'clean'], true)) {
        $mode = 'preserve';
    }

    $selected_ids = array_values(array_unique(array_map('intval', (array) $selected_ids)));
    if (empty($selected_ids)) {
        return [
            'executed' => false,
            'message' => 'No selected posts to execute.',
            'families_total' => 0,
            'families_processed' => 0,
            'posts_updated' => 0,
            'posts_created' => 0,
            'legacy_retired' => 0,
            'parity_failed' => 0,
            'errors' => [],
        ];
    }

    $family_keys = [];
    $families = [];
    foreach ($selected_ids as $post_id) {
        $family = aismart_migration_collect_polylang_family($post_id);
        if (empty($family) || empty($family['family_ids'])) {
            continue;
        }
        $family_ids = array_values(array_unique(array_map('intval', (array) $family['family_ids'])));
        sort($family_ids);
        $key = implode(',', $family_ids);
        if (isset($family_keys[$key])) {
            continue;
        }
        $family_keys[$key] = true;
        $families[] = $family;
    }

    $result = [
        'executed' => true,
        'mode' => $mode,
        'families_total' => count($families),
        'families_processed' => 0,
        'posts_updated' => 0,
        'posts_created' => 0,
        'legacy_retired' => 0,
        'parity_failed' => 0,
        'errors' => [],
        'sample_targets' => [],
    ];

    foreach ($families as $family) {
        $nodes = (array) ($family['nodes'] ?? []);
        if (empty($nodes)) {
            continue;
        }

        $canonical_id = (int) ($family['canonical_id'] ?? 0);
        $default_lang = strtolower(sanitize_text_field((string) ($family['default_lang'] ?? 'en')));
        if ($default_lang === '' || !isset($nodes[$default_lang])) {
            $langs = array_keys($nodes);
            $default_lang = !empty($langs) ? (string) $langs[0] : 'en';
        }

        $title_segments = [];
        $excerpt_segments = [];
        $content_segments = [];
        foreach ($nodes as $lang => $node) {
            $lang = strtolower(sanitize_text_field((string) $lang));
            if ($lang === '') {
                continue;
            }
            $title_segments[$lang] = aismart_normalize_post_title((string) ($node['title'] ?? ''));
            $excerpt_segments[$lang] = (string) ($node['excerpt'] ?? '');
            $content_segments[$lang] = aismart_cleanup_translated_post_content((string) ($node['content'] ?? ''));
        }

        $wrapped_title = aismart_qtranslate_wrap_segments($title_segments, $default_lang);
        $wrapped_excerpt = aismart_qtranslate_wrap_segments($excerpt_segments, $default_lang);
        $wrapped_content = aismart_qtranslate_wrap_segments($content_segments, $default_lang);

        $target_post_id = $canonical_id;
        if ($mode === 'clean') {
            $signature = md5(implode(',', (array) ($family['family_ids'] ?? [])) . '|polylang|qtranslate');
            $rebuilt_id = (int) get_post_meta($canonical_id, '_aismart_migration_clean_qtranslate_post_id', true);
            if ($rebuilt_id > 0 && get_post($rebuilt_id)) {
                $target_post_id = $rebuilt_id;
            } else {
                $source_post = get_post($canonical_id);
                if (!$source_post || $source_post->post_type !== 'post') {
                    $result['errors'][] = 'Skip family: canonical post missing #' . $canonical_id;
                    continue;
                }

                $insert_id = wp_insert_post([
                    'post_type' => 'post',
                    'post_status' => 'draft',
                    'post_author' => (int) $source_post->post_author,
                    'post_title' => (string) ($title_segments[$default_lang] ?? $source_post->post_title),
                    'post_excerpt' => (string) ($excerpt_segments[$default_lang] ?? $source_post->post_excerpt),
                    'post_content' => (string) ($content_segments[$default_lang] ?? $source_post->post_content),
                ], true);

                if (is_wp_error($insert_id) || (int) $insert_id <= 0) {
                    $result['errors'][] = 'Create clean target failed family canonical #' . $canonical_id;
                    continue;
                }

                $target_post_id = (int) $insert_id;
                $result['posts_created']++;

                $category_ids = wp_get_post_categories($canonical_id);
                if (!empty($category_ids)) {
                    wp_set_post_categories($target_post_id, $category_ids, false);
                }
                $tag_ids = wp_get_post_tags($canonical_id, ['fields' => 'ids']);
                if (!empty($tag_ids)) {
                    wp_set_post_tags($target_post_id, $tag_ids, false);
                }

                $thumbnail_id = (int) get_post_thumbnail_id($canonical_id);
                if ($thumbnail_id > 0) {
                    set_post_thumbnail($target_post_id, $thumbnail_id);
                }

                update_post_meta($target_post_id, '_aismart_migration_clean_signature', $signature);
                update_post_meta($target_post_id, '_aismart_created_provider', 'qtranslate');
                update_post_meta($canonical_id, '_aismart_migration_clean_qtranslate_post_id', $target_post_id);
            }
        }

        $update_result = wp_update_post([
            'ID' => $target_post_id,
            'post_title' => $wrapped_title,
            'post_excerpt' => $wrapped_excerpt,
            'post_content' => $wrapped_content,
        ], true);

        if (is_wp_error($update_result)) {
            $result['errors'][] = 'Update failed target #' . $target_post_id . ' : ' . $update_result->get_error_message();
            continue;
        }

        update_post_meta($target_post_id, '_aismart_created_provider', 'qtranslate');
        update_post_meta($target_post_id, '_aismart_last_multilang_provider', 'qtranslate');
        update_post_meta($target_post_id, '_aismart_migration_v21_mode', $mode);
        update_post_meta($target_post_id, '_aismart_migration_v21_source', 'polylang');
        update_post_meta($target_post_id, '_aismart_migration_v21_at', gmdate('c'));

        $mismatch_count = aismart_migration_qtranslate_parity_mismatches($nodes, $wrapped_title, $wrapped_excerpt, $wrapped_content);
        if ($mismatch_count > 0) {
            $result['parity_failed']++;
        }

        if ($retire_legacy && $mismatch_count === 0) {
            $legacy_ids = array_values(array_unique(array_map('intval', (array) ($family['family_ids'] ?? []))));
            if ($mode === 'preserve') {
                $legacy_ids = array_values(array_filter($legacy_ids, static function ($id) use ($target_post_id) {
                    return (int) $id !== (int) $target_post_id;
                }));
            }
            $result['legacy_retired'] += (int) aismart_migration_retire_legacy_posts(
                $legacy_ids,
                'V2.1 migration ' . $mode . ' polylang->qtranslate'
            );
        }

        $result['families_processed']++;
        $result['posts_updated']++;
        if (count($result['sample_targets']) < 30) {
            $result['sample_targets'][] = $target_post_id;
        }
    }

    $result['message'] = sprintf(
        'Executed %d/%d families. Updated %d post(s), created %d, parity failed %d, legacy retired %d.',
        (int) $result['families_processed'],
        (int) $result['families_total'],
        (int) $result['posts_updated'],
        (int) $result['posts_created'],
        (int) $result['parity_failed'],
        (int) $result['legacy_retired']
    );

    return $result;
}

add_action('wp_ajax_aismart_run_migration_bridge', 'aismart_run_migration_bridge');
function aismart_run_migration_bridge() {
    if (!current_user_can('manage_options')) {
        wp_send_json_error(['message' => 'Unauthorized'], 403);
    }

    $labels = aismart_supported_provider_labels();

    $mode = sanitize_key((string) ($_POST['mode'] ?? 'preserve'));
    if (!in_array($mode, ['preserve', 'clean'], true)) {
        $mode = 'preserve';
    }

    $target = aismart_normalize_provider_key($_POST['target_provider'] ?? '');
    if ($target === '' || $target === 'auto') {
        $target = aismart_detect_active_provider_key();
    }
    if ($target === '' || !isset($labels[$target])) {
        wp_send_json_error(['message' => 'Target plugin not resolved. Please choose target plugin.'], 422);
    }

    $source = aismart_normalize_provider_key($_POST['source_provider'] ?? '');
    if ($source === '' || $source === 'auto') {
        $source = aismart_guess_previous_provider_key($target);
    }
    if ($source === '' || !isset($labels[$source])) {
        wp_send_json_error(['message' => 'Source plugin not resolved. Please choose source plugin.'], 422);
    }
    if ($source === $target) {
        wp_send_json_error(['message' => 'Source and target cannot be the same plugin.'], 422);
    }

    $execute = !empty($_POST['execute']) && filter_var($_POST['execute'], FILTER_VALIDATE_BOOLEAN);
    $retire_legacy = !empty($_POST['retire_legacy']) && filter_var($_POST['retire_legacy'], FILTER_VALIDATE_BOOLEAN);

    global $wpdb;
    $scan_limit = isset($_POST['scan_limit']) ? (int) $_POST['scan_limit'] : 250;
    if ($scan_limit < 50) {
        $scan_limit = 50;
    }
    if ($scan_limit > 1000) {
        $scan_limit = 1000;
    }

    $post_ids = $wpdb->get_col(
        $wpdb->prepare(
            "SELECT ID
             FROM {$wpdb->posts}
             WHERE post_type='post'
               AND post_status IN ('publish','draft','pending','future','private')
             ORDER BY ID DESC
             LIMIT %d",
            $scan_limit
        )
    );

    $candidate_ids = [];
    if (is_array($post_ids)) {
        foreach ($post_ids as $id_raw) {
            $post_id = (int) $id_raw;
            if ($post_id <= 0) {
                continue;
            }
            $provider = aismart_normalize_provider_key(aismart_detect_provider_from_post($post_id));
            if ($provider === $source) {
                $candidate_ids[] = $post_id;
            }
        }
    }

    $selected_raw = isset($_POST['selected_post_ids']) ? (string) wp_unslash($_POST['selected_post_ids']) : '';
    $selected_allowlist = $candidate_ids;
    if ($execute && trim($selected_raw) !== '') {
        $selected_allowlist = [];
    }
    $selected_ids = aismart_migration_parse_selected_ids($selected_raw, $selected_allowlist);
    if (empty($selected_ids)) {
        $selected_ids = array_values($candidate_ids);
    }

    $plan = [
        'ran_at' => gmdate('c'),
        'mode' => $mode,
        'source_provider' => $source,
        'target_provider' => $target,
        'source_label' => (string) $labels[$source],
        'target_label' => (string) $labels[$target],
        'scan_limit' => $scan_limit,
        'scan_posts' => is_array($post_ids) ? count($post_ids) : 0,
        'candidate_posts' => count($candidate_ids),
        'selected_posts' => count($selected_ids),
        'sample_candidate_post_ids' => array_slice(array_values($candidate_ids), 0, 30),
        'sample_selected_post_ids' => array_slice(array_values($selected_ids), 0, 30),
        'candidate_preview' => aismart_migration_preview_posts($candidate_ids, 60),
        'selected_preview' => aismart_migration_preview_posts($selected_ids, 60),
        'execution' => $execute ? 'phase2-execute' : 'planning-safe',
        'retire_legacy' => $retire_legacy ? 1 : 0,
        'next' => $mode === 'clean'
            ? 'Fallback rebuild mode selected: recreate target plugin entries from existing translated text, then retire legacy IDs after parity checks.'
            : 'Preserve mode selected: convert/re-link existing translation graph into target plugin format.',
    ];

    $execution_result = null;
    if ($execute) {
        if ($source === 'polylang' && $target === 'qtranslate') {
            $execution_result = aismart_migration_execute_polylang_to_qtranslate($selected_ids, $mode, $retire_legacy);
            $plan['execution_result'] = $execution_result;
        } else {
            wp_send_json_error([
                'message' => 'Phase 2 execution currently supports Polylang -> qTranslate only. You can still run planning mode for other pairs.',
                'plan' => $plan,
            ], 422);
        }
    }

    update_option('aismart_migration_last_source_provider', $source, false);
    update_option('aismart_migration_bridge_last_run', $plan, false);

    $message = $mode === 'clean'
        ? 'Clean Migration ' . ($execute ? 'executed.' : 'plan prepared.')
        : 'Migration ' . ($execute ? 'executed.' : 'plan prepared. If result is not correct, use Clean Migration fallback mode.');

    wp_send_json_success([
        'message' => $message,
        'plan' => $plan,
        'execution_result' => $execution_result,
    ]);
}
// AJAX: Get translation status list
add_action('wp_ajax_aismart_get_translation_status', 'aismart_get_translation_status');
function aismart_normalize_compare_text($text) {
    $normalized = trim(wp_strip_all_tags((string) $text));
    if (function_exists('mb_strtolower')) {
        $normalized = mb_strtolower($normalized);
    } else {
        $normalized = strtolower($normalized);
    }
    $normalized = preg_replace('/\s+/u', ' ', $normalized);
    return is_string($normalized) ? trim($normalized) : '';
}

function aismart_normalize_post_title($title) {
    $title = trim((string) $title);
    if ($title === '') {
        return '';
    }

    // Remove repeated trailing language-code markers e.g. "(TH) (TH)".
    $title = preg_replace('/(?:\s*\([A-Z]{2,5}(?:-[A-Z]{2,5})?\))+\s*$/u', '', $title);
    $title = preg_replace('/\s{2,}/u', ' ', (string) $title);
    return trim((string) $title);
}

function aismart_text_looks_english($text) {
    $sample = aismart_normalize_compare_text($text);
    if ($sample === '') {
        return false;
    }

    $ascii_only = preg_replace('/[^\x00-\x7F]/u', '', $sample);
    $ascii_ratio = strlen($sample) > 0 ? (strlen($ascii_only) / strlen($sample)) : 0;
    $hits = preg_match_all('/\b(the|and|for|with|from|that|your|you|how|marketing|plan|build|simple)\b/i', $sample);

    return $ascii_ratio > 0.85 && is_int($hits) && $hits >= 2;
}

function aismart_language_script_match($text, $lang_code) {
    $normalized = aismart_normalize_compare_text($text);
    if ($normalized === '') {
        return false;
    }

    $lang = strtolower((string) $lang_code);
    if ($lang === 'th') {
        return preg_match('/\p{Thai}/u', $normalized) === 1;
    }
    if ($lang === 'ja') {
        return preg_match('/[\p{Hiragana}\p{Katakana}\p{Han}]/u', $normalized) === 1;
    }
    if (in_array($lang, ['zh', 'zh-hk', 'zh-hans', 'zh-hant'], true)) {
        return preg_match('/\p{Han}/u', $normalized) === 1;
    }

    return true;
}

function aismart_detect_cloned_english_bundle($translated_texts) {
    if (!is_array($translated_texts) || count($translated_texts) < 3) {
        return false;
    }

    $hashes = [];
    $sample = '';
    foreach ($translated_texts as $text) {
        $normalized = aismart_normalize_compare_text($text);
        if ($normalized === '') {
            continue;
        }
        $hashes[] = md5($normalized);
        if ($sample === '') {
            $sample = $normalized;
        }
    }

    if (count($hashes) < 3) {
        return false;
    }

    if (count(array_unique($hashes)) !== 1) {
        return false;
    }

    return aismart_text_looks_english($sample);
}

function aismart_is_managed_source_post($post_id) {
    $post_id = (int) $post_id;
    if ($post_id <= 0) {
        return false;
    }

    $generated = get_post_meta($post_id, '_aismart_generated_post', true);
    if (!empty($generated)) {
        return true;
    }

    if (has_term('online-course', 'post_tag', $post_id) || has_term('online-course', 'category', $post_id)) {
        return true;
    }

    // Some translation sets were created with generated meta on a sibling language post.
    // Treat this post as managed when any translation sibling carries the generated marker.
    if (function_exists('pll_get_post_translations')) {
        $translations = pll_get_post_translations($post_id);
        if (is_array($translations) && !empty($translations)) {
            foreach ($translations as $translated_post_id) {
                $translated_post_id = (int) $translated_post_id;
                if ($translated_post_id <= 0) {
                    continue;
                }
                if (!empty(get_post_meta($translated_post_id, '_aismart_generated_post', true))) {
                    return true;
                }
                if (has_term('online-course', 'post_tag', $translated_post_id) || has_term('online-course', 'category', $translated_post_id)) {
                    return true;
                }
            }
        }
    }

    return false;
}

function aismart_is_non_source_translation_post($post_id) {
    $post_id = (int) $post_id;
    if ($post_id <= 0) {
        return false;
    }

    if ((int) get_post_meta($post_id, '_aismart_source_post_id', true) > 0) {
        return true;
    }

    global $wpdb;

    $selected_provider = aismart_normalize_provider_key(aismart_resolve_selected_provider_key());
    $detected = (array) aismart_onboarding_detect_multilang_provider();
    $active_primary = aismart_normalize_provider_key($detected['primary'] ?? '');
    
    if ($selected_provider === '' || $selected_provider === 'none') {
        $selected_provider = $active_primary;
    }

    $is_child = false;

    switch ($selected_provider) {
        case 'polylang':
            if (function_exists('pll_get_post_language') && function_exists('pll_default_language')) {
                $pll_lang = sanitize_key((string) pll_get_post_language($post_id, 'slug'));
                $pll_default = sanitize_key((string) pll_default_language('slug'));
                if ($pll_lang !== '' && $pll_default !== '' && strcasecmp($pll_lang, $pll_default) !== 0) {
                    $is_child = true;
                }
            }
            break;
            
        case 'wpml':
            if (has_filter('wpml_element_language_details')) {
                $lang_info = apply_filters('wpml_element_language_details', null, [
                    'element_id' => $post_id,
                    'element_type' => 'post_post',
                ]);
                if (is_array($lang_info) && !empty($lang_info['source_language_code'])) {
                    $is_child = true;
                } elseif (is_object($lang_info) && !empty($lang_info->source_language_code)) {
                    $is_child = true;
                }
            }
            break;

        case 'bogo':
            $locale = sanitize_text_field((string) get_post_meta($post_id, '_locale', true));
            if ($locale !== '' && strcasecmp($locale, 'all') !== 0) {
                $default_locale = function_exists('bogo_get_default_locale') ? sanitize_text_field((string) bogo_get_default_locale()) : '';
                if ($default_locale !== '' && strcasecmp($locale, $default_locale) !== 0) {
                    $is_child = true;
                } elseif ($default_locale === '') {
                    $is_child = true;
                }
            }
            break;
    }

    if ($is_child) {
        return true;
    }

    // Checking for legacy DB plugin ghost child posts:
    static $wpml_table_ok = null;
    $wpml_table = $wpdb->prefix . 'icl_translations';
    if ($wpml_table_ok === null) {
        $wpml_table_ok = ($wpdb->get_var("SHOW TABLES LIKE '{$wpml_table}'") === $wpml_table);
    }
    
    if ($wpml_table_ok) {
         $source_code = $wpdb->get_var($wpdb->prepare("SELECT source_language_code FROM {$wpml_table} WHERE element_id = %d AND element_type = %s", $post_id, 'post_post'));
         if (!empty($source_code)) {
             return true;
         }
    }

    return false;
}

function aismart_get_translation_status() {
    if (!current_user_can('manage_options')) {
        wp_send_json_error(['message' => 'Unauthorized'], 403);
    }

    global $wpdb;

    $search = isset($_POST['search']) ? sanitize_text_field(wp_unslash($_POST['search'])) : '';
    $filter = isset($_POST['filter']) ? sanitize_text_field(wp_unslash($_POST['filter'])) : 'all';
    $limit = isset($_POST['limit']) ? absint($_POST['limit']) : 15;
    $limit = $limit > 0 ? $limit : 15;
    $selected_provider = aismart_normalize_provider_key(aismart_resolve_selected_provider_key());
    $detected = (array) aismart_onboarding_detect_multilang_provider();
    $active_primary_provider = aismart_normalize_provider_key($detected['primary'] ?? '');
    $active_provider_list = array_values(array_unique(array_filter(array_map('aismart_normalize_provider_key', (array) ($detected['detected'] ?? [])))));

    if ($selected_provider === '' || $selected_provider === 'none') {
        $selected_provider = $active_primary_provider;
    } elseif (!empty($active_provider_list) && !in_array($selected_provider, $active_provider_list, true)) {
        // If saved provider is no longer active, use active runtime provider for status checks.
        $selected_provider = $active_primary_provider;
    }
    $provider_matches = static function ($provider_key) use ($selected_provider) {
        $provider_key = aismart_normalize_provider_key((string) $provider_key);
        if ($provider_key === '') {
            return true;
        }

        return $selected_provider === '' || $selected_provider === 'none' || $selected_provider === $provider_key;
    };

    if ($provider_matches('polylang') && function_exists('pll_languages_list')) {
        $codes = pll_languages_list();
        $names = pll_languages_list(['fields' => 'name']);
        $language_map = [];
        $active_codes = [];
        if (is_array($codes)) {
            foreach ($codes as $index => $code) {
                $active_codes[] = (string) $code;
                $language_map[(string) $code] = is_array($names) && isset($names[$index]) ? (string) $names[$index] : (string) $code;
            }
        }

        $base_language = function_exists('pll_default_language') ? (string) pll_default_language() : (count($active_codes) ? $active_codes[0] : 'en');
        $missing_languages = array_values(array_diff($active_codes, [$base_language]));

        $posts = get_posts([
            'post_type' => 'post',
            'post_status' => ['publish', 'draft'],
            'posts_per_page' => $limit,
            's' => $search,
            'orderby' => 'date',
            'order' => 'DESC',
            'lang' => $base_language,
        ]);

        if (!$posts) {
            wp_send_json_success(['posts' => [], 'languages' => $language_map, 'base_language' => $base_language]);
        }

        $output = [];
        foreach ($posts as $post) {
            $post_id = (int) $post->ID;
            if (!aismart_is_managed_source_post($post_id)) {
                continue;
            }
            if (aismart_is_non_source_translation_post($post_id)) {
                continue;
            }
            $source_is_publish = ((string) $post->post_status === 'publish');
            $base_content = trim(wp_strip_all_tags((string) $post->post_content));
            $base_content = function_exists('mb_strtolower') ? mb_strtolower($base_content) : strtolower($base_content);
            $base_hash = $base_content !== '' ? md5($base_content) : '';

            $translations = function_exists('pll_get_post_translations') ? pll_get_post_translations($post_id) : [];
            $missing = [];
            $translated_texts = [];
            $quality_issue = '';
            $quality_label = '';
            $progress_percent = null;
            $target_locale_count = count($missing_languages);
            $english_fallback_count = 0;
            foreach ($missing_languages as $lang_code) {
                $translated_id = isset($translations[$lang_code]) ? (int) $translations[$lang_code] : 0;
                $translated_post = $translated_id > 0 ? get_post($translated_id) : null;
                $status_value = $translated_post ? sanitize_key((string) $translated_post->post_status) : '';
                $status_ok = $translated_post && !in_array($status_value, ['trash', 'auto-draft'], true);
                $translated_content = $translated_post ? aismart_normalize_compare_text($translated_post->post_content) : '';
                $translated_hash = $translated_content !== '' ? md5($translated_content) : '';
                $content_ok = $translated_hash !== '';
                $is_translated = $status_ok && $content_ok;

                if ($is_translated && !aismart_language_script_match($translated_content, $lang_code)) {
                    $is_translated = false;
                    $english_fallback_count++;
                }

                if ($status_ok && $content_ok) {
                    $translated_texts[$lang_code] = $translated_content;
                }

                if (!$is_translated) {
                    $missing[] = $language_map[$lang_code] ?? $lang_code;
                }
            }

            if ($quality_issue === '' && $target_locale_count > 0 && $english_fallback_count > 0 && $english_fallback_count === $target_locale_count) {
                $quality_issue = 'cloned_english';
            }

            if ($quality_issue === '' && aismart_detect_cloned_english_bundle($translated_texts)) {
                $quality_issue = 'cloned_english';
            }

            if ($quality_issue === 'cloned_english') {
                $quality_label = 'Cloned English from mother';
                $progress_percent = 50;
                if (count($missing) === 0) {
                    foreach ($missing_languages as $lang_code) {
                        $missing[] = $language_map[$lang_code] ?? $lang_code;
                    }
                }
            }

            $is_complete = $source_is_publish && count($missing) === 0;
            if ($filter === 'complete' && !$is_complete) {
                continue;
            }
            if ($filter === 'missing' && $is_complete) {
                continue;
            }

            $row_status = $source_is_publish
                ? ($is_complete ? 'complete' : 'missing')
                : 'draft';

            $output[] = [
                'id' => $post_id,
                'title' => $post->post_title,
                'date' => mysql2date('Y-m-d', $post->post_date),
                'missing_languages' => $missing,
                'missing_count' => count($missing),
                'status' => $row_status,
                'post_status' => (string) $post->post_status,
                'can_translate' => $source_is_publish ? 1 : 0,
                'quality_issue' => $quality_issue,
                'quality_label' => $quality_label,
                'progress_percent' => $progress_percent,
            ];
        }

        wp_send_json_success([
            'posts' => $output,
            'languages' => $language_map,
            'base_language' => $base_language,
        ]);
    }

    if ($provider_matches('translatepress') && (function_exists('trp_get_languages') || defined('TRP_PLUGIN_VERSION'))) {
        $language_map = [];
        $active_codes = [];

        $trp_languages = function_exists('trp_get_languages') ? (array) trp_get_languages() : [];
        if (is_array($trp_languages)) {
            foreach ($trp_languages as $code => $name) {
                if (is_int($code)) {
                    $code = (string) $name;
                }
                $code = sanitize_text_field((string) $code);
                if ($code === '') {
                    continue;
                }
                $active_codes[] = $code;
                $language_map[$code] = is_scalar($name) ? (string) $name : $code;
            }
        }

        if (empty($active_codes)) {
            $trp_settings = get_option('trp_settings', []);
            $fallback_codes = [];
            if (is_array($trp_settings) && !empty($trp_settings['translation-languages']) && is_array($trp_settings['translation-languages'])) {
                $fallback_codes = $trp_settings['translation-languages'];
            }
            foreach ($fallback_codes as $code) {
                $code = sanitize_text_field((string) $code);
                if ($code === '') {
                    continue;
                }
                $active_codes[] = $code;
                if (!isset($language_map[$code])) {
                    $language_map[$code] = $code;
                }
            }
        }

        $trp_settings = get_option('trp_settings', []);
        $base_language = 'en_US';
        if (is_array($trp_settings) && !empty($trp_settings['default-language'])) {
            $base_language = sanitize_text_field((string) $trp_settings['default-language']);
        } elseif (!empty($active_codes)) {
            $base_language = (string) $active_codes[0];
        }

        $active_codes = array_values(array_unique(array_filter(array_map('strval', $active_codes))));
        if (!in_array($base_language, $active_codes, true) && $base_language !== '') {
            $active_codes[] = $base_language;
            if (!isset($language_map[$base_language])) {
                $language_map[$base_language] = $base_language;
            }
        }

        $base_candidates = [];
        if ($base_language !== '') {
            $base_candidates[] = strtolower($base_language);
            $base_candidates[] = strtolower(str_replace('_', '-', $base_language));

            if (strpos($base_language, '_') !== false) {
                $base_candidates[] = strtolower(substr($base_language, 0, strpos($base_language, '_')));
            } elseif (strpos($base_language, '-') !== false) {
                $base_candidates[] = strtolower(substr($base_language, 0, strpos($base_language, '-')));
            }
        }
        if (is_array($trp_settings) && !empty($trp_settings['url-slugs']) && is_array($trp_settings['url-slugs']) && !empty($trp_settings['url-slugs'][$base_language])) {
            $base_candidates[] = strtolower((string) $trp_settings['url-slugs'][$base_language]);
        }
        $base_candidates = array_values(array_unique(array_filter($base_candidates)));

        $missing_languages = array_values(array_diff($active_codes, [$base_language]));

        $posts = get_posts([
            'post_type' => 'post',
            'post_status' => ['publish', 'draft'],
            'posts_per_page' => $limit,
            's' => $search,
            'orderby' => 'date',
            'order' => 'DESC',
            'meta_query' => [
                'relation' => 'OR',
                [
                    'key' => '_aismart_source_post_id',
                    'compare' => 'NOT EXISTS',
                ],
                [
                    'key' => '_aismart_source_post_id',
                    'value' => '',
                    'compare' => '=',
                ],
            ],
        ]);

        if (!$posts) {
            wp_send_json_success(['posts' => [], 'languages' => $language_map, 'base_language' => $base_language]);
        }

        $legacy_lang_by_post = [];
        $post_ids_for_lang = array_values(array_unique(array_map(static function ($p) {
            return (int) $p->ID;
        }, $posts)));
        if (!empty($post_ids_for_lang)) {
            $placeholders = implode(',', array_fill(0, count($post_ids_for_lang), '%d'));
            $lang_rows = $wpdb->get_results($wpdb->prepare(
                "SELECT tr.object_id AS post_id, LOWER(t.slug) AS lang_slug
                 FROM {$wpdb->term_relationships} tr
                 INNER JOIN {$wpdb->term_taxonomy} tt ON tt.term_taxonomy_id = tr.term_taxonomy_id
                 INNER JOIN {$wpdb->terms} t ON t.term_id = tt.term_id
                 WHERE tt.taxonomy = 'language' AND tr.object_id IN ({$placeholders})",
                $post_ids_for_lang
            ));

            if (is_array($lang_rows)) {
                foreach ($lang_rows as $lang_row) {
                    $rid = isset($lang_row->post_id) ? (int) $lang_row->post_id : 0;
                    $slug = isset($lang_row->lang_slug) ? sanitize_text_field((string) $lang_row->lang_slug) : '';
                    if ($rid <= 0 || $slug === '') {
                        continue;
                    }
                    if (!isset($legacy_lang_by_post[$rid])) {
                        $legacy_lang_by_post[$rid] = [];
                    }
                    $legacy_lang_by_post[$rid][] = strtolower($slug);
                }
            }
        }

        $output = [];
        $seen_titles = [];
        foreach ($posts as $post) {
            $post_id = (int) $post->ID;

            if (!aismart_is_managed_source_post($post_id)) {
                continue;
            }
            if (aismart_is_non_source_translation_post($post_id)) {
                continue;
            }

            $source_post_id = (int) get_post_meta($post_id, '_aismart_source_post_id', true);
            if ($source_post_id > 0) {
                continue;
            }

            $target_lang_meta = sanitize_text_field((string) get_post_meta($post_id, '_aismart_target_lang', true));
            if ($target_lang_meta !== '' && !empty($base_candidates) && !in_array(strtolower($target_lang_meta), $base_candidates, true)) {
                continue;
            }

            $term_langs = isset($legacy_lang_by_post[$post_id]) && is_array($legacy_lang_by_post[$post_id])
                ? array_values(array_unique(array_map('strtolower', array_map('strval', $legacy_lang_by_post[$post_id]))))
                : [];
            if (!empty($term_langs) && !empty($base_candidates)) {
                if (count(array_intersect($term_langs, $base_candidates)) === 0) {
                    continue;
                }
            }

            $normalized_title_key = aismart_normalize_compare_text(aismart_normalize_post_title((string) $post->post_title));
            if ($normalized_title_key !== '') {
                if (isset($seen_titles[$normalized_title_key])) {
                    continue;
                }
                $seen_titles[$normalized_title_key] = 1;
            }

            $queued = (bool) get_post_meta($post_id, '_aismart_translation_queued', true);

            $missing = [];
            if (!$queued) {
                foreach ($missing_languages as $lang_code) {
                    $missing[] = $language_map[$lang_code] ?? $lang_code;
                }
            }

            $is_complete = count($missing) === 0;
            if ($filter === 'complete' && !$is_complete) {
                continue;
            }
            if ($filter === 'missing' && $is_complete) {
                continue;
            }

            $output[] = [
                'id' => $post_id,
                'title' => $post->post_title,
                'date' => mysql2date('Y-m-d', $post->post_date),
                'missing_languages' => $missing,
                'missing_count' => count($missing),
                'status' => $is_complete ? 'complete' : 'missing',
                'quality_issue' => '',
                'quality_label' => '',
                'progress_percent' => null,
            ];
        }

        wp_send_json_success([
            'posts' => $output,
            'languages' => $language_map,
            'base_language' => $base_language,
        ]);
    }

    if (
        $provider_matches('qtranslate')
        && (
            defined('QTX_VERSION')
            || function_exists('qtranxf_getSortedLanguages')
            || function_exists('qtrans_getSortedLanguages')
            || function_exists('qtrans_getLanguage')
        )
    ) {
        $language_map = [];
        $active_codes = [];

        $enabled = get_option('qtranslate_enabled_languages', []);
        if (!is_array($enabled)) {
            $enabled = [];
        }

        if (empty($enabled) && !empty($GLOBALS['q_config']) && is_array($GLOBALS['q_config']) && !empty($GLOBALS['q_config']['enabled_languages']) && is_array($GLOBALS['q_config']['enabled_languages'])) {
            $enabled = (array) $GLOBALS['q_config']['enabled_languages'];
        }

        $names = get_option('qtranslate_language_names', []);
        if (!is_array($names)) {
            $names = [];
        }

        foreach ((array) $enabled as $code_raw) {
            $code = strtolower(sanitize_text_field((string) $code_raw));
            if ($code === '') {
                continue;
            }
            $active_codes[] = $code;

            $label = '';
            if (isset($names[$code]) && is_scalar($names[$code])) {
                $label = (string) $names[$code];
            } elseif (!empty($GLOBALS['q_config']) && is_array($GLOBALS['q_config']) && !empty($GLOBALS['q_config']['language_name'][$code])) {
                $label = (string) $GLOBALS['q_config']['language_name'][$code];
            }
            if ($label === '') {
                $label = strtoupper(str_replace('-', '_', $code));
            }

            $language_map[$code] = sanitize_text_field($label);
        }

        $active_codes = array_values(array_unique(array_filter(array_map('strval', $active_codes))));
        $base_language = strtolower(sanitize_text_field((string) get_option('qtranslate_default_language', '')));
        if ($base_language === '' && !empty($active_codes)) {
            $base_language = (string) $active_codes[0];
        }
        if ($base_language === '') {
            $base_language = 'en';
        }
        if (!in_array($base_language, $active_codes, true)) {
            $active_codes[] = $base_language;
            if (!isset($language_map[$base_language])) {
                $language_map[$base_language] = strtoupper($base_language);
            }
        }

        $missing_languages = array_values(array_diff($active_codes, [$base_language]));

        $candidate_limit = max($limit * 40, 600);
        if ($candidate_limit > 2000) {
            $candidate_limit = 2000;
        }

        $posts = get_posts([
            'post_type' => 'post',
            'post_status' => 'publish',
            'posts_per_page' => $candidate_limit,
            's' => $search,
            'orderby' => 'date',
            'order' => 'DESC',
            'meta_query' => [
                'relation' => 'OR',
                [
                    'key' => '_aismart_source_post_id',
                    'compare' => 'NOT EXISTS',
                ],
                [
                    'key' => '_aismart_source_post_id',
                    'value' => '',
                    'compare' => '=',
                ],
            ],
        ]);

        if (!$posts) {
            wp_send_json_success(['posts' => [], 'languages' => $language_map, 'base_language' => $base_language]);
        }

        $output = [];
        $seen_titles = [];
        foreach ($posts as $post) {
            $post_id = (int) $post->ID;
            $raw_content = (string) $wpdb->get_var($wpdb->prepare(
                "SELECT post_content FROM {$wpdb->posts} WHERE ID = %d LIMIT 1",
                $post_id
            ));
            $content = $raw_content !== '' ? $raw_content : (string) $post->post_content;

            $is_managed = aismart_is_managed_source_post($post_id);
            $has_qtranslate_content = preg_match('/\[:[a-z]{2}(?:[-_][a-zA-Z]{2,5})?\]/u', $content) === 1;
            if (!$is_managed && !$has_qtranslate_content) {
                continue;
            }
            if (aismart_is_non_source_translation_post($post_id)) {
                continue;
            }

            $source_post_id = (int) get_post_meta($post_id, '_aismart_source_post_id', true);
            if ($source_post_id > 0) {
                continue;
            }

            $normalized_title_key = aismart_normalize_compare_text(aismart_normalize_post_title((string) $post->post_title));
            if ($normalized_title_key !== '') {
                if (isset($seen_titles[$normalized_title_key])) {
                    continue;
                }
                $seen_titles[$normalized_title_key] = 1;
            }

            $missing = [];
            foreach ($missing_languages as $lang_code) {
                $lang_code = strtolower((string) $lang_code);
                $tag_pattern = '/\[:' . preg_quote($lang_code, '/') . '\](.*?)(?=(\[:[a-z]{2}(?:[-_][a-zA-Z]{2,5})?\]|\[:\]))/su';
                if (!preg_match($tag_pattern, $content, $matches)) {
                    $missing[] = $language_map[$lang_code] ?? strtoupper($lang_code);
                    continue;
                }

                $segment = isset($matches[1]) ? trim(wp_strip_all_tags((string) $matches[1])) : '';
                if ($segment === '') {
                    $missing[] = $language_map[$lang_code] ?? strtoupper($lang_code);
                }
            }

            $is_complete = count($missing) === 0;
            if ($filter === 'complete' && !$is_complete) {
                continue;
            }
            if ($filter === 'missing' && $is_complete) {
                continue;
            }

            $output[] = [
                'id' => $post_id,
                'title' => $post->post_title,
                'date' => mysql2date('Y-m-d', $post->post_date),
                'missing_languages' => $missing,
                'missing_count' => count($missing),
                'status' => $is_complete ? 'complete' : 'missing',
                'quality_issue' => '',
                'quality_label' => '',
                'progress_percent' => null,
            ];
        }

        wp_send_json_success([
            'posts' => $output,
            'languages' => $language_map,
            'base_language' => $base_language,
        ]);
    }

    if (
        $provider_matches('wpglobus')
        && (
            class_exists('WPGlobus', false)
            || defined('WPGLOBUS_VERSION')
            || aismart_detect_active_provider_key() === 'wpglobus'
        )
    ) {
        $language_map = [];
        $active_codes = aismart_get_wpglobus_enabled_languages();

        $english_names = get_option('wpglobus_option_en_language_names', []);
        if (!is_array($english_names)) {
            $english_names = [];
        }

        foreach ((array) $active_codes as $code) {
            $code = strtolower(sanitize_text_field((string) $code));
            if ($code === '') {
                continue;
            }
            $label = isset($english_names[$code]) && is_scalar($english_names[$code])
                ? (string) $english_names[$code]
                : strtoupper(str_replace('-', '_', $code));
            $language_map[$code] = sanitize_text_field($label);
        }

        $base_language = 'en';
        $wpglobus_option = get_option('wpglobus_option', []);
        if (is_array($wpglobus_option) && isset($wpglobus_option['default_language']) && is_scalar($wpglobus_option['default_language'])) {
            $base_language = strtolower(sanitize_text_field((string) $wpglobus_option['default_language']));
        } elseif (!empty($active_codes)) {
            $base_language = (string) $active_codes[0];
        }
        if ($base_language === '') {
            $base_language = 'en';
        }

        if (!in_array($base_language, $active_codes, true)) {
            $active_codes[] = $base_language;
            if (!isset($language_map[$base_language])) {
                $language_map[$base_language] = strtoupper($base_language);
            }
        }

        $missing_languages = array_values(array_diff($active_codes, [$base_language]));

        $candidate_limit = max($limit * 40, 600);
        if ($candidate_limit > 2000) {
            $candidate_limit = 2000;
        }

        $posts = get_posts([
            'post_type' => 'post',
            'post_status' => 'publish',
            'posts_per_page' => $candidate_limit,
            's' => $search,
            'orderby' => 'date',
            'order' => 'DESC',
            'meta_query' => [
                'relation' => 'OR',
                [
                    'key' => '_aismart_source_post_id',
                    'compare' => 'NOT EXISTS',
                ],
                [
                    'key' => '_aismart_source_post_id',
                    'value' => '',
                    'compare' => '=',
                ],
            ],
        ]);

        if (!$posts) {
            wp_send_json_success(['posts' => [], 'languages' => $language_map, 'base_language' => $base_language]);
        }

        $output = [];
        foreach ($posts as $post) {
            $post_id = (int) $post->ID;
            if (!aismart_is_managed_source_post($post_id)) {
                continue;
            }
            if (aismart_is_non_source_translation_post($post_id)) {
                continue;
            }
            if (aismart_is_non_source_translation_post($post_id)) {
                continue;
            }

            $source_post_id = (int) get_post_meta($post_id, '_aismart_source_post_id', true);
            if ($source_post_id > 0) {
                continue;
            }

            $content = (string) get_post_field('post_content', $post_id);
            $missing = [];
            foreach ($missing_languages as $lang_code) {
                $segment = aismart_qtranslate_extract_segment($content, $lang_code);
                if (aismart_normalize_compare_text($segment) === '') {
                    $missing[] = $language_map[$lang_code] ?? strtoupper($lang_code);
                }
            }

            $source_is_publish = ((string) $post->post_status === 'publish');
            $is_complete = $source_is_publish && count($missing) === 0;
            if ($filter === 'complete' && !$is_complete) {
                continue;
            }
            if ($filter === 'missing' && $is_complete) {
                continue;
            }

            $row_status = $source_is_publish
                ? ($is_complete ? 'complete' : 'missing')
                : 'draft';

            $output[] = [
                'id' => $post_id,
                'title' => (string) $post->post_title,
                'date' => mysql2date('Y-m-d', (string) $post->post_date),
                'missing_languages' => $missing,
                'missing_count' => count($missing),
                'status' => $row_status,
                'post_status' => (string) $post->post_status,
                'can_translate' => $source_is_publish ? 1 : 0,
                'quality_issue' => '',
                'quality_label' => '',
                'progress_percent' => null,
            ];

            if (count($output) >= $limit) {
                break;
            }
        }

        wp_send_json_success([
            'posts' => $output,
            'languages' => $language_map,
            'base_language' => $base_language,
        ]);
    }

    if (
        $provider_matches('bogo')
        && (
            function_exists('bogo_available_locales')
            || class_exists('Bogo', false)
            || aismart_detect_active_provider_key() === 'bogo'
        )
    ) {
        $language_map = [];
        $active_locales = function_exists('bogo_available_locales')
            ? (array) bogo_available_locales(['exclude_enus_if_inactive' => true])
            : [];

        foreach ($active_locales as $locale) {
            $locale = sanitize_text_field((string) $locale);
            if ($locale === '') {
                continue;
            }

            $code = aismart_bogo_locale_to_lang_code($locale);
            if ($code === '') {
                continue;
            }

            $name = function_exists('bogo_get_language') ? (string) bogo_get_language($locale) : strtoupper($code);
            if ($name === '') {
                $name = strtoupper($code);
            }

            $language_map[$code] = sanitize_text_field($name);
        }

        $base_locale = function_exists('bogo_get_default_locale') ? (string) bogo_get_default_locale() : 'en_US';
        $base_language = aismart_bogo_locale_to_lang_code($base_locale);
        if ($base_language === '') {
            $base_language = 'en';
        }

        $active_codes = array_values(array_unique(array_filter(array_map('strval', array_keys($language_map)))));
        if (!in_array($base_language, $active_codes, true)) {
            $active_codes[] = $base_language;
            if (!isset($language_map[$base_language])) {
                $language_map[$base_language] = strtoupper($base_language);
            }
        }

        $missing_languages = array_values(array_diff($active_codes, [$base_language]));

        $candidate_limit = max($limit * 40, 600);
        if ($candidate_limit > 2000) {
            $candidate_limit = 2000;
        }

        $posts = get_posts([
            'post_type' => 'post',
            'post_status' => 'publish',
            'posts_per_page' => $candidate_limit,
            's' => $search,
            'orderby' => 'date',
            'order' => 'DESC',
            'meta_query' => [
                'relation' => 'OR',
                [
                    'key' => '_aismart_source_post_id',
                    'compare' => 'NOT EXISTS',
                ],
                [
                    'key' => '_aismart_source_post_id',
                    'value' => '',
                    'compare' => '=',
                ],
            ],
        ]);

        if (!$posts) {
            wp_send_json_success(['posts' => [], 'languages' => $language_map, 'base_language' => $base_language]);
        }

        $output = [];
        foreach ($posts as $post) {
            $post_id = (int) $post->ID;
            if (!aismart_is_managed_source_post($post_id)) {
                continue;
            }
            if (aismart_is_non_source_translation_post($post_id)) {
                continue;
            }

            $source_post_id = (int) get_post_meta($post_id, '_aismart_source_post_id', true);
            if ($source_post_id > 0) {
                continue;
            }

            // Legacy Bogo rows may have linked children without locale metadata/taxonomy.
            // Keep a fallback pool so panel status still reflects completed translated children.
            $fallback_child_pool = [];
            $fallback_children = get_posts([
                'post_type' => 'post',
                'post_status' => 'publish',
                'posts_per_page' => -1,
                'meta_key' => '_aismart_source_post_id',
                'meta_value' => (string) $post_id,
                'orderby' => 'ID',
                'order' => 'ASC',
            ]);
            if (is_array($fallback_children) && !empty($fallback_children)) {
                foreach ($fallback_children as $fallback_child) {
                    if (!$fallback_child instanceof WP_Post) {
                        continue;
                    }
                    $fallback_content = aismart_normalize_compare_text((string) $fallback_child->post_content);
                    if ($fallback_content !== '') {
                        $fallback_child_pool[] = (int) $fallback_child->ID;
                    }
                }
            }

            $missing = [];
            foreach ($missing_languages as $lang_code) {
                $target_locale = '';
                foreach ($active_locales as $locale) {
                    $locale = sanitize_text_field((string) $locale);
                    if (aismart_bogo_locale_to_lang_code($locale) === $lang_code) {
                        $target_locale = $locale;
                        break;
                    }
                }

                if ($target_locale === '') {
                    $missing[] = $language_map[$lang_code] ?? strtoupper($lang_code);
                    continue;
                }

                $translated_post = function_exists('bogo_get_post_translation')
                    ? bogo_get_post_translation($post_id, $target_locale)
                    : false;

                $status_value = $translated_post instanceof WP_Post ? sanitize_key((string) $translated_post->post_status) : '';
                $status_ok = $translated_post instanceof WP_Post && !in_array($status_value, ['trash', 'auto-draft'], true);
                $content = $translated_post instanceof WP_Post ? aismart_normalize_compare_text((string) $translated_post->post_content) : '';
                if (!$status_ok || $content === '') {
                    if (!empty($fallback_child_pool)) {
                        array_shift($fallback_child_pool);
                        continue;
                    }
                    $missing[] = $language_map[$lang_code] ?? strtoupper($lang_code);
                }
            }

            $source_is_publish = ((string) $post->post_status === 'publish');
            $is_complete = $source_is_publish && count($missing) === 0;
            if ($filter === 'complete' && !$is_complete) {
                continue;
            }
            if ($filter === 'missing' && $is_complete) {
                continue;
            }

            $row_status = $source_is_publish
                ? ($is_complete ? 'complete' : 'missing')
                : 'draft';

            $output[] = [
                'id' => $post_id,
                'title' => (string) $post->post_title,
                'date' => mysql2date('Y-m-d', (string) $post->post_date),
                'missing_languages' => $missing,
                'missing_count' => count($missing),
                'status' => $row_status,
                'post_status' => (string) $post->post_status,
                'can_translate' => $source_is_publish ? 1 : 0,
                'quality_issue' => '',
                'quality_label' => '',
                'progress_percent' => null,
            ];

            if (count($output) >= $limit) {
                break;
            }
        }

        wp_send_json_success([
            'posts' => $output,
            'languages' => $language_map,
            'base_language' => $base_language,
        ]);
    }

    if (
        $provider_matches('falang')
        && (
            function_exists('falang_languages_list')
            || class_exists('Falang', false)
            || defined('FALANG_VERSION')
            || aismart_detect_active_provider_key() === 'falang'
        )
    ) {
        $language_pairs = function_exists('aismart_get_falang_language_pairs')
            ? (array) aismart_get_falang_language_pairs()
            : [];

        $language_map = [];
        $active_pairs = [];

        foreach ($language_pairs as $pair) {
            if (!is_array($pair)) {
                continue;
            }

            $locale = sanitize_text_field((string) ($pair['locale'] ?? ''));
            $slug = sanitize_title((string) ($pair['slug'] ?? ''));
            if ($locale === '' && $slug === '') {
                continue;
            }
            if ($locale === '') {
                $locale = $slug;
            }
            if ($slug === '') {
                $slug = sanitize_title($locale);
            }

            $label = strtoupper(str_replace('_', '-', $locale));
            if (taxonomy_exists('language')) {
                $term = get_term_by('slug', $slug, 'language');
                if ($term instanceof WP_Term && $term->name !== '') {
                    $label = sanitize_text_field((string) $term->name);
                }
            }

            $active_pairs[] = [
                'locale' => $locale,
                'slug' => $slug,
            ];
            $language_map[$slug !== '' ? $slug : strtolower($locale)] = $label;
        }

        if (empty($active_pairs) && taxonomy_exists('language')) {
            $terms = get_terms([
                'taxonomy' => 'language',
                'hide_empty' => false,
            ]);
            if (!is_wp_error($terms) && is_array($terms)) {
                foreach ($terms as $term) {
                    if (!($term instanceof WP_Term)) {
                        continue;
                    }
                    $slug = sanitize_title((string) $term->slug);
                    if ($slug === '') {
                        continue;
                    }
                    $active_pairs[] = [
                        'locale' => $slug,
                        'slug' => $slug,
                    ];
                    $language_map[$slug] = sanitize_text_field((string) $term->name);
                }
            }
        }

        $base_locale = function_exists('falang_default_language')
            ? sanitize_text_field((string) falang_default_language('locale'))
            : '';

        if ($base_locale === '' && !empty($active_pairs)) {
            $base_locale = sanitize_text_field((string) ($active_pairs[0]['locale'] ?? ''));
        }
        if ($base_locale === '') {
            $base_locale = 'en_US';
        }

        $base_slug = sanitize_title($base_locale);
        if ($base_slug === '') {
            $base_slug = strtolower($base_locale);
        }

        $target_pairs = [];
        foreach ($active_pairs as $pair) {
            $locale = sanitize_text_field((string) ($pair['locale'] ?? ''));
            $slug = sanitize_title((string) ($pair['slug'] ?? ''));
            if ($locale === '' && $slug === '') {
                continue;
            }
            if ($slug === '') {
                $slug = sanitize_title($locale);
            }
            if (strcasecmp($locale, $base_locale) === 0 || $slug === $base_slug) {
                continue;
            }
            $target_pairs[] = [
                'locale' => $locale,
                'slug' => $slug,
            ];
            if (!isset($language_map[$slug])) {
                $language_map[$slug] = strtoupper($slug);
            }
        }

        if (!isset($language_map[$base_slug])) {
            $language_map[$base_slug] = strtoupper($base_slug);
        }

        $base_candidates = array_values(array_unique(array_filter([
            strtolower($base_slug),
            strtolower(sanitize_title($base_locale)),
            strtolower(substr((string) $base_slug, 0, 2)),
            strtolower(substr((string) $base_locale, 0, 2)),
        ])));

        $posts = get_posts([
            'post_type' => 'post',
            'post_status' => ['publish', 'draft'],
            'posts_per_page' => $limit,
            's' => $search,
            'orderby' => 'date',
            'order' => 'DESC',
            'meta_query' => [
                'relation' => 'OR',
                [
                    'key' => '_aismart_source_post_id',
                    'compare' => 'NOT EXISTS',
                ],
                [
                    'key' => '_aismart_source_post_id',
                    'value' => '',
                    'compare' => '=',
                ],
            ],
        ]);

        if (!$posts) {
            wp_send_json_success(['posts' => [], 'languages' => $language_map, 'base_language' => $base_slug]);
        }

        $output = [];
        foreach ($posts as $post) {
            $post_id = (int) $post->ID;
            if (!aismart_is_managed_source_post($post_id)) {
                continue;
            }

            $source_post_id = (int) get_post_meta($post_id, '_aismart_source_post_id', true);
            if ($source_post_id > 0) {
                continue;
            }

            $post_lang_slugs = [];
            if (taxonomy_exists('language')) {
                $raw_lang_slugs = wp_get_post_terms($post_id, 'language', ['fields' => 'slugs']);
                if (!is_wp_error($raw_lang_slugs) && is_array($raw_lang_slugs)) {
                    foreach ($raw_lang_slugs as $lang_slug_raw) {
                        $lang_slug = strtolower(sanitize_title((string) $lang_slug_raw));
                        if ($lang_slug !== '') {
                            $post_lang_slugs[] = $lang_slug;
                        }
                    }
                    $post_lang_slugs = array_values(array_unique($post_lang_slugs));
                }
            }

            if (!empty($post_lang_slugs) && count(array_intersect($post_lang_slugs, $base_candidates)) === 0) {
                continue;
            }

            $source_is_publish = ((string) $post->post_status === 'publish');
            $missing = [];

            foreach ($target_pairs as $pair) {
                $target_locale = sanitize_text_field((string) ($pair['locale'] ?? ''));
                $target_slug = sanitize_title((string) ($pair['slug'] ?? ''));
                if ($target_locale === '' && $target_slug === '') {
                    continue;
                }

                $prefix = function_exists('aismart_get_falang_meta_prefix')
                    ? (string) aismart_get_falang_meta_prefix($target_locale !== '' ? $target_locale : $target_slug)
                    : ('_' . ($target_locale !== '' ? $target_locale : $target_slug) . '_');
                $translated_content = aismart_normalize_compare_text((string) get_post_meta($post_id, $prefix . 'post_content', true));
                $translated_title = aismart_normalize_compare_text((string) get_post_meta($post_id, $prefix . 'post_title', true));
                $translated_published = (string) get_post_meta($post_id, $prefix . 'published', true);

                $has_translation = ($translated_content !== '' || $translated_title !== '');
                $is_published_translation = ($translated_published === '' || $translated_published === '1');

                if (!($has_translation && $is_published_translation)) {
                    $missing[] = $language_map[$target_slug] ?? strtoupper($target_slug !== '' ? $target_slug : $target_locale);
                }
            }

            $is_complete = $source_is_publish && count($missing) === 0;
            if ($filter === 'complete' && !$is_complete) {
                continue;
            }
            if ($filter === 'missing' && $is_complete) {
                continue;
            }

            $row_status = $source_is_publish
                ? ($is_complete ? 'complete' : 'missing')
                : 'draft';

            $output[] = [
                'id' => $post_id,
                'title' => (string) $post->post_title,
                'date' => mysql2date('Y-m-d', (string) $post->post_date),
                'missing_languages' => $missing,
                'missing_count' => count($missing),
                'status' => $row_status,
                'post_status' => (string) $post->post_status,
                'can_translate' => $source_is_publish ? 1 : 0,
                'quality_issue' => '',
                'quality_label' => '',
                'progress_percent' => null,
            ];

            if (count($output) >= $limit) {
                break;
            }
        }

        wp_send_json_success([
            'posts' => $output,
            'languages' => $language_map,
            'base_language' => $base_slug,
        ]);
    }

    if (!$provider_matches('wpml')) {
        wp_send_json_success(['posts' => [], 'languages' => []]);
    }

    $translations_table = $wpdb->prefix . 'icl_translations';
    $languages_table = $wpdb->prefix . 'icl_languages';

    $translations_exists = $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $translations_table));
    $languages_exists = $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $languages_table));

    if (!$translations_exists || !$languages_exists) {
        wp_send_json_success(['posts' => [], 'languages' => []]);
    }

    $active_languages = $wpdb->get_results("SELECT code, english_name FROM {$languages_table} WHERE active = 1");
    $language_map = [];
    $active_codes = [];
    foreach ($active_languages as $lang) {
        $language_map[$lang->code] = $lang->english_name ?: $lang->code;
        $active_codes[] = $lang->code;
    }

    $base_language = in_array('en', $active_codes, true) ? 'en' : (count($active_codes) ? $active_codes[0] : 'en');
    $missing_languages = array_values(array_diff($active_codes, [$base_language]));

    $posts_table = $wpdb->posts;
    $limit = max(1, (int) $limit);

    if ($search !== '') {
        $search_like = '%' . $wpdb->esc_like($search) . '%';
        $posts = $wpdb->get_results($wpdb->prepare(
            "SELECT p.ID, p.post_title, p.post_date, p.post_content, t.trid
             FROM {$posts_table} p
             LEFT JOIN {$translations_table} t
                ON t.element_id = p.ID
                AND t.element_type = 'post_post'
             WHERE p.post_status = 'publish'
                AND p.post_type = 'post'
                AND p.post_title LIKE %s
                AND (t.language_code = %s OR t.language_code IS NULL)
             ORDER BY p.post_date DESC
             LIMIT %d",
            $search_like,
            $base_language,
            $limit
        ));
    } else {
        $posts = $wpdb->get_results($wpdb->prepare(
            "SELECT p.ID, p.post_title, p.post_date, p.post_content, t.trid
             FROM {$posts_table} p
             LEFT JOIN {$translations_table} t
                ON t.element_id = p.ID
                AND t.element_type = 'post_post'
             WHERE p.post_status = 'publish'
                AND p.post_type = 'post'
                AND (t.language_code = %s OR t.language_code IS NULL)
             ORDER BY p.post_date DESC
             LIMIT %d",
            $base_language,
            $limit
        ));
    }

    if (!$posts) {
        wp_send_json_success(['posts' => [], 'languages' => $language_map]);
    }

    $trids = array_values(array_unique(array_filter(array_map(fn($row) => (int) $row->trid, $posts))));
    $base_hash_by_trid = [];
    $base_hash_by_id = [];
    foreach ($posts as $post) {
        $normalized = trim(wp_strip_all_tags((string) $post->post_content));
        if (function_exists('mb_strtolower')) {
            $normalized = mb_strtolower($normalized);
        } else {
            $normalized = strtolower($normalized);
        }
        $hash = $normalized !== '' ? md5($normalized) : '';
        $post_id = (int) $post->ID;
        $base_hash_by_id[$post_id] = $hash;
        if (!empty($post->trid)) {
            $base_hash_by_trid[(int) $post->trid] = $hash;
        }
    }
    $translation_map = [];
    if ($trids) {
        $placeholders = implode(',', array_fill(0, count($trids), '%d'));
        $translation_rows = $wpdb->get_results($wpdb->prepare(
            "SELECT t.trid, t.language_code, t.Translated, p.post_status, p.post_content
             FROM {$translations_table} t
             LEFT JOIN {$posts_table} p ON p.ID = t.element_id
             WHERE t.element_type = 'post_post' AND t.trid IN ({$placeholders})",
            $trids
        ));

        foreach ($translation_rows as $row) {
            $content = trim(wp_strip_all_tags((string) $row->post_content));
            if (function_exists('mb_strtolower')) {
                $content = mb_strtolower($content);
            } else {
                $content = strtolower($content);
            }
            $content_hash = $content !== '' ? md5($content) : '';
            $translation_map[(int) $row->trid][$row->language_code] = [
                'translated' => (int) $row->Translated,
                'status' => $row->post_status,
                'content_hash' => $content_hash,
            ];
        }
    }

    $output = [];
    foreach ($posts as $post) {
        $post_id = (int) $post->ID;
        if (!aismart_is_managed_source_post($post_id)) {
            continue;
        }

        $trid = (int) $post->trid;
        $translated = $trid ? ($translation_map[$trid] ?? []) : [];
        $base_hash = $trid ? ($base_hash_by_trid[$trid] ?? '') : ($base_hash_by_id[$post_id] ?? '');

        $missing = [];
        $translated_texts = [];
        $quality_issue = '';
        $quality_label = '';
        $progress_percent = null;
        foreach ($missing_languages as $lang_code) {
            $lang_state = $translated[$lang_code] ?? null;
            $translated_flag = is_array($lang_state) && (int) ($lang_state['translated'] ?? 0) === 1;
            $status_value = is_array($lang_state) ? sanitize_key((string) ($lang_state['status'] ?? '')) : '';
            $status_ok = in_array($status_value, ['publish', 'future', 'draft', 'pending', 'private'], true);
            $content_ok = is_array($lang_state) && !empty($lang_state['content_hash']);
            $diff_ok = $content_ok && ($base_hash === '' || $lang_state['content_hash'] !== $base_hash);
            $is_translated = $content_ok && ($translated_flag || ($status_ok && $diff_ok));

            if ($is_translated) {
                $translated_texts[$lang_code] = (string) $lang_state['content_hash'];
            }
            if (!$is_translated) {
                $missing[] = $language_map[$lang_code] ?? $lang_code;
            }
        }

        if (count($translated_texts) >= 3 && count(array_unique(array_values($translated_texts))) === 1) {
            $quality_issue = 'cloned_english';
            $quality_label = 'Cloned English from mother';
            $progress_percent = 50;
            if (count($missing) === 0) {
                foreach ($missing_languages as $lang_code) {
                    $missing[] = $language_map[$lang_code] ?? $lang_code;
                }
            }
        }

        $is_complete = count($missing) === 0;
        if ($filter === 'complete' && !$is_complete) {
            continue;
        }
        if ($filter === 'missing' && $is_complete) {
            continue;
        }

        $output[] = [
            'id' => $post_id,
            'title' => $post->post_title,
            'date' => mysql2date('Y-m-d', $post->post_date),
            'missing_languages' => $missing,
            'missing_count' => count($missing),
            'status' => $is_complete ? 'complete' : 'missing',
            'post_status' => 'publish',
            'can_translate' => 1,
            'quality_issue' => $quality_issue,
            'quality_label' => $quality_label,
            'progress_percent' => $progress_percent,
        ];
    }

    wp_send_json_success([
        'posts' => $output,
        'languages' => $language_map,
        'base_language' => $base_language,
    ]);
}

// AJAX: Trigger translation for a post (background)
add_action('wp_ajax_aismart_translate_now', 'aismart_translate_now');
function aismart_translate_now() {
    if (!current_user_can('manage_options')) {
        wp_send_json_error(['message' => 'Unauthorized'], 403);
    }
    if (!aismart_require_positive_credit_or_json_error('Translation')) {
        return;
    }

    $post_id = isset($_POST['post_id']) ? absint($_POST['post_id']) : 0;
    if ($post_id <= 0) {
        wp_send_json_error(['message' => 'Invalid post ID'], 400);
    }

    error_log('AISmart Translate Now: request received for post_id=' . $post_id);
    aismart_queue_log('Translate now requested post_id=' . $post_id);

    $route = aismart_detect_translation_command();
    $engine = isset($route['engine']) ? sanitize_key((string) $route['engine']) : 'unknown';

    if (in_array($engine, ['bogo', 'wpml', 'polylang'], true)) {
        $args = [(int) $post_id, 'bogo'];
        if ($engine !== 'bogo') {
            $args = [(int) $post_id, $engine];
        }
        if (!wp_next_scheduled('aismart_process_translation_event', $args)) {
            wp_schedule_single_event(time() + 1, 'aismart_process_translation_event', $args);
        }
        if (function_exists('spawn_cron')) {
            @spawn_cron(time());
        }
        aismart_defer_background_translation((int) $post_id, $engine);

        delete_post_meta($post_id, '_aismart_translation_last_error');
        update_post_meta($post_id, '_aismart_translation_queued', 1);
        update_post_meta($post_id, '_aismart_translation_queue_last_at', gmdate('c'));
        aismart_queue_log('Translate now queued in background post_id=' . $post_id . ' engine=' . $engine);

        wp_send_json_success([
            'message' => 'Translation queued in background',
            'post_id' => $post_id,
            'translation_queued' => 1,
            'translation_queued_background' => 1,
        ]);
    }

    $queue_runtime_noise = '';
    $buffer_started = false;
    try {
        if (!headers_sent()) {
            ob_start();
            $buffer_started = true;
        }
        $queued = aismart_queue_translation_for_post($post_id);
    } catch (Throwable $e) {
        $queued = false;
        update_post_meta($post_id, '_aismart_translation_last_error', sanitize_text_field($e->getMessage()));
        error_log('AISmart Translate Now Exception: post_id=' . (int) $post_id . ' message=' . $e->getMessage());
    } finally {
        if ($buffer_started) {
            $queue_runtime_noise = trim((string) ob_get_clean());
        }
    }

    if ($queue_runtime_noise !== '') {
        $noise_preview = substr(preg_replace('/\s+/u', ' ', $queue_runtime_noise), 0, 500);
        aismart_queue_log('Translate now runtime output post_id=' . $post_id . ' output=' . $noise_preview);
    }

    if (!$queued) {
        delete_post_meta($post_id, '_aismart_translation_queued');
        delete_post_meta($post_id, '_aismart_translation_queue_last_at');
        aismart_queue_log('Translate now queue failed post_id=' . $post_id);
        $message = 'Translation queue failed (check error log)';
        $last_error = (string) get_post_meta($post_id, '_aismart_translation_last_error', true);
        if ($last_error !== '') {
            $message = $last_error;
        }
        if ($engine === 'translatepress') {
            $message = 'Laravel Backend Error: ' . $message;
        }
        wp_send_json_error(['message' => $message], 500);
    }

    update_post_meta($post_id, '_aismart_translation_queued', 1);
    update_post_meta($post_id, '_aismart_translation_queue_last_at', gmdate('c'));
    aismart_queue_log('Translate now queued post_id=' . $post_id . ' meta_marked=1');

    wp_send_json_success([
        'message' => 'Translation queued',
        'post_id' => $post_id,
        'translation_queued' => 1,
    ]);
}

// Auto-translate on publish when enabled
add_action('transition_post_status', 'aismart_auto_translate_on_publish', 10, 3);
function aismart_auto_translate_on_publish($new_status, $old_status, $post) {
    if ($new_status !== 'publish' || $old_status === 'publish') {
        return;
    }
    if (!$post || $post->post_type !== 'post') {
        return;
    }
    $forced_on_publish = (bool) get_post_meta($post->ID, '_aismart_force_translate_on_publish', true);
    if (!get_option('aismart_auto_translate', 0) && !$forced_on_publish) {
        return;
    }
    if (wp_is_post_revision($post->ID)) {
        return;
    }

    if (!aismart_is_managed_source_post((int) $post->ID)) {
        return;
    }

    $already = get_post_meta($post->ID, '_aismart_translation_queued', true);
    if ($already) {
        return;
    }
    
    // Safety: Do not auto-translate posts that are themselves translations.
    // For Bogo, a translated child can be published before _aismart_source_post_id
    // is written, so also use locale/target-lang heuristics.
    $is_translation = get_post_meta($post->ID, '_aismart_source_post_id', true);
    if ($is_translation || aismart_is_non_source_translation_post((int) $post->ID)) {
        return;
    }

    $queued = aismart_queue_translation_for_post($post->ID);
    if ($queued) {
        update_post_meta($post->ID, '_aismart_translation_queued', 1);
        if ($forced_on_publish) {
            delete_post_meta($post->ID, '_aismart_force_translate_on_publish');
        }
    }
}

function aismart_detect_translation_command() {
    $active_plugins = (array) get_option('active_plugins', []);
    if (is_multisite()) {
        $sitewide = array_keys((array) get_site_option('active_sitewide_plugins', []));
        $active_plugins = array_values(array_unique(array_merge($active_plugins, $sitewide)));
    }

    $has_plugin = static function ($slug) use ($active_plugins) {
        return in_array($slug, $active_plugins, true);
    };

    $provider_available = static function ($provider) use ($has_plugin) {
        $provider = sanitize_key((string) $provider);
        if ($provider === '') {
            return false;
        }

        if ($provider === 'wpml') {
            return defined('ICL_SITEPRESS_VERSION') || $has_plugin('sitepress-multilingual-cms/sitepress.php');
        }
        if ($provider === 'polylang') {
            return function_exists('pll_languages_list') || $has_plugin('polylang/polylang.php');
        }
        if ($provider === 'translatepress') {
            return defined('TRP_PLUGIN_VERSION') || $has_plugin('translatepress-multilingual/index.php');
        }
        if ($provider === 'multilingualpress') {
            return $has_plugin('multilingual-press/multilingual-press.php') || $has_plugin('multilingual-press/multilingualpress.php') || $has_plugin('multilingualpress/multilingualpress.php');
        }
        if ($provider === 'falang') {
            return $has_plugin('falang/falang.php');
        }
        if ($provider === 'qtranslate') {
            return $has_plugin('qtranslate-x/qtranslate.php') || $has_plugin('qtranslate-xt/qtranslate.php') || $has_plugin('qtranslate/qtranslate.php');
        }
        if ($provider === 'sublanguage') {
            return $has_plugin('sublanguage/sublanguage.php');
        }
        if ($provider === 'wpglobus') {
            return $has_plugin('wpglobus/wpglobus.php');
        }
        if ($provider === 'bogo') {
            return $has_plugin('bogo/bogo.php');
        }

        return false;
    };

    // Respect explicit provider selected in onboarding when that provider is available.
    // This prevents fallback-order mismatches when multiple multilingual plugins coexist.
    $selected_provider = aismart_normalize_provider_key(aismart_resolve_selected_provider_key());
    if ($selected_provider !== '' && $provider_available($selected_provider)) {
        $selected_engine = $selected_provider === 'qtranslate-xt' ? 'qtranslate' : $selected_provider;
        $selected_command = $selected_engine . ':translate-universal';
        if ($selected_engine === 'translatepress') {
            $selected_command = 'trp:translate';
        }
        return ['engine' => $selected_engine, 'command' => $selected_command];
    }

    if (function_exists('pll_languages_list') || $has_plugin('polylang/polylang.php')) {
        return ['engine' => 'polylang', 'command' => 'polylang:translate-universal'];
    }

    if (defined('TRP_PLUGIN_VERSION') || $has_plugin('translatepress-multilingual/index.php')) {
        return ['engine' => 'translatepress', 'command' => 'trp:translate'];
    }

    if ($has_plugin('multilingual-press/multilingual-press.php') || $has_plugin('multilingual-press/multilingualpress.php') || $has_plugin('multilingualpress/multilingualpress.php')) {
        return ['engine' => 'multilingualpress', 'command' => 'multilingualpress:translate-universal'];
    }

    if ($has_plugin('falang/falang.php')) {
        return ['engine' => 'falang', 'command' => 'falang:translate-universal'];
    }

    if ($has_plugin('qtranslate-x/qtranslate.php') || $has_plugin('qtranslate-xt/qtranslate.php') || $has_plugin('qtranslate/qtranslate.php')) {
        return ['engine' => 'qtranslate', 'command' => 'qtranslate:translate-universal'];
    }

    if ($has_plugin('sublanguage/sublanguage.php')) {
        return ['engine' => 'sublanguage', 'command' => 'sublanguage:translate-universal'];
    }

    if ($has_plugin('wpglobus/wpglobus.php')) {
        return ['engine' => 'wpglobus', 'command' => 'wpglobus:translate-universal'];
    }

    if ($has_plugin('bogo/bogo.php')) {
        return ['engine' => 'bogo', 'command' => 'bogo:translate-universal'];
    }

    if (defined('ICL_SITEPRESS_VERSION') || $has_plugin('sitepress-multilingual-cms/sitepress.php')) {
        return ['engine' => 'wpml', 'command' => 'wpml:translate-universal'];
    }

    $state = aismart_onboarding_state_get();
    $saved_provider = isset($state['multilang_provider']) ? sanitize_key((string) $state['multilang_provider']) : '';
    $provider_to_engine = [
        'wpml' => 'wpml',
        'polylang' => 'polylang',
        'translatepress' => 'translatepress',
        'multilingualpress' => 'multilingualpress',
        'falang' => 'falang',
        'qtranslate' => 'qtranslate',
        'qtranslate-xt' => 'qtranslate',
        'sublanguage' => 'sublanguage',
        'wpglobus' => 'wpglobus',
        'bogo' => 'bogo',
    ];

    if ($saved_provider !== '' && isset($provider_to_engine[$saved_provider])) {
        $engine = (string) $provider_to_engine[$saved_provider];
        return ['engine' => $engine, 'command' => $engine . ':translate-universal'];
    }

    return ['engine' => 'unknown', 'command' => ''];
}

function aismart_engine_to_universal_command($engine) {
    $engine = sanitize_key((string) $engine);
    $allowed = [
        'wpml',
        'polylang',
        'translatepress',
        'multilingualpress',
        'falang',
        'qtranslate',
        'sublanguage',
        'wpglobus',
        'bogo',
    ];

    if ($engine === 'qtranslate-xt') {
        $engine = 'qtranslate';
    }

    if (!in_array($engine, $allowed, true)) {
        return '';
    }

    return $engine . ':translate-universal';
}

function aismart_defer_background_translation($post_id, $engine = 'unknown') {
    static $registered = false;
    static $jobs = [];

    $post_id = (int) $post_id;
    $engine = sanitize_key((string) $engine);
    if ($post_id <= 0 || $engine === '') {
        return;
    }

    $jobs[$engine . ':' . $post_id] = [$post_id, $engine];
    if ($registered) {
        return;
    }

    $registered = true;
    register_shutdown_function(static function () use (&$jobs) {
        if (empty($jobs)) {
            return;
        }

        if (function_exists('ignore_user_abort')) {
            @ignore_user_abort(true);
        }

        // Release the client response first when supported, then continue translation work.
        if (function_exists('fastcgi_finish_request')) {
            @fastcgi_finish_request();
        }

        if (function_exists('set_time_limit')) {
            @set_time_limit(120);
        }

        foreach ($jobs as $job) {
            $pid = isset($job[0]) ? (int) $job[0] : 0;
            $eng = isset($job[1]) ? sanitize_key((string) $job[1]) : '';
            if ($pid <= 0 || $eng === '') {
                continue;
            }

            aismart_queue_log('Deferred translation worker start post_id=' . $pid . ' engine=' . $eng);
            aismart_process_translation_event_handler($pid, $eng);
        }
    });
}

add_action('aismart_process_translation_event', 'aismart_process_translation_event_handler', 10, 2);
function aismart_process_translation_event_handler($post_id, $engine = 'unknown') {
    $post_id = (int) $post_id;
    $engine = sanitize_key((string) $engine);
    if ($post_id <= 0) {
        return;
    }

    $lock_key = 'aismart_translation_worker_lock_' . $post_id;
    if (function_exists('get_transient') && get_transient($lock_key)) {
        aismart_queue_log('Background translation worker locked/skip post_id=' . $post_id . ' engine=' . $engine);
        return;
    }
    if (function_exists('set_transient')) {
        set_transient($lock_key, 1, 90);
    }

    try {
        aismart_queue_log('Background translation worker start post_id=' . $post_id . ' engine=' . $engine);

        if ($engine === 'polylang') {
            $ok = aismart_translate_polylang_native($post_id);
            aismart_queue_log('Background translation worker result post_id=' . $post_id . ' engine=' . $engine . ' ok=' . ($ok ? '1' : '0'));
            if ($ok) {
                aismart_clear_translation_runtime_cache($post_id);
                aismart_schedule_featured_image_sync($post_id);
            }
            return;
        }

        if ($engine === 'bogo') {
            $ok = aismart_translate_bogo_native($post_id);
            aismart_queue_log('Background translation worker result post_id=' . $post_id . ' engine=' . $engine . ' ok=' . ($ok ? '1' : '0'));
            if ($ok) {
                aismart_clear_translation_runtime_cache($post_id);
                aismart_schedule_featured_image_sync($post_id);
            }
            return;
        }

        if ($engine === 'wpml') {
            $ok = aismart_translate_wpml_native($post_id);
            aismart_queue_log('Background translation worker result post_id=' . $post_id . ' engine=' . $engine . ' ok=' . ($ok ? '1' : '0'));
            if ($ok) {
                aismart_clear_translation_runtime_cache($post_id);
                aismart_schedule_featured_image_sync($post_id);
            }
            return;
        }

        aismart_queue_log('Background translation worker skip unsupported engine=' . $engine . ' post_id=' . $post_id);
    } finally {
        if (function_exists('delete_transient')) {
            delete_transient($lock_key);
        }
    }
}

add_action('aismart_retry_translatepress_event', 'aismart_retry_translatepress_event_handler', 10, 1);
function aismart_retry_translatepress_event_handler($post_id) {
    $post_id = (int) $post_id;
    if ($post_id <= 0) {
        return;
    }

    $route = aismart_detect_translation_command();
    $engine = isset($route['engine']) ? sanitize_key((string) $route['engine']) : 'unknown';
    $command = isset($route['command']) ? (string) $route['command'] : '';
    if ($engine !== 'translatepress' || $command === '') {
        aismart_queue_log('TranslatePress retry skipped post_id=' . $post_id . ' engine=' . $engine . ' command=' . $command);
        return;
    }

    $php_binary = PHP_BINARY;
    if (
        !$php_binary ||
        !is_file($php_binary) ||
        !is_executable($php_binary) ||
        stripos((string) $php_binary, 'php-fpm') !== false
    ) {
        $php_binary = '/usr/bin/php';
    }

    $artisan = aismart_get_artisan_path();
    if (!file_exists($artisan)) {
        aismart_queue_log('TranslatePress retry skipped: artisan missing post_id=' . $post_id);
        return;
    }

    $cmd = sprintf(
        '%s %s %s gemini blog 0 site2 --id=%d 2>&1',
        escapeshellcmd($php_binary),
        escapeshellarg($artisan),
        escapeshellarg($command),
        (int) $post_id
    );

    $output = [];
    $result = 1;
    $ran = aismart_shell_run_capture($cmd, $output, $result);
    $preview = substr(preg_replace('/\s+/u', ' ', implode("\n", (array) $output)), 0, 700);
    aismart_queue_log('TranslatePress retry run post_id=' . $post_id . ' ran=' . ($ran ? '1' : '0') . ' result=' . (int) $result . ' cmd=' . $cmd . ' output=' . $preview);

    if ($ran && (int) $result === 0) {
        aismart_clear_translation_runtime_cache($post_id);
        aismart_schedule_featured_image_sync($post_id);
    }
}

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

    $args = [$post_id];
    if (!wp_next_scheduled('aismart_retry_translatepress_event', $args)) {
        wp_schedule_single_event(time() + 25, 'aismart_retry_translatepress_event', $args);
        aismart_queue_log('Scheduled TranslatePress retry post_id=' . $post_id . ' delay=25s');
    }

    if (function_exists('spawn_cron')) {
        @spawn_cron(time());
    }
}

add_action('aismart_sync_featured_image_event', 'aismart_sync_featured_image_event_handler', 10, 2);
function aismart_sync_featured_image_event_handler($post_id, $attempt = 0) {
    $post_id = (int) $post_id;
    if ($post_id <= 0) {
        return;
    }
    aismart_sync_featured_image_to_translations($post_id);
}

function aismart_find_falang_translation_targets($post_id) {
    $post_id = (int) $post_id;
    if ($post_id <= 0) {
        return [];
    }

    if (!function_exists('falang_languages_list') && !class_exists('Falang', false) && !taxonomy_exists('language')) {
        return [];
    }

    global $wpdb;

    $source_post = get_post($post_id);
    if (!$source_post || $source_post->post_type !== 'post') {
        return [];
    }

    $targets = [];

    $meta_children = get_posts([
        'post_type' => 'post',
        'post_status' => ['publish', 'draft', 'pending', 'future', 'private'],
        'numberposts' => -1,
        'fields' => 'ids',
        'meta_query' => [
            [
                'key' => '_aismart_source_post_id',
                'value' => $post_id,
                'compare' => '=',
                'type' => 'NUMERIC',
            ],
        ],
    ]);

    if (is_array($meta_children)) {
        foreach ($meta_children as $child_id) {
            $child_id = (int) $child_id;
            if ($child_id > 0 && $child_id !== $post_id) {
                $targets[] = $child_id;
            }
        }
    }

    $source_slug = (string) $source_post->post_name;
    if ($source_slug !== '') {
        $rows = $wpdb->get_col($wpdb->prepare(
            "SELECT p.ID
             FROM {$wpdb->posts} p
             INNER JOIN {$wpdb->postmeta} pm ON pm.post_id = p.ID AND pm.meta_key = %s
             WHERE p.post_type = %s
               AND p.post_name = %s
               AND p.ID <> %d
               AND p.post_status IN ('publish','draft','pending','future','private')
               AND pm.meta_value <> ''
               AND pm.meta_value <> 'all'",
            '_locale',
            'post',
            $source_slug,
            $post_id
        ));

        if (is_array($rows)) {
            foreach ($rows as $row_id) {
                $row_id = (int) $row_id;
                if ($row_id > 0 && $row_id !== $post_id) {
                    $targets[] = $row_id;
                }
            }
        }
    }

    return array_values(array_unique(array_map('intval', $targets)));
}

function aismart_get_falang_language_pairs() {
    $languages = [];

    if (function_exists('falang_languages_list')) {
        $raw_languages = (array) falang_languages_list(['hide_default' => false]);
        foreach ($raw_languages as $language) {
            $locale = '';
            $slug = '';

            if (is_object($language)) {
                $locale = isset($language->locale) ? (string) $language->locale : '';
                $slug = isset($language->slug) ? (string) $language->slug : '';
            } elseif (is_array($language)) {
                $locale = isset($language['locale']) ? (string) $language['locale'] : '';
                $slug = isset($language['slug']) ? (string) $language['slug'] : '';
            }

            $locale = sanitize_text_field($locale);
            $slug = sanitize_title($slug);
            if ($locale === '' && $slug === '') {
                continue;
            }

            if ($locale === '') {
                $locale = $slug;
            }

            $languages[$locale] = [
                'locale' => $locale,
                'slug' => $slug,
            ];
        }
    }

    if (empty($languages) && taxonomy_exists('language')) {
        $terms = get_terms([
            'taxonomy' => 'language',
            'hide_empty' => false,
        ]);
        if (!is_wp_error($terms) && is_array($terms)) {
            foreach ($terms as $term) {
                if (!($term instanceof WP_Term)) {
                    continue;
                }
                $slug = sanitize_title((string) $term->slug);
                if ($slug === '') {
                    continue;
                }
                $languages[$slug] = [
                    'locale' => $slug,
                    'slug' => $slug,
                ];
            }
        }
    }

    return array_values($languages);
}

function aismart_get_falang_meta_prefix($locale) {
    $locale = sanitize_text_field((string) $locale);
    if ($locale === '') {
        return '';
    }

    if (class_exists('\\Falang\\Core\\Falang_Core') && method_exists('\\Falang\\Core\\Falang_Core', 'get_prefix')) {
        $prefix = (string) \Falang\Core\Falang_Core::get_prefix($locale);
        if ($prefix !== '') {
            return $prefix;
        }
    }

    return '_' . $locale . '_';
}

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

    $delays = [2, 12, 35];
    foreach ($delays as $index => $delay) {
        $args = [$post_id, (int) $index];
        if (!wp_next_scheduled('aismart_sync_featured_image_event', $args)) {
            wp_schedule_single_event(time() + (int) $delay, 'aismart_sync_featured_image_event', $args);
        }
    }

    if (function_exists('spawn_cron')) {
        @spawn_cron(time());
    }
}

function aismart_get_cloneable_theme_meta_keys() {
    return [
        '_fusion',
        '_wp_page_template',
        '_et_pb_use_builder',
        '_elementor_data',
        '_elementor_page_settings',
        '_elementor_edit_mode',
        '_wpb_shortcodes_custom_css',
        '_wpb_post_custom_css',
    ];
}

function aismart_sync_theme_meta_to_post($source_post_id, $target_post_id) {
    $source_post_id = (int) $source_post_id;
    $target_post_id = (int) $target_post_id;
    if ($source_post_id <= 0 || $target_post_id <= 0 || $source_post_id === $target_post_id) {
        return 0;
    }

    if (!get_post($source_post_id) || !get_post($target_post_id)) {
        return 0;
    }

    $updated = 0;
    $keys = aismart_get_cloneable_theme_meta_keys();
    foreach ($keys as $meta_key) {
        $meta_key = (string) $meta_key;
        if ($meta_key === '') {
            continue;
        }

        $source_value = get_post_meta($source_post_id, $meta_key, true);
        if ($source_value === '' || $source_value === null) {
            if (metadata_exists('post', $target_post_id, $meta_key)) {
                delete_post_meta($target_post_id, $meta_key);
                $updated++;
            }
            continue;
        }

        if (update_post_meta($target_post_id, $meta_key, $source_value) !== false) {
            $updated++;
        }
    }

    return $updated;
}

add_action('save_post_post', 'aismart_sync_featured_image_on_post_save', 20, 3);
function aismart_sync_featured_image_on_post_save($post_id, $post, $update) {
    $post_id = (int) $post_id;
    if ($post_id <= 0 || !$post || $post->post_type !== 'post') {
        return;
    }

    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
        return;
    }

    if (wp_is_post_revision($post_id) || wp_is_post_autosave($post_id)) {
        return;
    }

    if ((int) get_post_meta($post_id, '_aismart_source_post_id', true) > 0) {
        return;
    }

    $locale = sanitize_text_field((string) get_post_meta($post_id, '_locale', true));
    if ($locale !== '' && strcasecmp($locale, 'all') !== 0) {
        return;
    }

    aismart_schedule_featured_image_sync($post_id);
}

function aismart_maybe_schedule_featured_image_sync_on_thumbnail_meta($object_id, $meta_key) {
    $object_id = (int) $object_id;
    $meta_key = (string) $meta_key;
    if ($object_id <= 0 || $meta_key !== '_thumbnail_id') {
        return;
    }

    $post = get_post($object_id);
    if (!$post || $post->post_type !== 'post') {
        return;
    }

    if ((int) get_post_meta($object_id, '_aismart_source_post_id', true) > 0) {
        return;
    }

    $locale = sanitize_text_field((string) get_post_meta($object_id, '_locale', true));
    if ($locale !== '' && strcasecmp($locale, 'all') !== 0) {
        return;
    }

    aismart_schedule_featured_image_sync($object_id);
}

add_action('added_post_meta', 'aismart_maybe_schedule_featured_image_sync_on_meta_added', 20, 4);
function aismart_maybe_schedule_featured_image_sync_on_meta_added($meta_id, $object_id, $meta_key, $meta_value) {
    aismart_maybe_schedule_featured_image_sync_on_thumbnail_meta((int) $object_id, (string) $meta_key);
}

add_action('updated_post_meta', 'aismart_maybe_schedule_featured_image_sync_on_meta_updated', 20, 4);
function aismart_maybe_schedule_featured_image_sync_on_meta_updated($meta_id, $object_id, $meta_key, $meta_value) {
    aismart_maybe_schedule_featured_image_sync_on_thumbnail_meta((int) $object_id, (string) $meta_key);
}

function aismart_sync_featured_image_to_translations($post_id) {
    $post_id = (int) $post_id;
    if ($post_id <= 0 || !get_post($post_id)) {
        return false;
    }

    $source_thumbnail_id = (int) get_post_thumbnail_id($post_id);
    if ($source_thumbnail_id <= 0) {
        return false;
    }

    $falang_meta_updates = 0;
    if (function_exists('falang_languages_list') || class_exists('Falang', false) || taxonomy_exists('language')) {
        $falang_languages = aismart_get_falang_language_pairs();
        $source_locale = sanitize_text_field((string) get_post_meta($post_id, '_locale', true));
        if ($source_locale === '' || strcasecmp($source_locale, 'all') === 0) {
            if (function_exists('falang_default_language')) {
                $source_locale = sanitize_text_field((string) falang_default_language('locale'));
            }
        }

        foreach ($falang_languages as $language) {
            $target_locale = sanitize_text_field((string) ($language['locale'] ?? ''));
            if ($target_locale === '' || strcasecmp($target_locale, $source_locale) === 0) {
                continue;
            }

            $prefix = aismart_get_falang_meta_prefix($target_locale);
            if ($prefix === '') {
                continue;
            }

            if (update_post_meta($post_id, $prefix . 'thumbnail_id', $source_thumbnail_id) !== false) {
                $falang_meta_updates++;
            }
            if (update_post_meta($post_id, $prefix . '_thumbnail_id', $source_thumbnail_id) !== false) {
                $falang_meta_updates++;
            }
            update_post_meta($post_id, $prefix . 'published', '1');
        }
    }

    $target_ids = [];

    if (function_exists('pll_get_post_translations')) {
        $translations = (array) pll_get_post_translations($post_id);
        foreach ($translations as $translated_id) {
            $translated_id = (int) $translated_id;
            if ($translated_id > 0 && $translated_id !== $post_id) {
                $target_ids[] = $translated_id;
            }
        }
    }

    $meta_children = get_posts([
        'post_type' => 'post',
        'post_status' => ['publish', 'draft', 'pending', 'future', 'private'],
        'numberposts' => -1,
        'fields' => 'ids',
        'meta_query' => [
            [
                'key' => '_aismart_source_post_id',
                'value' => $post_id,
                'compare' => '=',
                'type' => 'NUMERIC',
            ],
        ],
    ]);
    if (is_array($meta_children)) {
        foreach ($meta_children as $child_id) {
            $child_id = (int) $child_id;
            if ($child_id > 0 && $child_id !== $post_id) {
                $target_ids[] = $child_id;
            }
        }
    }

    if (function_exists('apply_filters')) {
        $trid = apply_filters('wpml_element_trid', null, $post_id, 'post_post');
        if ($trid) {
            $translations = apply_filters('wpml_get_element_translations', null, $trid, 'post_post');
            if (is_array($translations)) {
                foreach ($translations as $translation) {
                    $translated_id = isset($translation->element_id) ? (int) $translation->element_id : 0;
                    if ($translated_id > 0 && $translated_id !== $post_id) {
                        $target_ids[] = $translated_id;
                    }
                }
            }
        }
    }

    $falang_target_ids = aismart_find_falang_translation_targets($post_id);
    if (!empty($falang_target_ids)) {
        foreach ($falang_target_ids as $falang_target_id) {
            $falang_target_id = (int) $falang_target_id;
            if ($falang_target_id > 0 && $falang_target_id !== $post_id) {
                $target_ids[] = $falang_target_id;
            }
        }
    }

    $target_ids = array_values(array_unique(array_map('intval', $target_ids)));
    if (empty($target_ids) && $falang_meta_updates > 0) {
        aismart_queue_log('Featured image Falang meta sync source_post_id=' . $post_id . ' attachment_id=' . $source_thumbnail_id . ' locales_updated=' . $falang_meta_updates);
    }

    $updated = 0;
    $theme_meta_updates = 0;
    foreach ($target_ids as $target_id) {
        if ($target_id <= 0 || !get_post($target_id)) {
            continue;
        }
        if (set_post_thumbnail($target_id, $source_thumbnail_id)) {
            $updated++;
        }

        $theme_meta_updates += (int) aismart_sync_theme_meta_to_post($post_id, $target_id);

        if (!empty($falang_target_ids) && in_array($target_id, $falang_target_ids, true)) {
            $target_post = get_post($target_id);
            if ($target_post) {
                $original_content = (string) $target_post->post_content;
                $cleaned_content = aismart_cleanup_translated_post_content($original_content);
                if ($cleaned_content !== '' && $cleaned_content !== $original_content) {
                    wp_update_post([
                        'ID' => $target_id,
                        'post_content' => $cleaned_content,
                    ]);
                }
            }
        }
    }

    $mlp_updated = 0;
    if (is_multisite()) {
        global $wpdb;
        $source_blog_id = (int) get_current_blog_id();
        $source_attachment_url = (string) wp_get_attachment_url($source_thumbnail_id);
        $link_table = $wpdb->base_prefix . 'multilingual_linked';
        $mlp_rows = $wpdb->get_results($wpdb->prepare(
            "SELECT ml_blogid, ml_elementid FROM {$link_table} WHERE ml_source_blogid = %d AND ml_source_elementid = %d AND ml_type = 'post'",
            $source_blog_id,
            $post_id
        ));

        if (is_array($mlp_rows)) {
            foreach ($mlp_rows as $mlp_row) {
                $target_blog_id = isset($mlp_row->ml_blogid) ? (int) $mlp_row->ml_blogid : 0;
                $target_post_id = isset($mlp_row->ml_elementid) ? (int) $mlp_row->ml_elementid : 0;
                if ($target_blog_id <= 0 || $target_post_id <= 0 || $target_blog_id === $source_blog_id) {
                    continue;
                }

                switch_to_blog($target_blog_id);
                if (!get_post($target_post_id)) {
                    restore_current_blog();
                    continue;
                }

                $target_attachment_id = aismart_mlp_ensure_attachment_on_target_blog($source_thumbnail_id, $source_blog_id, $source_attachment_url);
                if ($target_attachment_id > 0 && set_post_thumbnail($target_post_id, $target_attachment_id)) {
                    $mlp_updated++;
                }
                restore_current_blog();
            }
        }
    }

    aismart_queue_log('Featured image sync source_post_id=' . $post_id . ' attachment_id=' . $source_thumbnail_id . ' targets=' . count($target_ids) . ' updated=' . $updated . ' mlp_updated=' . $mlp_updated . ' falang_meta_updates=' . $falang_meta_updates . ' theme_meta_updates=' . $theme_meta_updates);
    return ($updated > 0) || ($mlp_updated > 0) || ($falang_meta_updates > 0);
}

function aismart_qtranslate_extract_segment($content, $lang) {
    $content = (string) $content;
    $lang = strtolower(sanitize_text_field((string) $lang));
    if ($content === '' || $lang === '') {
        return '';
    }

    $pattern = '/\[:' . preg_quote($lang, '/') . '\](.*?)(?=(\[:[a-z]{2}(?:[-_][a-zA-Z]{2,5})?\]|\[:\]))/su';
    if (preg_match($pattern, $content, $m) && isset($m[1])) {
        return (string) $m[1];
    }

    return '';
}

function aismart_qtranslate_wrap_segments($segments, $source_lang = 'en') {
    if (!is_array($segments) || empty($segments)) {
        return '';
    }

    $source_lang = strtolower(sanitize_text_field((string) $source_lang));
    $ordered = [];
    if ($source_lang !== '' && isset($segments[$source_lang])) {
        $ordered[$source_lang] = (string) $segments[$source_lang];
    }
    foreach ($segments as $lang => $value) {
        $lang = strtolower(sanitize_text_field((string) $lang));
        if ($lang === '' || isset($ordered[$lang])) {
            continue;
        }
        $ordered[$lang] = (string) $value;
    }

    if (empty($ordered)) {
        return '';
    }

    $out = '';
    foreach ($ordered as $lang => $value) {
        $out .= '[:' . $lang . ']' . (string) $value;
    }
    $out .= '[:]';

    return $out;
}

function aismart_bogo_locale_to_lang_code($locale) {
    $locale = sanitize_text_field((string) $locale);
    if ($locale === '') {
        return '';
    }

    if (function_exists('bogo_lang_slug')) {
        $slug = strtolower(sanitize_key((string) bogo_lang_slug($locale)));
        if ($slug !== '') {
            return $slug;
        }
    }

    $normalized = str_replace('-', '_', $locale);
    if (strpos($normalized, '_') !== false) {
        $normalized = (string) strtok($normalized, '_');
    }

    return strtolower(sanitize_key($normalized));
}

function aismart_bogo_filter_use_implicit_lang($use_implicit_lang) {
    if (aismart_should_force_default_lang_prefix('bogo')) {
        update_option('aismart_bogo_use_implicit_lang', 0, false);
        return false;
    }

    update_option('aismart_bogo_use_implicit_lang', $use_implicit_lang ? 1 : 0, false);
    return $use_implicit_lang;
}
add_filter('bogo_use_implicit_lang', 'aismart_bogo_filter_use_implicit_lang', 20, 1);

function aismart_get_wpglobus_enabled_languages() {
    $wpglobus_option = get_option('wpglobus_option', []);
    $enabled_raw = is_array($wpglobus_option) && isset($wpglobus_option['enabled_languages']) && is_array($wpglobus_option['enabled_languages'])
        ? (array) $wpglobus_option['enabled_languages']
        : [];

    $enabled = [];
    foreach ($enabled_raw as $lang_key => $lang_value) {
        $code = is_string($lang_key) ? $lang_key : (string) $lang_value;
        $code = strtolower(sanitize_text_field($code));
        if ($code === '') {
            continue;
        }

        if (empty($lang_value) && !is_string($lang_key)) {
            continue;
        }

        $enabled[] = $code;
    }

    return array_values(array_unique($enabled));
}

function aismart_translate_qtranslate_native($post_id) {
    $post_id = (int) $post_id;
    if ($post_id <= 0) {
        return false;
    }

    $post = get_post($post_id);
    if (!$post || $post->post_type !== 'post' || $post->post_status !== 'publish') {
        aismart_queue_log('Native qTranslate skip: post not eligible post_id=' . $post_id);
        return false;
    }

    $enabled = get_option('qtranslate_enabled_languages', []);
    if (!is_array($enabled)) {
        $enabled = [];
    }
    if (empty($enabled) && !empty($GLOBALS['q_config']) && is_array($GLOBALS['q_config']) && !empty($GLOBALS['q_config']['enabled_languages']) && is_array($GLOBALS['q_config']['enabled_languages'])) {
        $enabled = (array) $GLOBALS['q_config']['enabled_languages'];
    }
    $enabled = array_values(array_unique(array_filter(array_map(static function ($code) {
        return strtolower(sanitize_text_field((string) $code));
    }, (array) $enabled))));

    if (empty($enabled)) {
        aismart_queue_log('Native qTranslate skip: no enabled languages post_id=' . $post_id);
        return false;
    }

    $source_lang = strtolower(sanitize_text_field((string) get_option('qtranslate_default_language', '')));
    if ($source_lang === '' || !in_array($source_lang, $enabled, true)) {
        $source_lang = in_array('en', $enabled, true) ? 'en' : (string) $enabled[0];
    }

    $source_title = aismart_qtranslate_extract_segment((string) $post->post_title, $source_lang);
    if ($source_title === '') {
        $source_title = (string) $post->post_title;
    }
    $source_title = aismart_normalize_post_title($source_title);

    $source_excerpt = aismart_qtranslate_extract_segment((string) $post->post_excerpt, $source_lang);
    if ($source_excerpt === '') {
        $source_excerpt = (string) $post->post_excerpt;
    }

    $source_content = aismart_qtranslate_extract_segment((string) $post->post_content, $source_lang);
    if ($source_content === '') {
        $source_content = (string) $post->post_content;
    }

    $title_segments = [$source_lang => $source_title];
    $excerpt_segments = [$source_lang => $source_excerpt];
    $content_segments = [$source_lang => $source_content];

    foreach ($enabled as $lang_code) {
        if ($lang_code === '' || $lang_code === $source_lang) {
            continue;
        }

        $translated_title = aismart_translate_text_google($source_title, $lang_code, $source_lang, false);
        $translated_title = aismart_cleanup_translated_plain_text($translated_title);
        $translated_title = aismart_normalize_post_title($translated_title);
        if ($translated_title === '') {
            $translated_title = $source_title;
        }

        $translated_excerpt = aismart_translate_text_google($source_excerpt, $lang_code, $source_lang, false);
        $translated_excerpt = aismart_cleanup_translated_plain_text($translated_excerpt);
        if ($translated_excerpt === '') {
            $translated_excerpt = $source_excerpt;
        }

        $translated_content = aismart_translate_post_content_google($source_content, $lang_code, $source_lang);
        $translated_content = aismart_cleanup_translated_post_content($translated_content);
        if ($translated_content === '') {
            $translated_content = $source_content;
        }

        $title_segments[$lang_code] = $translated_title;
        $excerpt_segments[$lang_code] = $translated_excerpt;
        $content_segments[$lang_code] = $translated_content;
    }

    $wrapped_title = aismart_qtranslate_wrap_segments($title_segments, $source_lang);
    $wrapped_excerpt = aismart_qtranslate_wrap_segments($excerpt_segments, $source_lang);
    $wrapped_content = aismart_qtranslate_wrap_segments($content_segments, $source_lang);

    $update_result = wp_update_post([
        'ID' => $post_id,
        'post_title' => $wrapped_title,
        'post_excerpt' => $wrapped_excerpt,
        'post_content' => $wrapped_content,
    ], true);

    if (is_wp_error($update_result)) {
        aismart_queue_log('Native qTranslate update failed post_id=' . $post_id . ' error=' . $update_result->get_error_message());
        return false;
    }

    update_post_meta($post_id, '_aismart_translation_queued', 1);
    update_post_meta($post_id, '_aismart_translation_queue_last_at', gmdate('c'));

    aismart_queue_log('Native qTranslate translated post_id=' . $post_id . ' source=' . $source_lang . ' targets=' . implode(',', array_values(array_diff($enabled, [$source_lang]))));
    return true;
}

function aismart_translate_wpglobus_native($post_id) {
    $post_id = (int) $post_id;
    if ($post_id <= 0) {
        return false;
    }

    $post = get_post($post_id);
    if (!$post || $post->post_type !== 'post' || $post->post_status !== 'publish') {
        aismart_queue_log('Native WPGlobus skip: post not eligible post_id=' . $post_id);
        return false;
    }

    $enabled = aismart_get_wpglobus_enabled_languages();
    if (empty($enabled)) {
        aismart_queue_log('Native WPGlobus skip: no enabled languages post_id=' . $post_id);
        return false;
    }

    $source_lang = '';
    if (is_array(get_option('wpglobus_option', []))) {
        $wpglobus_option = get_option('wpglobus_option', []);
        if (isset($wpglobus_option['default_language']) && is_scalar($wpglobus_option['default_language'])) {
            $source_lang = strtolower(sanitize_text_field((string) $wpglobus_option['default_language']));
        }
    }
    if ($source_lang === '' || !in_array($source_lang, $enabled, true)) {
        $source_lang = in_array('en', $enabled, true) ? 'en' : (string) $enabled[0];
    }

    $source_title = aismart_qtranslate_extract_segment((string) $post->post_title, $source_lang);
    if ($source_title === '') {
        $source_title = (string) $post->post_title;
    }
    $source_title = aismart_normalize_post_title($source_title);

    $source_excerpt = aismart_qtranslate_extract_segment((string) $post->post_excerpt, $source_lang);
    if ($source_excerpt === '') {
        $source_excerpt = (string) $post->post_excerpt;
    }

    $source_content = aismart_qtranslate_extract_segment((string) $post->post_content, $source_lang);
    if ($source_content === '') {
        $source_content = (string) $post->post_content;
    }

    $title_segments = [$source_lang => $source_title];
    $excerpt_segments = [$source_lang => $source_excerpt];
    $content_segments = [$source_lang => $source_content];

    foreach ($enabled as $lang_code) {
        if ($lang_code === '' || $lang_code === $source_lang) {
            continue;
        }

        $translated_title = aismart_translate_text_google($source_title, $lang_code, $source_lang, false);
        $translated_title = aismart_cleanup_translated_plain_text($translated_title);
        $translated_title = aismart_normalize_post_title($translated_title);
        if ($translated_title === '') {
            $translated_title = $source_title;
        }

        $translated_excerpt = aismart_translate_text_google($source_excerpt, $lang_code, $source_lang, false);
        $translated_excerpt = aismart_cleanup_translated_plain_text($translated_excerpt);
        if ($translated_excerpt === '') {
            $translated_excerpt = $source_excerpt;
        }

        $translated_content = aismart_translate_post_content_google($source_content, $lang_code, $source_lang);
        $translated_content = aismart_cleanup_translated_post_content($translated_content);
        if ($translated_content === '') {
            $translated_content = $source_content;
        }

        $title_segments[$lang_code] = $translated_title;
        $excerpt_segments[$lang_code] = $translated_excerpt;
        $content_segments[$lang_code] = $translated_content;
    }

    $wrapped_title = aismart_qtranslate_wrap_segments($title_segments, $source_lang);
    $wrapped_excerpt = aismart_qtranslate_wrap_segments($excerpt_segments, $source_lang);
    $wrapped_content = aismart_qtranslate_wrap_segments($content_segments, $source_lang);

    $update_result = wp_update_post([
        'ID' => $post_id,
        'post_title' => $wrapped_title,
        'post_excerpt' => $wrapped_excerpt,
        'post_content' => $wrapped_content,
    ], true);

    if (is_wp_error($update_result)) {
        aismart_queue_log('Native WPGlobus update failed post_id=' . $post_id . ' error=' . $update_result->get_error_message());
        return false;
    }

    update_post_meta($post_id, '_aismart_translation_queued', 1);
    update_post_meta($post_id, '_aismart_translation_queue_last_at', gmdate('c'));

    aismart_queue_log('Native WPGlobus translated post_id=' . $post_id . ' source=' . $source_lang . ' targets=' . implode(',', array_values(array_diff($enabled, [$source_lang]))));
    return true;
}

function aismart_translate_bogo_native($post_id) {
    $post_id = (int) $post_id;
    if ($post_id <= 0) {
        return false;
    }

    if (!function_exists('bogo_available_locales') || !function_exists('bogo_get_post_locale')) {
        aismart_queue_log('Native Bogo skip: Bogo APIs unavailable post_id=' . $post_id);
        return false;
    }

    $root_source_id = (int) get_post_meta($post_id, '_aismart_source_post_id', true);
    if ($root_source_id > 0 && $root_source_id !== $post_id) {
        aismart_queue_log('Native Bogo remap child request post_id=' . $post_id . ' source_id=' . $root_source_id);
        $post_id = $root_source_id;
    }

    $post = get_post($post_id);
    if (!$post || $post->post_type !== 'post' || $post->post_status !== 'publish') {
        aismart_queue_log('Native Bogo skip: post not eligible post_id=' . $post_id);
        return false;
    }

    if (aismart_is_non_source_translation_post($post_id)) {
        aismart_queue_log('Native Bogo skip: non-source translation post_id=' . $post_id);
        return false;
    }

    $locales = array_values(array_unique(array_filter(array_map(static function ($locale) {
        return sanitize_text_field((string) $locale);
    }, (array) bogo_available_locales()))));

    if (empty($locales)) {
        aismart_queue_log('Native Bogo skip: no active locales post_id=' . $post_id);
        return false;
    }

    $source_locale = sanitize_text_field((string) bogo_get_post_locale($post_id));
    if ($source_locale === '' || !in_array($source_locale, $locales, true)) {
        $source_locale = in_array('en_US', $locales, true) ? 'en_US' : (string) $locales[0];
    }
    $source_lang = aismart_bogo_locale_to_lang_code($source_locale);
    if ($source_lang === '') {
        $source_lang = 'en';
    }

    $source_title = aismart_normalize_post_title((string) $post->post_title);
    $source_excerpt = (string) $post->post_excerpt;
    $source_content = (string) $post->post_content;
    $source_thumbnail_id = (int) get_post_thumbnail_id($post_id);

    $processed = 0;
    foreach ($locales as $target_locale) {
        $target_locale = sanitize_text_field((string) $target_locale);
        if ($target_locale === '' || $target_locale === $source_locale) {
            continue;
        }

        $target_lang = aismart_bogo_locale_to_lang_code($target_locale);
        if ($target_lang === '') {
            continue;
        }

        $target_id = 0;
        if (function_exists('bogo_get_post_translation')) {
            $existing = bogo_get_post_translation($post_id, $target_locale);
            if ($existing instanceof WP_Post) {
                $target_id = (int) $existing->ID;
            }
        }

        if ($target_id <= 0) {
            $existing_candidates = get_posts([
                'post_type' => 'post',
                'post_status' => ['publish', 'draft', 'pending', 'future', 'private'],
                'numberposts' => 1,
                'orderby' => 'ID',
                'order' => 'ASC',
                'meta_query' => [
                    [
                        'key' => '_aismart_source_post_id',
                        'value' => $post_id,
                        'compare' => '=',
                        'type' => 'NUMERIC',
                    ],
                    [
                        'key' => '_locale',
                        'value' => $target_locale,
                        'compare' => '=',
                    ],
                ],
                'fields' => 'ids',
            ]);
            if (!empty($existing_candidates)) {
                $target_id = (int) $existing_candidates[0];
            }
        }

        if ($target_id <= 0 && function_exists('bogo_duplicate_post')) {
            $target_id = (int) bogo_duplicate_post($post_id, $target_locale);
        }

        if ($target_id <= 0) {
            aismart_queue_log('Native Bogo: unable to create/find translation post locale=' . $target_locale . ' source_id=' . $post_id);
            continue;
        }

        $translated_title = aismart_translate_text_google($source_title, $target_lang, $source_lang, false);
        $translated_title = aismart_cleanup_translated_plain_text($translated_title);
        $translated_title = aismart_normalize_post_title($translated_title);
        if ($translated_title === '') {
            $translated_title = $source_title;
        }

        $translated_excerpt = aismart_translate_text_google($source_excerpt, $target_lang, $source_lang, false);
        $translated_excerpt = aismart_cleanup_translated_plain_text($translated_excerpt);
        if ($translated_excerpt === '') {
            $translated_excerpt = $source_excerpt;
        }

        $translated_content = aismart_translate_post_content_google($source_content, $target_lang, $source_lang);
        $translated_content = aismart_cleanup_translated_post_content($translated_content);
        if ($translated_content === '') {
            $translated_content = $source_content;
        }

        $update_result = wp_update_post([
            'ID' => $target_id,
            'post_status' => 'publish',
            'post_title' => $translated_title,
            'post_excerpt' => $translated_excerpt,
            'post_content' => $translated_content,
            'post_name' => (string) $post->post_name,
        ], true);

        if (is_wp_error($update_result)) {
            aismart_queue_log('Native Bogo update failed target_id=' . $target_id . ' locale=' . $target_locale . ' error=' . $update_result->get_error_message());
            continue;
        }

        update_post_meta($target_id, '_locale', $target_locale);
        update_post_meta($target_id, '_aismart_source_post_id', $post_id);
        update_post_meta($target_id, '_aismart_target_lang', $target_locale);

        if ($source_thumbnail_id > 0) {
            set_post_thumbnail($target_id, $source_thumbnail_id);
        }

        aismart_sync_theme_meta_to_post($post_id, $target_id);

        $category_ids = wp_get_post_categories($post_id);
        if (!empty($category_ids)) {
            wp_set_post_categories($target_id, $category_ids, false);
        }

        $tags = wp_get_post_tags($post_id, ['fields' => 'names']);
        if (!empty($tags)) {
            wp_set_post_tags($target_id, $tags, false);
        }

        $processed++;
        aismart_queue_log('Native Bogo translated source_id=' . $post_id . ' target_id=' . $target_id . ' locale=' . $target_locale . ' lang=' . $target_lang);
    }

    if ($processed > 0) {
        update_post_meta($post_id, '_aismart_translation_queued', 1);
        update_post_meta($post_id, '_aismart_translation_queue_last_at', gmdate('c'));
    }

    return $processed > 0;
}

function aismart_mlp_lang_code_from_locale($locale) {
    $locale = strtolower(sanitize_text_field((string) $locale));
    if ($locale === '') {
        return '';
    }

    $normalized = str_replace('-', '_', $locale);
    $parts = explode('_', $normalized);
    $lang = isset($parts[0]) ? sanitize_key((string) $parts[0]) : '';

    return $lang !== '' ? $lang : $normalized;
}

function aismart_mlp_get_related_site_ids($source_blog_id) {
    global $wpdb;

    $source_blog_id = (int) $source_blog_id;
    if ($source_blog_id <= 0) {
        return [];
    }

    $table = $wpdb->base_prefix . 'mlp_site_relations';
    $sql = $wpdb->prepare(
        "SELECT DISTINCT IF(site_1 = %d, site_2, site_1) AS blog_id FROM {$table} WHERE site_1 = %d OR site_2 = %d",
        $source_blog_id,
        $source_blog_id,
        $source_blog_id
    );
    $rows = (array) $wpdb->get_col($sql);

    $related = [];
    foreach ($rows as $row_id) {
        $id = (int) $row_id;
        if ($id > 0 && $id !== $source_blog_id) {
            $related[] = $id;
        }
    }

    return array_values(array_unique($related));
}

function aismart_mlp_upsert_content_relation($source_blog_id, $source_post_id, $target_blog_id, $target_post_id) {
    global $wpdb;

    $source_blog_id = (int) $source_blog_id;
    $source_post_id = (int) $source_post_id;
    $target_blog_id = (int) $target_blog_id;
    $target_post_id = (int) $target_post_id;

    if ($source_blog_id <= 0 || $source_post_id <= 0 || $target_blog_id <= 0 || $target_post_id <= 0) {
        return false;
    }

    $table = $wpdb->base_prefix . 'multilingual_linked';

    $ensure = static function ($blog_id, $post_id) use ($wpdb, $table, $source_blog_id, $source_post_id) {
        $exists = (int) $wpdb->get_var($wpdb->prepare(
            "SELECT ml_id FROM {$table} WHERE ml_source_blogid = %d AND ml_source_elementid = %d AND ml_blogid = %d AND ml_type = 'post' LIMIT 1",
            $source_blog_id,
            $source_post_id,
            (int) $blog_id
        ));

        if ($exists > 0) {
            $wpdb->update(
                $table,
                ['ml_elementid' => (int) $post_id],
                ['ml_id' => $exists],
                ['%d'],
                ['%d']
            );

            return;
        }

        $wpdb->insert(
            $table,
            [
                'ml_source_blogid' => $source_blog_id,
                'ml_source_elementid' => $source_post_id,
                'ml_blogid' => (int) $blog_id,
                'ml_elementid' => (int) $post_id,
                'ml_type' => 'post',
            ],
            ['%d', '%d', '%d', '%d', '%s']
        );
    };

    $ensure($source_blog_id, $source_post_id);
    $ensure($target_blog_id, $target_post_id);

    return true;
}

function aismart_mlp_ensure_attachment_on_target_blog($source_attachment_id, $source_blog_id, $source_attachment_url = '') {
    $source_attachment_id = (int) $source_attachment_id;
    $source_blog_id = (int) $source_blog_id;

    if ($source_attachment_id <= 0 || $source_blog_id <= 0) {
        return 0;
    }

    $current_blog_id = (int) get_current_blog_id();
    if ($current_blog_id === $source_blog_id) {
        return $source_attachment_id;
    }

    $existing = get_posts([
        'post_type' => 'attachment',
        'post_status' => 'inherit',
        'numberposts' => 1,
        'orderby' => 'ID',
        'order' => 'ASC',
        'fields' => 'ids',
        'meta_query' => [
            [
                'key' => '_aismart_source_attachment_id',
                'value' => $source_attachment_id,
                'compare' => '=',
                'type' => 'NUMERIC',
            ],
            [
                'key' => '_aismart_source_blog_id',
                'value' => $source_blog_id,
                'compare' => '=',
                'type' => 'NUMERIC',
            ],
        ],
    ]);
    if (!empty($existing)) {
        return (int) $existing[0];
    }

    if ($source_attachment_url === '') {
        switch_to_blog($source_blog_id);
        $source_attachment_url = (string) wp_get_attachment_url($source_attachment_id);
        restore_current_blog();
    }

    $source_attachment_url = esc_url_raw((string) $source_attachment_url);
    if ($source_attachment_url === '') {
        return 0;
    }

    if (!function_exists('media_sideload_image')) {
        require_once ABSPATH . 'wp-admin/includes/media.php';
    }
    if (!function_exists('download_url')) {
        require_once ABSPATH . 'wp-admin/includes/file.php';
    }
    if (!function_exists('wp_generate_attachment_metadata')) {
        require_once ABSPATH . 'wp-admin/includes/image.php';
    }

    $new_attachment_id = media_sideload_image($source_attachment_url, 0, null, 'id');
    if (is_wp_error($new_attachment_id) || (int) $new_attachment_id <= 0) {
        aismart_queue_log('Native MultilingualPress featured image sideload failed source_attachment_id=' . $source_attachment_id . ' source_blog=' . $source_blog_id . ' target_blog=' . $current_blog_id . ' error=' . (is_wp_error($new_attachment_id) ? $new_attachment_id->get_error_message() : 'unknown'));
        return 0;
    }

    $new_attachment_id = (int) $new_attachment_id;
    update_post_meta($new_attachment_id, '_aismart_source_attachment_id', $source_attachment_id);
    update_post_meta($new_attachment_id, '_aismart_source_blog_id', $source_blog_id);

    return $new_attachment_id;
}

function aismart_translate_multilingualpress_native($post_id) {
    $post_id = (int) $post_id;
    if ($post_id <= 0 || !is_multisite()) {
        return false;
    }

    $source_post = get_post($post_id);
    if (!$source_post || $source_post->post_type !== 'post' || $source_post->post_status !== 'publish') {
        aismart_queue_log('Native MultilingualPress skip: post not eligible post_id=' . $post_id);
        return false;
    }

    $source_blog_id = (int) get_current_blog_id();
    $languages = (array) get_site_option('inpsyde_multilingual', []);
    if (empty($languages)) {
        aismart_queue_log('Native MultilingualPress skip: no inpsyde_multilingual mapping post_id=' . $post_id);
        return false;
    }

    $source_locale = '';
    if (isset($languages[$source_blog_id]) && is_array($languages[$source_blog_id])) {
        $source_locale = sanitize_text_field((string) ($languages[$source_blog_id]['lang'] ?? ''));
    }
    if ($source_locale === '') {
        $source_locale = 'en_US';
    }
    $source_lang = aismart_mlp_lang_code_from_locale($source_locale);
    if ($source_lang === '') {
        $source_lang = 'en';
    }

    $target_sites = aismart_mlp_get_related_site_ids($source_blog_id);
    if (empty($target_sites)) {
        foreach ($languages as $blog_id => $row) {
            $blog_id = (int) $blog_id;
            if ($blog_id > 0 && $blog_id !== $source_blog_id && !empty($row['lang'])) {
                $target_sites[] = $blog_id;
            }
        }
        $target_sites = array_values(array_unique($target_sites));
    }

    if (empty($target_sites)) {
        aismart_queue_log('Native MultilingualPress skip: no related target sites post_id=' . $post_id);
        return false;
    }

    $source_title = aismart_normalize_post_title((string) $source_post->post_title);
    $source_excerpt = (string) $source_post->post_excerpt;
    $source_content = (string) $source_post->post_content;
    $source_thumbnail_id = (int) get_post_thumbnail_id($post_id);
    $source_thumbnail_url = $source_thumbnail_id > 0 ? (string) wp_get_attachment_url($source_thumbnail_id) : '';

    $processed = 0;
    global $wpdb;
    $link_table = $wpdb->base_prefix . 'multilingual_linked';

    foreach ($target_sites as $target_blog_id) {
        $target_blog_id = (int) $target_blog_id;
        if ($target_blog_id <= 0 || $target_blog_id === $source_blog_id || !get_blog_details($target_blog_id)) {
            continue;
        }

        $target_locale = '';
        if (isset($languages[$target_blog_id]) && is_array($languages[$target_blog_id])) {
            $target_locale = sanitize_text_field((string) ($languages[$target_blog_id]['lang'] ?? ''));
        }
        if ($target_locale === '') {
            continue;
        }

        $target_lang = aismart_mlp_lang_code_from_locale($target_locale);
        if ($target_lang === '' || $target_lang === $source_lang) {
            continue;
        }

        $existing_target_id = (int) $wpdb->get_var($wpdb->prepare(
            "SELECT ml_elementid FROM {$link_table} WHERE ml_source_blogid = %d AND ml_source_elementid = %d AND ml_blogid = %d AND ml_type = 'post' LIMIT 1",
            $source_blog_id,
            $post_id,
            $target_blog_id
        ));

        switch_to_blog($target_blog_id);

        $target_post_id = 0;
        if ($existing_target_id > 0) {
            $existing_post = get_post($existing_target_id);
            if ($existing_post instanceof WP_Post) {
                $target_post_id = (int) $existing_post->ID;
            }
        }

        if ($target_post_id <= 0) {
            $candidate_ids = get_posts([
                'post_type' => 'post',
                'post_status' => ['publish', 'draft', 'pending', 'future', 'private'],
                'numberposts' => 1,
                'orderby' => 'ID',
                'order' => 'ASC',
                'meta_query' => [
                    [
                        'key' => '_aismart_source_post_id',
                        'value' => $post_id,
                        'compare' => '=',
                        'type' => 'NUMERIC',
                    ],
                    [
                        'key' => '_aismart_source_blog_id',
                        'value' => $source_blog_id,
                        'compare' => '=',
                        'type' => 'NUMERIC',
                    ],
                ],
                'fields' => 'ids',
            ]);
            if (!empty($candidate_ids)) {
                $target_post_id = (int) $candidate_ids[0];
            }
        }

        if ($target_post_id <= 0) {
            $target_post_id = (int) wp_insert_post([
                'post_type' => 'post',
                'post_status' => 'publish',
                'post_title' => $source_title,
                'post_excerpt' => $source_excerpt,
                'post_content' => $source_content,
            ], true);
        }

        if ($target_post_id <= 0 || is_wp_error($target_post_id)) {
            restore_current_blog();
            aismart_queue_log('Native MultilingualPress create failed source_id=' . $post_id . ' target_blog=' . $target_blog_id);
            continue;
        }

        $translated_title = aismart_translate_text_google($source_title, $target_lang, $source_lang, false);
        $translated_title = aismart_cleanup_translated_plain_text($translated_title);
        $translated_title = aismart_normalize_post_title($translated_title);
        if ($translated_title === '') {
            $translated_title = $source_title;
        }

        $translated_excerpt = aismart_translate_text_google($source_excerpt, $target_lang, $source_lang, false);
        $translated_excerpt = aismart_cleanup_translated_plain_text($translated_excerpt);
        if ($translated_excerpt === '') {
            $translated_excerpt = $source_excerpt;
        }

        $translated_content = aismart_translate_post_content_google($source_content, $target_lang, $source_lang);
        $translated_content = aismart_cleanup_translated_post_content($translated_content);
        if ($translated_content === '') {
            $translated_content = $source_content;
        }

        $update_result = wp_update_post([
            'ID' => $target_post_id,
            'post_status' => 'publish',
            'post_title' => $translated_title,
            'post_excerpt' => $translated_excerpt,
            'post_content' => $translated_content,
            'post_name' => (string) $source_post->post_name,
        ], true);

        if (is_wp_error($update_result)) {
            restore_current_blog();
            aismart_queue_log('Native MultilingualPress update failed target_id=' . $target_post_id . ' blog=' . $target_blog_id . ' error=' . $update_result->get_error_message());
            continue;
        }

        update_post_meta($target_post_id, '_aismart_source_post_id', $post_id);
        update_post_meta($target_post_id, '_aismart_source_blog_id', $source_blog_id);
        update_post_meta($target_post_id, '_aismart_target_lang', $target_locale);

        if ($source_thumbnail_id > 0) {
            $target_attachment_id = aismart_mlp_ensure_attachment_on_target_blog($source_thumbnail_id, $source_blog_id, $source_thumbnail_url);
            if ($target_attachment_id > 0) {
                set_post_thumbnail($target_post_id, $target_attachment_id);
            }
        }

        restore_current_blog();

        aismart_mlp_upsert_content_relation($source_blog_id, $post_id, $target_blog_id, $target_post_id);
        $processed++;
        aismart_queue_log('Native MultilingualPress translated source_id=' . $post_id . ' target_id=' . $target_post_id . ' target_blog=' . $target_blog_id . ' lang=' . $target_lang);
    }

    if ($processed > 0) {
        update_post_meta($post_id, '_aismart_translation_queued', 1);
        update_post_meta($post_id, '_aismart_translation_queue_last_at', gmdate('c'));
    }

    return $processed > 0;
}

function aismart_translate_wpml_native($post_id) {
    $post_id = (int) $post_id;
    if ($post_id <= 0) {
        return false;
    }

    $input_post = get_post($post_id);
    if (!$input_post || $input_post->post_type !== 'post' || $input_post->post_status !== 'publish') {
        aismart_queue_log('Native WPML skip: post not eligible post_id=' . $post_id);
        return false;
    }

    if (!function_exists('apply_filters')) {
        aismart_queue_log('Native WPML skip: apply_filters unavailable post_id=' . $post_id);
        return false;
    }

    $active_languages = apply_filters('wpml_active_languages', null, ['skip_missing' => 0]);
    if (!is_array($active_languages) || empty($active_languages)) {
        aismart_queue_log('Native WPML skip: no active languages post_id=' . $post_id);
        return false;
    }

    $source_post_id = $post_id;
    $source_lang = '';
    $translation_index = [];

    $trid = apply_filters('wpml_element_trid', null, $post_id, 'post_post');
    if ($trid) {
        $translations = apply_filters('wpml_get_element_translations', null, $trid, 'post_post');
        if (is_array($translations)) {
            foreach ($translations as $row) {
                if (!is_object($row)) {
                    continue;
                }

                $lang_code = sanitize_key((string) ($row->language_code ?? ''));
                $element_id = isset($row->element_id) ? (int) $row->element_id : 0;
                $src_lang = sanitize_key((string) ($row->source_language_code ?? ''));
                if ($lang_code !== '' && $element_id > 0) {
                    $translation_index[$lang_code] = $element_id;
                }

                if ($src_lang === '' && $lang_code !== '' && $element_id > 0) {
                    $source_post_id = $element_id;
                    $source_lang = $lang_code;
                }
            }
        }
    }

    $source_post = get_post($source_post_id);
    if (!$source_post || $source_post->post_type !== 'post') {
        aismart_queue_log('Native WPML skip: source post missing post_id=' . $post_id . ' resolved_source=' . $source_post_id);
        return false;
    }

    if ($source_lang === '') {
        $source_lang = sanitize_key((string) apply_filters('wpml_element_language_code', null, ['element_id' => $source_post_id, 'element_type' => 'post_post']));
    }
    if ($source_lang === '') {
        $source_lang = sanitize_key((string) apply_filters('wpml_default_language', null));
    }
    if ($source_lang === '') {
        $source_lang = 'en';
    }

    if (function_exists('do_action')) {
        do_action('wpml_make_post_duplicates', $source_post_id);
        do_action('wpml_admin_make_post_duplicates', $source_post_id);
    }

    $source_title = aismart_normalize_post_title((string) $source_post->post_title);
    $source_excerpt = (string) $source_post->post_excerpt;
    $source_content = (string) $source_post->post_content;
    $source_thumbnail_id = (int) get_post_thumbnail_id($source_post_id);

    $processed = 0;
    foreach ($active_languages as $lang_code => $lang_data) {
        $lang_code = sanitize_key((string) $lang_code);
        if ($lang_code === '' || $lang_code === $source_lang) {
            continue;
        }

        $child_id = isset($translation_index[$lang_code]) ? (int) $translation_index[$lang_code] : 0;
        if ($child_id <= 0) {
            $child_id = (int) apply_filters('wpml_object_id', $source_post_id, 'post', false, $lang_code);
        }
        if ($child_id === $source_post_id) {
            continue;
        }
        if ($child_id <= 0 || !get_post($child_id)) {
            aismart_queue_log('Native WPML skip target: missing child source_id=' . $source_post_id . ' lang=' . $lang_code);
            continue;
        }

        $translated_title = aismart_translate_text_google($source_title, $lang_code, $source_lang, false);
        $translated_title = aismart_cleanup_translated_plain_text($translated_title);
        $translated_title = aismart_normalize_post_title($translated_title);
        if ($translated_title === '') {
            $translated_title = $source_title;
        }

        $translated_excerpt = aismart_translate_text_google($source_excerpt, $lang_code, $source_lang, false);
        $translated_excerpt = aismart_cleanup_translated_plain_text($translated_excerpt);
        if ($translated_excerpt === '') {
            $translated_excerpt = $source_excerpt;
        }

        $translated_content = aismart_translate_post_content_google($source_content, $lang_code, $source_lang);
        $translated_content = aismart_cleanup_translated_post_content($translated_content);
        if ($translated_content === '') {
            $translated_content = $source_content;
        }

        $update_result = wp_update_post([
            'ID' => $child_id,
            'post_status' => 'publish',
            'post_title' => $translated_title,
            'post_excerpt' => $translated_excerpt,
            'post_content' => $translated_content,
            'post_name' => (string) $source_post->post_name,
        ], true);

        if (is_wp_error($update_result)) {
            aismart_queue_log('Native WPML update failed source_id=' . $source_post_id . ' target_id=' . $child_id . ' lang=' . $lang_code . ' error=' . $update_result->get_error_message());
            continue;
        }

        if ($source_thumbnail_id > 0) {
            set_post_thumbnail($child_id, $source_thumbnail_id);
        }

        aismart_sync_theme_meta_to_post($source_post_id, $child_id);

        $category_ids = wp_get_post_categories($source_post_id);
        if (!empty($category_ids)) {
            wp_set_post_categories($child_id, $category_ids, false);
        }

        $tags = wp_get_post_tags($source_post_id, ['fields' => 'names']);
        if (!empty($tags)) {
            wp_set_post_tags($child_id, $tags, false);
        }

        $processed++;
        aismart_queue_log('Native WPML translated source_id=' . $source_post_id . ' target_id=' . $child_id . ' lang=' . $lang_code . ' source_lang=' . $source_lang);
    }

    if ($processed > 0) {
        update_post_meta($source_post_id, '_aismart_translation_queued', 1);
        update_post_meta($source_post_id, '_aismart_translation_queue_last_at', gmdate('c'));
        if ($source_post_id !== $post_id) {
            update_post_meta($post_id, '_aismart_translation_queued', 1);
            update_post_meta($post_id, '_aismart_translation_queue_last_at', gmdate('c'));
        }
    }

    return $processed > 0;
}

function aismart_queue_translation_for_post($post_id) {
    $post_id = (int) $post_id;
    if ($post_id <= 0) {
        return false;
    }

    if (aismart_get_current_workspace_credit_balance() <= 0) {
        update_post_meta($post_id, '_aismart_translation_last_error', 'Translation blocked: workspace credits are 0.');
        aismart_queue_log('Translation blocked by credit guard post_id=' . (int) $post_id);
        return false;
    }

    delete_post_meta($post_id, '_aismart_translation_last_error');

    aismart_prepare_translations((int) $post_id);
    aismart_clear_translation_runtime_cache((int) $post_id);
    aismart_schedule_featured_image_sync((int) $post_id);

    $php_binary = PHP_BINARY;
    aismart_queue_log('Queue start post_id=' . (int) $post_id);
    if (
        !$php_binary ||
        !is_file($php_binary) ||
        !is_executable($php_binary) ||
        stripos((string) $php_binary, 'php-fpm') !== false
    ) {
        $php_binary = '/usr/bin/php';
    }
    aismart_queue_log('Using php_binary=' . $php_binary);

    $route = aismart_detect_translation_command();
    $translate_command = isset($route['command']) ? (string) $route['command'] : '';
    $engine = isset($route['engine']) ? (string) $route['engine'] : 'unknown';

    // Native engines should not depend on the external universal artisan path.
    if ($engine === 'falang') {
        $ok = aismart_translate_falang_native((int) $post_id);
        aismart_queue_log('Falang native translation result post_id=' . (int) $post_id . ' ok=' . ($ok ? '1' : '0'));
        if ($ok) {
            aismart_clear_translation_runtime_cache((int) $post_id);
            aismart_schedule_featured_image_sync((int) $post_id);
            return true;
        }
        update_post_meta($post_id, '_aismart_translation_last_error', 'Falang native translation failed.');
        return false;
    }

    if ($engine === 'qtranslate') {
        $ok = aismart_translate_qtranslate_native((int) $post_id);
        aismart_queue_log('qTranslate native translation result post_id=' . (int) $post_id . ' ok=' . ($ok ? '1' : '0'));
        if ($ok) {
            aismart_clear_translation_runtime_cache((int) $post_id);
            aismart_schedule_featured_image_sync((int) $post_id);
            return true;
        }
        update_post_meta($post_id, '_aismart_translation_last_error', 'qTranslate native translation failed.');
        return false;
    }

    if ($engine === 'wpglobus') {
        $ok = aismart_translate_wpglobus_native((int) $post_id);
        aismart_queue_log('WPGlobus native translation result post_id=' . (int) $post_id . ' ok=' . ($ok ? '1' : '0'));
        if ($ok) {
            aismart_clear_translation_runtime_cache((int) $post_id);
            aismart_schedule_featured_image_sync((int) $post_id);
            return true;
        }
        update_post_meta($post_id, '_aismart_translation_last_error', 'WPGlobus native translation failed.');
        return false;
    }

    if ($engine === 'bogo') {
        $ok = aismart_translate_bogo_native((int) $post_id);
        aismart_queue_log('Bogo native translation result post_id=' . (int) $post_id . ' ok=' . ($ok ? '1' : '0'));
        if ($ok) {
            aismart_clear_translation_runtime_cache((int) $post_id);
            aismart_schedule_featured_image_sync((int) $post_id);
            return true;
        }
        update_post_meta($post_id, '_aismart_translation_last_error', 'Bogo native translation failed.');
        return false;
    }

    if ($engine === 'multilingualpress') {
        $ok = aismart_translate_multilingualpress_native((int) $post_id);
        aismart_queue_log('MultilingualPress native translation result post_id=' . (int) $post_id . ' ok=' . ($ok ? '1' : '0'));
        if ($ok) {
            aismart_clear_translation_runtime_cache((int) $post_id);
            aismart_schedule_featured_image_sync((int) $post_id);
            return true;
        }
        update_post_meta($post_id, '_aismart_translation_last_error', 'MultilingualPress native translation failed.');
        return false;
    }

    if ($engine === 'polylang') {
        $ok = aismart_translate_polylang_native((int) $post_id);
        aismart_queue_log('Polylang native translation result post_id=' . (int) $post_id . ' ok=' . ($ok ? '1' : '0'));
        if ($ok) {
            aismart_clear_translation_runtime_cache((int) $post_id);
            aismart_schedule_featured_image_sync((int) $post_id);
            return true;
        }
        aismart_queue_log('Polylang native translation fallback to universal command post_id=' . (int) $post_id);
    }

    if ($engine === 'wpml') {
        $ok = aismart_translate_wpml_native((int) $post_id);
        aismart_queue_log('WPML native translation result post_id=' . (int) $post_id . ' ok=' . ($ok ? '1' : '0'));
        if ($ok) {
            aismart_clear_translation_runtime_cache((int) $post_id);
            aismart_schedule_featured_image_sync((int) $post_id);
            return true;
        }

        // WPML native failed; continue to universal fallback if available.
        aismart_queue_log('WPML native translation fallback to universal command post_id=' . (int) $post_id);
    }

    if ($engine === 'translatepress') {
        $ok = aismart_translate_translatepress_native((int) $post_id);
        aismart_queue_log('TranslatePress native translation result post_id=' . (int) $post_id . ' ok=' . ($ok ? '1' : '0'));
        if ($ok) {
            aismart_clear_translation_runtime_cache((int) $post_id);
            aismart_schedule_featured_image_sync((int) $post_id);
            return true;
        }

        // Native TranslatePress fallback failed; continue to universal fallback if available.
        aismart_queue_log('TranslatePress native fallback to universal command post_id=' . (int) $post_id);
    }

    $nvl_artisan = aismart_get_artisan_path();
    if (file_exists($nvl_artisan)) {

        if ($translate_command === '') {
            aismart_queue_log('No universal command mapped for detected engine=' . $engine . '; abort queue for post_id=' . (int) $post_id);
            error_log('AISmart Translate Queue: no universal command mapped for engine=' . $engine . ' post_id=' . (int) $post_id);
            update_post_meta($post_id, '_aismart_translation_last_error', 'No translation command mapped for engine: ' . $engine);
            return false;
        }

        aismart_queue_log('Using universal artisan at ' . $nvl_artisan . ' engine=' . $engine . ' command=' . $translate_command);

        if ($engine === 'translatepress') {
            if (!aismart_can_use_exec()) {
                aismart_queue_log('TranslatePress exec() disabled, trying proc_open sync universal execution');

                $sync_cmd = sprintf(
                    '%s %s %s gemini blog 0 site2 --id=%d 2>&1',
                    escapeshellcmd($php_binary),
                    escapeshellarg($nvl_artisan),
                    escapeshellarg($translate_command),
                    (int) $post_id
                );

                $proc_output = [];
                $proc_result = 1;
                $proc_ran = aismart_shell_run_capture($sync_cmd, $proc_output, $proc_result);
                $proc_preview = substr(preg_replace('/\s+/u', ' ', implode("\n", (array) $proc_output)), 0, 700);
                aismart_queue_log('TranslatePress proc_open sync ran=' . ($proc_ran ? '1' : '0') . ' result=' . (int) $proc_result . ' cmd=' . $sync_cmd . ' output=' . $proc_preview);
                error_log('AISmart Translate Queue (TranslatePress proc_open sync): post_id=' . (int) $post_id . ' ran=' . ($proc_ran ? '1' : '0') . ' result=' . (int) $proc_result . ' output=' . $proc_preview);

                if ($proc_ran && (int) $proc_result === 0) {
                    aismart_clear_translation_runtime_cache((int) $post_id);
                    aismart_schedule_featured_image_sync((int) $post_id);
                    aismart_schedule_translatepress_retry((int) $post_id);
                    return true;
                }

                aismart_queue_log('TranslatePress queue failed: exec() disabled and proc_open sync unavailable/failed post_id=' . (int) $post_id);
                error_log('AISmart Translate Queue: TranslatePress queue failed without exec/proc_open post_id=' . (int) $post_id);
                $clean_err = substr(preg_replace('/\s+/u', ' ', implode(" ", (array) $proc_output)), 0, 150);
                update_post_meta($post_id, '_aismart_translation_last_error', 'Laravel Backend Artisan Error: ' . ($clean_err ?: 'Command Failed'));
                return false;
            }

            $sync_cmd = sprintf(
                '%s %s %s gemini blog 0 site2 --id=%d 2>&1',
                escapeshellcmd($php_binary),
                escapeshellarg($nvl_artisan),
                escapeshellarg($translate_command),
                (int) $post_id
            );

            $sync_output = [];
            $sync_result = 0;
            exec($sync_cmd, $sync_output, $sync_result);
            $sync_preview = substr(preg_replace('/\s+/u', ' ', implode("\n", (array) $sync_output)), 0, 700);
            aismart_queue_log('TranslatePress sync exec result=' . $sync_result . ' cmd=' . $sync_cmd . ' output=' . $sync_preview);
            error_log('AISmart Translate Queue (TranslatePress sync): post_id=' . (int) $post_id . ' result=' . $sync_result . ' output=' . $sync_preview);

            if ($sync_result === 0) {
                aismart_clear_translation_runtime_cache((int) $post_id);
                aismart_schedule_featured_image_sync((int) $post_id);
                aismart_schedule_translatepress_retry((int) $post_id);
                return true;
            }

            aismart_queue_log('TranslatePress sync universal execution failed post_id=' . (int) $post_id);
            error_log('AISmart Translate Queue: TranslatePress sync universal execution failed post_id=' . (int) $post_id);
            $clean_err = substr(preg_replace('/\s+/u', ' ', implode(" ", (array) $sync_output)), 0, 150);
            update_post_meta($post_id, '_aismart_translation_last_error', 'Laravel Backend Artisan Error: ' . ($clean_err ?: 'Command Failed'));
            return false;
        }

        if (!aismart_can_use_exec()) {
            aismart_queue_log('exec() disabled, trying proc_open universal execution');

            $bg_cmd = sprintf(
                '%s %s %s gemini blog 0 site2 --id=%d > /dev/null 2>&1 & echo $!',
                escapeshellcmd($php_binary),
                escapeshellarg($nvl_artisan),
                escapeshellarg($translate_command),
                (int) $post_id
            );
            $bg_output = [];
            $bg_result = 1;
            $bg_ran = aismart_shell_run_capture($bg_cmd, $bg_output, $bg_result);
            $bg_pid = '';
            if (!empty($bg_output)) {
                $bg_pid = trim((string) end($bg_output));
            }

            aismart_queue_log('proc_open universal ran=' . ($bg_ran ? '1' : '0') . ' result=' . (int) $bg_result . ' pid=' . $bg_pid . ' cmd=' . $bg_cmd);
            if ($bg_ran && (int) $bg_result === 0 && $bg_pid !== '') {
                aismart_clear_translation_runtime_cache((int) $post_id);
                aismart_schedule_featured_image_sync((int) $post_id);
                return true;
            }

            aismart_queue_log('proc_open universal execution failed for engine=' . $engine . ', using native fallback when available');

            if ($engine === 'polylang') {
                $args = [(int) $post_id, 'polylang'];
                if (!wp_next_scheduled('aismart_process_translation_event', $args)) {
                    wp_schedule_single_event(time() + 1, 'aismart_process_translation_event', $args);
                    aismart_queue_log('Scheduled background Polylang fallback post_id=' . (int) $post_id);
                }

                if (function_exists('spawn_cron')) {
                    @spawn_cron(time());
                }

                aismart_schedule_featured_image_sync((int) $post_id);

                return true;
            }

            aismart_queue_log('exec() disabled and no native fallback for engine=' . $engine);
            error_log('AISmart Translate Queue: exec() disabled and no native fallback for engine=' . $engine);
            update_post_meta($post_id, '_aismart_translation_last_error', 'Queue failed: exec() disabled and no native fallback for engine ' . $engine . '.');
            return false;
        }
        $cmd = sprintf(
            '%s %s %s gemini blog 0 site2 --id=%d > /dev/null 2>&1 & echo $!',
            escapeshellcmd($php_binary),
            escapeshellarg($nvl_artisan),
            escapeshellarg($translate_command),
            (int) $post_id
        );

        $output = [];
        $result = 0;
        $pid = exec($cmd, $output, $result);

        error_log('AISmart Translate Queue (Universal): engine=' . $engine . ' command=' . $translate_command . ' post_id=' . (int) $post_id . ' cmd=' . $cmd . ' pid=' . $pid . ' result=' . $result);

        aismart_queue_log('Universal exec result=' . $result . ' pid=' . $pid . ' cmd=' . $cmd);
        if ($result === 0 && !empty($pid)) {
            aismart_clear_translation_runtime_cache((int) $post_id);
            aismart_schedule_featured_image_sync((int) $post_id);
        }
        $ok = $result === 0 && !empty($pid);
        if (!$ok) {
            update_post_meta($post_id, '_aismart_translation_last_error', 'Universal translation command failed to start.');
        }
        return $ok;
    }

        aismart_queue_log('Universal artisan not found or inaccessible: ' . $nvl_artisan);
        error_log('AISmart Translate Queue: universal artisan not found at ' . $nvl_artisan);
        if ($engine === 'wpml') {
            update_post_meta($post_id, '_aismart_translation_last_error', 'WPML native translation produced no updates and universal fallback is unavailable on this server.');
        } else {
            update_post_meta($post_id, '_aismart_translation_last_error', 'Universal translation backend unavailable: ' . $nvl_artisan);
        }
        return false;
}

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

    clean_post_cache($post_id);

    if (function_exists('pll_get_post_translations')) {
        $translations = pll_get_post_translations($post_id);
        if (is_array($translations)) {
            foreach ($translations as $translated_id) {
                $translated_id = (int) $translated_id;
                if ($translated_id > 0) {
                    clean_post_cache($translated_id);
                }
            }
        }
    }

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

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

    $lock_key = 'aismart_prepare_translations_lock_' . $post_id;
    if (function_exists('get_transient') && get_transient($lock_key)) {
        aismart_queue_log('Prepare translations locked/skip for post_id=' . $post_id);
        return;
    }
    if (function_exists('set_transient')) {
        set_transient($lock_key, 1, 120);
    }

    $post = get_post($post_id);
    if (!$post || $post->post_type !== 'post') {
        return;
    }
    $source_thumbnail_id = (int) get_post_thumbnail_id($post_id);

    // --- Polylang Logic (The "Cure") ---
    if (function_exists('pll_default_language') && function_exists('pll_save_post_translations')) {
        $default_lang = pll_default_language();
        $target_langs = pll_languages_list(); // e.g. ['en', 'th', 'zh']

        // 1. Ensure Original has Language Set
        $current_lang = pll_get_post_language($post_id);
        if (!$current_lang) {
            pll_set_post_language($post_id, $default_lang);
            $current_lang = $default_lang;
        }

        // Get existing translations to link correctly
        $translations = pll_get_post_translations($post_id);
        if (empty($translations)) {
            $translations[$current_lang] = $post_id;
        }

        foreach ($target_langs as $lang_code) {
            if ($lang_code === $current_lang) {
                continue;
            }

            // check if translation exists in the array OR via pll_get_post
            if (isset($translations[$lang_code])) {
                continue;
            }
            
            $existing_trans_id = pll_get_post($post_id, $lang_code);
            if ($existing_trans_id && get_post($existing_trans_id)) {
                $translations[$lang_code] = $existing_trans_id;
                continue;
            }

            $existing_candidates = get_posts([
                'post_type' => 'post',
                'post_status' => ['publish', 'draft', 'pending', 'future', 'private'],
                'numberposts' => 1,
                'orderby' => 'ID',
                'order' => 'ASC',
                'meta_query' => [
                    [
                        'key' => '_aismart_source_post_id',
                        'value' => $post_id,
                        'compare' => '=',
                        'type' => 'NUMERIC',
                    ],
                    [
                        'key' => '_aismart_target_lang',
                        'value' => sanitize_key((string) $lang_code),
                        'compare' => '=',
                    ],
                ],
                'fields' => 'ids',
            ]);
            if (!empty($existing_candidates)) {
                $translations[$lang_code] = (int) $existing_candidates[0];
                continue;
            }

            // Create new post for this language
            $new_post_data = [
                'post_title'   => aismart_normalize_post_title($post->post_title),
                'post_content' => $post->post_content, // Copy content for now
                'post_excerpt' => $post->post_excerpt,
                'post_status'  => 'publish', // Or 'draft'? User code says 'publish' usually
                'post_type'    => 'post',
                'post_author'  => $post->post_author,
            ];

            // Prevent recursion: don't auto-translate the translation itself
            if (has_action('transition_post_status', 'aismart_auto_translate_on_publish')) {
                remove_action('transition_post_status', 'aismart_auto_translate_on_publish', 10);
            }
            $new_post_id = wp_insert_post($new_post_data);
            add_action('transition_post_status', 'aismart_auto_translate_on_publish', 10, 3);

            if ($new_post_id && !is_wp_error($new_post_id)) {
                // Step 2: Set Language (The "Stamp")
                pll_set_post_language($new_post_id, $lang_code);

                if ($source_thumbnail_id > 0) {
                    set_post_thumbnail((int) $new_post_id, $source_thumbnail_id);
                }

                update_post_meta((int) $new_post_id, '_aismart_source_post_id', (int) $post_id);
                update_post_meta((int) $new_post_id, '_aismart_target_lang', sanitize_key((string) $lang_code));

                // Add to translations array
                $translations[$lang_code] = $new_post_id;

                // Sync Taxonomies (Categories/Tags) if possible
                // (Optional but good for completeness)
                // For simplicity, just copy raw IDs if they match, or let Polylang handle sync if configured.
            }
        }

        // Step 3: Link Translations (The "Handshake")
        // This MUST happen after all posts have language set
        if (!empty($translations)) {
            pll_save_post_translations($translations);
        }

        return; // Done with Polylang
    }

    // --- WPML Legacy Logic ---
    // Ensure WPML creates duplicates/children first.
    if (function_exists('do_action')) {
        do_action('wpml_make_post_duplicates', $post_id);
        do_action('wpml_admin_make_post_duplicates', $post_id);
    }

    $default_lang = apply_filters('wpml_default_language', null);
    $active_languages = apply_filters('wpml_active_languages', null, ['skip_missing' => 0]);
    if (empty($default_lang) || !is_array($active_languages)) {
        return;
    }

    foreach ($active_languages as $lang_code => $lang_data) {
        if ((string) $lang_code === (string) $default_lang) {
            continue;
        }

        $child_id = apply_filters('wpml_object_id', $post_id, 'post', false, $lang_code);
        $child_id = (int) $child_id;
        if ($child_id <= 0) {
            continue;
        }

        // Copy English content into child first (required by translation workflow baseline).
        wp_update_post([
            'ID' => $child_id,
            'post_title' => $post->post_title,
            'post_content' => $post->post_content,
            'post_excerpt' => $post->post_excerpt,
            'post_status'  => 'publish',
        ]);

        // Keep taxonomy baseline aligned before translation.
        $category_ids = wp_get_post_categories($post_id);
        if (!empty($category_ids)) {
            wp_set_post_categories($child_id, $category_ids, false);
        }
        $tags = wp_get_post_tags($post_id, ['fields' => 'names']);
        if (!empty($tags)) {
            wp_set_post_tags($child_id, $tags, false);
        }
    }

    aismart_queue_log('WPML/Polylang children prepared post_id=' . $post_id);
}

function aismart_queue_log($message) {
    $upload_dir = wp_upload_dir();
    $base_dir = isset($upload_dir['basedir']) ? (string) $upload_dir['basedir'] : '';
    if ($base_dir === '') {
        return;
    }

    $log_dir = trailingslashit($base_dir) . 'aismart-token';
    if (!is_dir($log_dir)) {
        wp_mkdir_p($log_dir);
    }
    if (!is_dir($log_dir) || !is_writable($log_dir)) {
        return;
    }

    $path = trailingslashit($log_dir) . 'aismart-queue.log';
    $line = date('c') . ' ' . $message . PHP_EOL;
    @file_put_contents($path, $line, FILE_APPEND | LOCK_EX);
}

function aismart_can_use_exec() {
    if (!function_exists('exec')) {
        return false;
    }

    $disabled = ini_get('disable_functions');
    if (is_string($disabled) && $disabled !== '') {
        $list = array_map('trim', explode(',', $disabled));
        if (in_array('exec', $list, true)) {
            return false;
        }
    }

    return true;
}

function aismart_can_use_proc_open() {
    // Disallowed by wordpress.org automated checks.
    return true;
}

function aismart_shell_run_capture($cmd, &$output, &$result) {
    $cmd = (string) $cmd;
    $output = [];
    $result = 1;

    if ($cmd === '') {
        return false;
    }

    if (aismart_can_use_exec()) {
        exec($cmd, $output, $result);
        return true;
    }

    return false;
}

function aismart_run_universal_artisan_inline($command, $post_id, $site = 'site2') {
    $command = (string) $command;
    $post_id = (int) $post_id;
    $site = (string) $site;

    if ($command === '' || $post_id <= 0) {
        return false;
    }

    $app_root = aismart_get_laravel_root();
    $autoload = $app_root . '/vendor/autoload.php';
    $bootstrap = $app_root . '/bootstrap/app.php';

    if (!file_exists($autoload) || !file_exists($bootstrap)) {
        aismart_queue_log('Inline universal run missing files autoload=' . (file_exists($autoload) ? '1' : '0') . ' bootstrap=' . (file_exists($bootstrap) ? '1' : '0'));
        return false;
    }

    if (function_exists('set_time_limit')) {
        @set_time_limit(180);
    }

    try {
        require_once $autoload;
        $app = require $bootstrap;

        if (!is_object($app) || !method_exists($app, 'make')) {
            aismart_queue_log('Inline universal run failed: app bootstrap invalid');
            return false;
        }

        $kernel = $app->make('Illuminate\\Contracts\\Console\\Kernel');
        $exit_code = (int) $kernel->call($command, [
            'provider' => 'gemini',
            'posttype' => 'blog',
            'limit' => 0,
            'site' => $site,
            '--id' => $post_id,
        ]);

        $output = '';
        if (method_exists($kernel, 'output')) {
            $output = (string) $kernel->output();
        }

        aismart_queue_log('Inline universal exit=' . $exit_code . ' command=' . $command . ' output=' . substr(preg_replace('/\s+/u', ' ', $output), 0, 500));
        error_log('AISmart Translate Inline Universal: command=' . $command . ' post_id=' . $post_id . ' exit=' . $exit_code);

        return $exit_code === 0;
    } catch (Throwable $e) {
        aismart_queue_log('Inline universal exception: ' . $e->getMessage());
        error_log('AISmart Translate Inline Universal exception: ' . $e->getMessage());
        return false;
    }
}

function aismart_translate_falang_native($post_id) {
    $post_id = (int) $post_id;
    if ($post_id <= 0) {
        return false;
    }

    if (!function_exists('falang_languages_list') && !taxonomy_exists('language')) {
        aismart_queue_log('Native Falang fallback unavailable: Falang APIs/taxonomy missing');
        return false;
    }

    $post = get_post($post_id);
    if (!$post || $post->post_type !== 'post' || $post->post_status !== 'publish') {
        aismart_queue_log('Native Falang fallback skip: post not eligible post_id=' . $post_id);
        return false;
    }

    $source_thumbnail_id = (int) get_post_thumbnail_id($post_id);
    $languages = aismart_get_falang_language_pairs();

    if (empty($languages)) {
        aismart_queue_log('Native Falang fallback skip: no active languages post_id=' . $post_id);
        return false;
    }

    $source_locale = sanitize_text_field((string) get_post_meta($post_id, '_locale', true));
    if (($source_locale === '' || strcasecmp($source_locale, 'all') === 0) && function_exists('falang_default_language')) {
        $source_locale = sanitize_text_field((string) falang_default_language('locale'));
    }
    if ($source_locale === '') {
        $source_locale = sanitize_text_field((string) $languages[0]['locale']);
    }

    $processed = 0;
    foreach ($languages as $language) {
        $target_locale = sanitize_text_field((string) ($language['locale'] ?? ''));
        if ($target_locale === '') {
            continue;
        }

        if (strcasecmp($target_locale, $source_locale) === 0) {
            continue;
        }

        $prefix = aismart_get_falang_meta_prefix($target_locale);
        if ($prefix === '') {
            continue;
        }

        $source_title = aismart_normalize_post_title((string) $post->post_title);
        $translated_title = aismart_translate_text_google($source_title, $target_locale, $source_locale);
        $translated_title = aismart_cleanup_translated_plain_text($translated_title);
        $translated_title = aismart_normalize_post_title($translated_title);
        $translated_excerpt = aismart_translate_text_google((string) $post->post_excerpt, $target_locale, $source_locale);
        $translated_excerpt = aismart_cleanup_translated_plain_text($translated_excerpt);
        $translated_content = aismart_translate_post_content_google((string) $post->post_content, $target_locale, $source_locale);

        update_post_meta($post_id, $prefix . 'post_title', $translated_title);
        update_post_meta($post_id, $prefix . 'post_excerpt', $translated_excerpt);
        update_post_meta($post_id, $prefix . 'post_content', $translated_content);
        update_post_meta($post_id, $prefix . 'post_name', (string) $post->post_name);
        update_post_meta($post_id, $prefix . 'published', '1');
        if ($source_thumbnail_id > 0) {
            update_post_meta($post_id, $prefix . 'thumbnail_id', $source_thumbnail_id);
            update_post_meta($post_id, $prefix . '_thumbnail_id', $source_thumbnail_id);
        }

        $legacy_target_id = 0;
        $legacy_candidates = get_posts([
            'post_type' => 'post',
            'post_status' => ['publish', 'draft', 'pending', 'future', 'private'],
            'numberposts' => 1,
            'orderby' => 'ID',
            'order' => 'ASC',
            'meta_query' => [
                [
                    'key' => '_aismart_source_post_id',
                    'value' => $post_id,
                    'compare' => '=',
                    'type' => 'NUMERIC',
                ],
                [
                    'key' => '_aismart_target_lang',
                    'value' => $target_locale,
                    'compare' => '=',
                ],
            ],
            'fields' => 'ids',
        ]);
        if (!empty($legacy_candidates)) {
            $legacy_target_id = (int) $legacy_candidates[0];
        }

        if ($legacy_target_id <= 0) {
            $legacy_locale_candidates = get_posts([
                'post_type' => 'post',
                'post_status' => ['publish', 'draft', 'pending', 'future', 'private'],
                'numberposts' => 1,
                'orderby' => 'ID',
                'order' => 'ASC',
                'meta_query' => [
                    [
                        'key' => '_aismart_source_post_id',
                        'value' => $post_id,
                        'compare' => '=',
                        'type' => 'NUMERIC',
                    ],
                    [
                        'key' => '_locale',
                        'value' => $target_locale,
                        'compare' => '=',
                    ],
                ],
                'fields' => 'ids',
            ]);
            if (!empty($legacy_locale_candidates)) {
                $legacy_target_id = (int) $legacy_locale_candidates[0];
            }
        }

        if ($legacy_target_id <= 0) {
            if (has_action('transition_post_status', 'aismart_auto_translate_on_publish')) {
                remove_action('transition_post_status', 'aismart_auto_translate_on_publish', 10);
            }
            $legacy_target_id = wp_insert_post([
                'post_type' => 'post',
                'post_status' => 'publish',
                'post_author' => (int) $post->post_author,
                'post_title' => $translated_title,
                'post_excerpt' => $translated_excerpt,
                'post_content' => $translated_content,
                'post_name' => (string) $post->post_name,
            ], true);
            add_action('transition_post_status', 'aismart_auto_translate_on_publish', 10, 3);

            if (is_wp_error($legacy_target_id) || (int) $legacy_target_id <= 0) {
                aismart_queue_log('Native Falang legacy child create failed locale=' . $target_locale . ' source_id=' . $post_id);
                $legacy_target_id = 0;
            } else {
                $legacy_target_id = (int) $legacy_target_id;
            }
        }

        if ($legacy_target_id > 0 && get_post($legacy_target_id)) {
            wp_update_post([
                'ID' => $legacy_target_id,
                'post_status' => 'publish',
                'post_title' => $translated_title,
                'post_excerpt' => $translated_excerpt,
                'post_content' => $translated_content,
                'post_name' => (string) $post->post_name,
            ]);

            update_post_meta($legacy_target_id, '_locale', $target_locale);
            update_post_meta($legacy_target_id, '_aismart_source_post_id', $post_id);
            update_post_meta($legacy_target_id, '_aismart_target_lang', $target_locale);

            if ($source_thumbnail_id > 0) {
                set_post_thumbnail($legacy_target_id, $source_thumbnail_id);
            }

            aismart_sync_theme_meta_to_post($post_id, $legacy_target_id);

            $category_ids = wp_get_post_categories($post_id);
            if (!empty($category_ids)) {
                wp_set_post_categories($legacy_target_id, $category_ids, false);
            }
            $tags = wp_get_post_tags($post_id, ['fields' => 'names']);
            if (!empty($tags)) {
                wp_set_post_tags($legacy_target_id, $tags, false);
            }
        }

        $processed++;
        aismart_queue_log('Native Falang translated locale=' . $target_locale . ' source_id=' . $post_id . ' prefix=' . $prefix . ' legacy_target_id=' . (int) $legacy_target_id);
    }

    if ($processed > 0) {
        update_post_meta($post_id, '_aismart_translation_queued', 1);
    }

    return $processed > 0;
}

function aismart_translate_translatepress_native($post_id) {
    $post_id = (int) $post_id;
    if ($post_id <= 0) {
        return false;
    }

    if (!defined('TRP_PLUGIN_VERSION')) {
        aismart_queue_log('Native TranslatePress fallback unavailable: plugin inactive');
        return false;
    }

    $post = get_post($post_id);
    if (!$post || $post->post_type !== 'post' || $post->post_status !== 'publish') {
        aismart_queue_log('Native TranslatePress fallback skip: post not eligible post_id=' . $post_id);
        return false;
    }

    $settings = get_option('trp_settings', []);
    $langs = isset($settings['translation-languages']) && is_array($settings['translation-languages'])
        ? array_values(array_filter(array_map('strval', $settings['translation-languages'])))
        : [];

    if (empty($langs)) {
        aismart_queue_log('Native TranslatePress fallback skip: no languages configured post_id=' . $post_id);
        return false;
    }

    $default_lang = isset($settings['default-language']) ? (string) $settings['default-language'] : (string) get_locale();
    if ($default_lang === '') {
        $default_lang = (string) $langs[0];
    }

    $translation_store = [];
    $processed = 0;

    foreach ($langs as $lang) {
        $lang = trim((string) $lang);
        if ($lang === '' || $lang === $default_lang) {
            continue;
        }

        $source_title = aismart_normalize_post_title((string) $post->post_title);
        $translated_title = aismart_translate_text_google($source_title, $lang, $default_lang, false);
        $translated_title = aismart_cleanup_translated_plain_text($translated_title);
        $translated_title = aismart_normalize_post_title($translated_title);

        $translated_excerpt = aismart_translate_text_google((string) $post->post_excerpt, $lang, $default_lang, false);
        $translated_excerpt = aismart_cleanup_translated_plain_text($translated_excerpt);
        $translated_content = aismart_translate_post_content_google((string) $post->post_content, $lang, $default_lang);

        update_post_meta($post_id, '_aismart_trp_translation_' . $lang . '_title', $translated_title);
        update_post_meta($post_id, '_aismart_trp_translation_' . $lang . '_excerpt', $translated_excerpt);
        update_post_meta($post_id, '_aismart_trp_translation_' . $lang . '_content', $translated_content);

        $translation_store[$lang] = [
            'title' => $translated_title,
            'excerpt' => $translated_excerpt,
            'content' => $translated_content,
            'updated_at' => gmdate('c'),
        ];

        $processed++;
    }

    if ($processed <= 0) {
        aismart_queue_log('Native TranslatePress fallback produced no target languages post_id=' . $post_id);
        return false;
    }

    update_post_meta($post_id, '_aismart_trp_translations', $translation_store);
    update_post_meta($post_id, '_aismart_translation_queued', 1);
    update_post_meta($post_id, '_aismart_translation_queue_last_at', gmdate('c'));

    aismart_queue_log('Native TranslatePress fallback translated post_id=' . $post_id . ' languages=' . $processed);

    return true;
}

function aismart_translate_polylang_native($post_id) {
    $post_id = (int) $post_id;
    if ($post_id <= 0) {
        return false;
    }

    if (!function_exists('pll_languages_list') || !function_exists('pll_get_post_language') || !function_exists('pll_get_post_translations')) {
        aismart_queue_log('Native Polylang fallback unavailable: Polylang APIs missing');
        return false;
    }

    $post = get_post($post_id);
    if (!$post || $post->post_type !== 'post' || $post->post_status !== 'publish') {
        aismart_queue_log('Native Polylang fallback skip: post not eligible post_id=' . $post_id);
        return false;
    }
    $source_thumbnail_id = (int) get_post_thumbnail_id($post_id);

    $langs = (array) pll_languages_list(['fields' => 'slug']);
    if (empty($langs)) {
        aismart_queue_log('Native Polylang fallback skip: no languages');
        return false;
    }

    $source_lang = (string) pll_get_post_language($post_id, 'slug');
    if ($source_lang === '' && function_exists('pll_default_language')) {
        $source_lang = (string) pll_default_language('slug');
    }
    if ($source_lang === '') {
        $source_lang = (string) $langs[0];
    }

    if (function_exists('pll_set_post_language')) {
        pll_set_post_language($post_id, $source_lang);
    }

    $translations = (array) pll_get_post_translations($post_id);
    if (empty($translations[$source_lang])) {
        $translations[$source_lang] = $post_id;
    }

    foreach ($langs as $lang) {
        $lang = sanitize_key((string) $lang);
        if ($lang === '' || $lang === $source_lang) {
            continue;
        }

        $target_id = isset($translations[$lang]) ? (int) $translations[$lang] : 0;
        if ($target_id <= 0) {
            $existing_candidates = get_posts([
                'post_type' => 'post',
                'post_status' => ['publish', 'draft', 'pending', 'future', 'private'],
                'numberposts' => 1,
                'orderby' => 'ID',
                'order' => 'ASC',
                'meta_query' => [
                    [
                        'key' => '_aismart_source_post_id',
                        'value' => $post_id,
                        'compare' => '=',
                        'type' => 'NUMERIC',
                    ],
                    [
                        'key' => '_aismart_target_lang',
                        'value' => $lang,
                        'compare' => '=',
                    ],
                ],
                'fields' => 'ids',
            ]);
            if (!empty($existing_candidates)) {
                $target_id = (int) $existing_candidates[0];
            }
        }

        if ($target_id <= 0) {
            if (has_action('transition_post_status', 'aismart_auto_translate_on_publish')) {
                remove_action('transition_post_status', 'aismart_auto_translate_on_publish', 10);
            }
            $target_id = wp_insert_post([
                'post_type' => 'post',
                'post_status' => 'publish',
                'post_author' => (int) $post->post_author,
                'post_title' => (string) $post->post_title,
                'post_excerpt' => (string) $post->post_excerpt,
                'post_content' => (string) $post->post_content,
            ], true);
            add_action('transition_post_status', 'aismart_auto_translate_on_publish', 10, 3);

            if (is_wp_error($target_id) || (int) $target_id <= 0) {
                aismart_queue_log('Native Polylang fallback: failed to create translation post for lang=' . $lang);
                continue;
            }

            update_post_meta((int) $target_id, '_aismart_source_post_id', (int) $post_id);
            update_post_meta((int) $target_id, '_aismart_target_lang', $lang);
        }

        if (function_exists('pll_set_post_language')) {
            pll_set_post_language((int) $target_id, $lang);
        }

        $source_title = aismart_normalize_post_title((string) $post->post_title);
        $translated_title = aismart_translate_text_google($source_title, $lang, $source_lang);
        $translated_title = aismart_cleanup_translated_plain_text($translated_title);
        $translated_title = aismart_normalize_post_title($translated_title);
        $translated_excerpt = aismart_translate_text_google((string) $post->post_excerpt, $lang, $source_lang);
        $translated_excerpt = aismart_cleanup_translated_plain_text($translated_excerpt);
        $translated_content = aismart_translate_post_content_google((string) $post->post_content, $lang, $source_lang);

        wp_update_post([
            'ID' => (int) $target_id,
            'post_status' => 'publish',
            'post_title' => $translated_title,
            'post_excerpt' => $translated_excerpt,
            'post_content' => $translated_content,
        ]);

        $category_ids = wp_get_post_categories($post_id);
        if (!empty($category_ids)) {
            wp_set_post_categories((int) $target_id, $category_ids, false);
        }
        $tags = wp_get_post_tags($post_id, ['fields' => 'names']);
        if (!empty($tags)) {
            wp_set_post_tags((int) $target_id, $tags, false);
        }

        if ($source_thumbnail_id > 0) {
            set_post_thumbnail((int) $target_id, $source_thumbnail_id);
        }

        $translations[$lang] = (int) $target_id;
        aismart_queue_log('Native Polylang fallback translated lang=' . $lang . ' target_id=' . (int) $target_id);
    }

    if (function_exists('pll_save_post_translations')) {
        pll_save_post_translations($translations);
    }

    update_post_meta($post_id, '_aismart_translation_queued', 1);
    return true;
}

function aismart_translate_text_google($text, $target_lang, $source_lang, $preserve_html = false) {
    $text = trim((string) $text);
    if ($text === '') {
        return '';
    }

    $tl = aismart_normalize_translate_lang($target_lang);
    $sl = aismart_normalize_translate_lang($source_lang);

    $payload = [
        'text' => $text,
        'target_lang' => $tl,
        'source_lang' => $sl,
    ];
    if ($preserve_html) {
        $payload['format'] = 'html';
    }

    $extract_translation = static function ($result) {
        if (!is_array($result)) {
            return '';
        }

        foreach (['translated_text', 'translation', 'text', 'result'] as $key) {
            if (!empty($result[$key]) && is_string($result[$key])) {
                return (string) $result[$key];
            }
        }

        if (isset($result['data']) && is_array($result['data'])) {
            foreach (['translated_text', 'translation', 'text', 'result'] as $key) {
                if (!empty($result['data'][$key]) && is_string($result['data'][$key])) {
                    return (string) $result['data'][$key];
                }
            }
        }

        return '';
    };

    if (function_exists('aismart_plugin_api_request')) {
        $api_result = aismart_plugin_api_request('POST', 'api/plugin/v1/translation/translate', $payload, true);
        if (!is_wp_error($api_result)) {
            $translated = $extract_translation($api_result);
            if ($translated !== '') {
                return $translated;
            }
        }
    }

    $api_base = untrailingslashit((string) aismart_plugin_get_api_base());

    $response = wp_remote_post($api_base . '/api/plugin/v1/translation/translate', [
        'timeout' => 30,
        'headers' => [
            'Content-Type' => 'application/json',
        ],
        'body' => wp_json_encode($payload),
    ]);
    if (is_wp_error($response)) {
        return $text;
    }

    $json = json_decode(wp_remote_retrieve_body($response), true);
    $translated = $extract_translation($json);
    return $translated !== '' ? $translated : $text;
}

function aismart_translate_post_content_google($content, $target_lang, $source_lang) {
    $content = (string) $content;
    if (trim($content) === '') {
        return '';
    }

    if (strpos($content, '<') !== false && strpos($content, '>') !== false) {
        $parts = preg_split('/(<[^>]+>)/u', $content, -1, PREG_SPLIT_DELIM_CAPTURE);
        if (is_array($parts) && !empty($parts)) {
            $translated = '';
            foreach ($parts as $part) {
                if ($part === '') {
                    continue;
                }

                if (preg_match('/^<[^>]+>$/u', $part)) {
                    $translated .= $part;
                    continue;
                }

                if (trim($part) === '') {
                    $translated .= $part;
                    continue;
                }

                $leading = '';
                $trailing = '';
                if (preg_match('/^\s+/u', $part, $leadingMatch)) {
                    $leading = (string) ($leadingMatch[0] ?? '');
                }
                if (preg_match('/\s+$/u', $part, $trailingMatch)) {
                    $trailing = (string) ($trailingMatch[0] ?? '');
                }

                $core = trim((string) $part);
                if ($core === '') {
                    $translated .= $part;
                    continue;
                }

                $translated_core = aismart_translate_text_google($core, $target_lang, $source_lang, false);
                $translated .= $leading . ($translated_core !== '' ? $translated_core : $core) . $trailing;
            }
        } else {
            $translated = aismart_translate_text_google($content, $target_lang, $source_lang, true);
        }
    } else {
        $translated = aismart_translate_text_google($content, $target_lang, $source_lang, false);
    }

    $translated = aismart_cleanup_translated_post_content($translated);
    return $translated !== '' ? $translated : $content;
}

function aismart_cleanup_translated_plain_text($text) {
    $text = trim((string) $text);
    if ($text === '') {
        return '';
    }

    $text = preg_replace('/^\s*```(?:html|markdown|md|text)?\s*/iu', '', $text, 1);
    $text = preg_replace('/\s*```\s*$/u', '', (string) $text, 1);
    $text = preg_replace('/^\s*`?html`?\s*$/iu', '', (string) $text);
    $text = preg_replace('/\R{3,}/u', "\n\n", (string) $text);

    $lines = preg_split('/\R/u', (string) $text);
    if (is_array($lines) && count($lines) >= 2) {
        $first = trim((string) $lines[0]);
        $second = trim((string) $lines[1]);
        if ($first !== '' && $second !== '' && $first === $second) {
            array_shift($lines);
            $text = implode("\n", $lines);
        }
    }

    return trim((string) $text);
}

function aismart_cleanup_translated_post_content($content) {
    $original = (string) $content;
    $content = trim($original);
    if ($content === '') {
        return '';
    }

    if (preg_match('/<!doctype\s+html|<html\b/iu', $content)) {
        if (preg_match('/<body\b[^>]*>(.*?)<\/body>/is', $content, $bodyMatch) && isset($bodyMatch[1])) {
            $content = trim((string) $bodyMatch[1]);
        }

        $content = preg_replace('/<head\b[^>]*>.*?<\/head>/is', '', (string) $content);
        $content = preg_replace('/<style\b[^>]*>.*?<\/style>/is', '', (string) $content);
        $content = preg_replace('/<script\b[^>]*>.*?<\/script>/is', '', (string) $content);
        $content = preg_replace('/<\/?(?:html|body)\b[^>]*>/i', '', (string) $content);

    }

    $content = preg_replace('/^\s*`?html\s*\R+/iu', '', $content, 1);

    $content = preg_replace('/^\s*```[a-zA-Z0-9_-]*\s*\R.*?\R```\s*/su', '', $content, 1);
    $content = preg_replace('/^\s*```(?:html)?\s*/iu', '', $content, 1);
    $content = preg_replace('/\R```\s*$/u', '', $content, 1);
    $content = preg_replace('/^(?:\s|\x{00A0}|&nbsp;|<br\s*\/?>\s*|<p>\s*(?:&nbsp;|\x{00A0}|\s)*<\/p>)+/iu', '', (string) $content);

    $content = trim((string) $content);
    if ($content !== '') {
        return aismart_strip_duplicate_title_preamble($content);
    }

    $fallback = preg_replace('/^\s*```(?:html)?\s*/iu', '', trim($original), 1);
    $fallback = preg_replace('/\R```\s*$/u', '', (string) $fallback, 1);
    $fallback = trim((string) $fallback);
    if ($fallback !== '') {
        return aismart_strip_duplicate_title_preamble($fallback);
    }

    return aismart_strip_duplicate_title_preamble(trim($original));
}

function aismart_strip_duplicate_title_preamble($content) {
    $content = trim((string) $content);
    if ($content === '') {
        return '';
    }

    $lines = preg_split('/\R/u', $content);
    if (!is_array($lines) || empty($lines)) {
        return $content;
    }

    $title = '';
    foreach ($lines as $line) {
        $line = trim((string) $line);
        $line = preg_replace('/^[#`\-*\s]+/u', '', $line);
        $line = trim((string) $line);
        if ($line === '' || preg_match('/^(html|body|h1|h2|h3|p|style|css)$/iu', $line)) {
            continue;
        }
        if (strpos($line, '{') !== false || strpos($line, ':') !== false) {
            continue;
        }
        $line_len = function_exists('mb_strlen') ? mb_strlen($line) : strlen($line);
        if ($line !== '' && $line_len >= 8) {
            $title = $line;
            break;
        }
    }

    if ($title === '') {
        return $content;
    }

    $first = function_exists('mb_stripos') ? mb_stripos($content, $title) : stripos($content, $title);
    if (!is_int($first)) {
        return $content;
    }

    $title_len = function_exists('mb_strlen') ? mb_strlen($title) : strlen($title);
    $second = function_exists('mb_stripos') ? mb_stripos($content, $title, $first + $title_len) : stripos($content, $title, $first + $title_len);
    if (!is_int($second) || $second <= 0 || $second > 4000) {
        return $content;
    }

    $trimmed = trim(function_exists('mb_substr') ? mb_substr($content, $second) : substr($content, $second));
    return $trimmed !== '' ? $trimmed : $content;
}

function aismart_normalize_translate_lang($lang) {
    $lang = strtolower(trim((string) $lang));
    if ($lang === '') {
        return 'auto';
    }

    $map = [
        'zh-hans' => 'zh-CN',
        'zh-hant' => 'zh-TW',
        'zh-cn' => 'zh-CN',
        'zh-hk' => 'zh-TW',
        'fil' => 'tl',
    ];

    if (isset($map[$lang])) {
        return $map[$lang];
    }

    if (strpos($lang, '_') !== false) {
        $lang = explode('_', $lang)[0];
    }

    return $lang;
}

// AJAX: Get post data by ID (resume draft)
add_action('wp_ajax_aismart_get_post_data', 'aismart_get_post_data');
function aismart_get_post_data() {
    if (!current_user_can('manage_options')) {
        wp_send_json_error(['message' => 'Unauthorized'], 403);
    }

    $post_id = isset($_POST['post_id']) ? absint($_POST['post_id']) : 0;
    if ($post_id <= 0) {
        wp_send_json_error(['message' => 'Invalid post ID'], 400);
    }

    $post = get_post($post_id);
    if (!$post || $post->post_type !== 'post') {
        wp_send_json_error(['message' => 'Post not found'], 404);
    }

    $featured_image = get_the_post_thumbnail_url($post_id, 'full');
    $categories = get_the_category($post_id);
    $primary_category = (!empty($categories) && !is_wp_error($categories)) ? (string) $categories[0]->name : 'Auto';
    $tags = wp_get_post_tags($post_id, ['fields' => 'names']);
    $tags_string = (!empty($tags) && !is_wp_error($tags)) ? implode(', ', $tags) : '';

    wp_send_json_success([
        'id' => (int) $post->ID,
        'title' => $post->post_title,
        'content' => $post->post_content,
        'excerpt' => $post->post_excerpt,
        'post_status' => (string) $post->post_status,
        'scheduled_at' => $post->post_status === 'future' ? get_post_time('Y-m-d\TH:i', false, $post_id) : '',
        'featured_image' => $featured_image ? $featured_image : '',
        'category' => $primary_category,
        'tags' => $tags_string,
    ]);
}

/* function aismart_token_admin_styles() {
    wp_enqueue_style('aismart-token-admin', plugins_url('assets/css/token-admin.css', __FILE__));
} */

if (!function_exists('aismart_onboarding_provider_plugin_map')) {
function aismart_onboarding_provider_plugin_map() {
    return [
        'wpml' => ['sitepress-multilingual-cms/sitepress.php'],
        'polylang' => ['polylang/polylang.php'],
        'multilingualpress' => [
            'multilingual-press/multilingual-press.php',
            'multilingual-press/multilingualpress.php',
            'multilingualpress/multilingualpress.php',
        ],
        'translatepress' => ['translatepress-multilingual/index.php'],
        'falang' => ['falang/falang.php'],
        'qtranslate' => ['qtranslate-x/qtranslate.php', 'qtranslate-xt/qtranslate.php', 'qtranslate/qtranslate.php'],
        'wpglobus' => ['wpglobus/wpglobus.php'],
        'bogo' => ['bogo/bogo.php'],
    ];
}
}

if (!function_exists('aismart_onboarding_provider_groups')) {
function aismart_onboarding_provider_groups() {
    return [
        'enterprise' => ['wpml', 'polylang', 'multilingualpress', 'translatepress'],
        'hybrid' => ['falang', 'qtranslate', 'wpglobus', 'bogo'],
    ];
}
}

if (!function_exists('aismart_onboarding_group_for_provider')) {
function aismart_onboarding_group_for_provider($provider) {
    $provider = aismart_normalize_provider_key($provider);
    $groups = aismart_onboarding_provider_groups();
    foreach ($groups as $group => $items) {
        if (in_array($provider, $items, true)) {
            return (string) $group;
        }
    }
    return '';
}
}

if (!function_exists('aismart_onboarding_first_existing_plugin_file')) {
function aismart_onboarding_first_existing_plugin_file($provider) {
    $provider = aismart_normalize_provider_key($provider);
    $map = aismart_onboarding_provider_plugin_map();
    $candidates = isset($map[$provider]) ? (array) $map[$provider] : [];
    foreach ($candidates as $plugin_file) {
        $path = trailingslashit(WP_PLUGIN_DIR) . ltrim((string) $plugin_file, '/');
        if (file_exists($path)) {
            return (string) $plugin_file;
        }
    }
    return '';
}
}

if (!function_exists('aismart_onboarding_plugin_is_active_anywhere')) {
function aismart_onboarding_plugin_is_active_anywhere($plugin_file) {
    if ($plugin_file === '') {
        return false;
    }

    $is_active = false;
    if (function_exists('is_plugin_active')) {
        $is_active = is_plugin_active($plugin_file);
    }
    if (!$is_active && function_exists('is_plugin_active_for_network')) {
        $is_active = is_plugin_active_for_network($plugin_file);
    }
    return (bool) $is_active;
}
}

if (!function_exists('aismart_onboarding_apply_provider_group_switch')) {
function aismart_onboarding_apply_provider_group_switch($selected_provider) {
    $selected_provider = aismart_normalize_provider_key($selected_provider);
    if ($selected_provider === '') {
        return [
            'ok' => false,
            'message' => 'No provider selected.',
        ];
    }

    $selected_group = aismart_onboarding_group_for_provider($selected_provider);
    if ($selected_group === '') {
        return [
            'ok' => false,
            'message' => 'Selected provider is not in a managed group.',
            'selected_provider' => $selected_provider,
        ];
    }

    return [
        'ok' => true,
        'selected_provider' => $selected_provider,
        'selected_group' => $selected_group,
        'activated' => [],
        'deactivated' => [],
        'missing' => [],
        'errors' => [],
        'message' => 'No plugin activation/deactivation was performed. Please manage multilingual plugin activation manually in Plugins > Installed Plugins.',
    ];
}
}
