<?php
/**
 * ZERTI admin screen — register/enqueue assets with tab-based bundles.
 */

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

/**
 * @return string Filemtime-based version when the asset exists.
 */
/**
 * REST client settings for admin grids (when zerti_use_rest_api filter is true).
 *
 * @return array{restUrl?:string,restNonce?:string}
 */
function zerti_rest_client_config(string $rest_path): array
{
    if (!apply_filters('zerti_use_rest_api', true)) {
        return [];
    }

    return [
        'restUrl' => rest_url('zerti/v1/' . ltrim($rest_path, '/')),
        'restNonce' => wp_create_nonce('wp_rest'),
    ];
}

function zerti_asset_version(string $relative_path): string
{
    $path = plugin_dir_path(ZERTI_PLUGIN_FILE) . ltrim($relative_path, '/');
    if (is_readable($path)) {
        return (string) filemtime($path);
    }

    return ZERTI_VERSION;
}

/**
 * Register third-party libraries vendored under assets/ (no CDN or cross-plugin URLs).
 */
function zerti_register_bundled_plugin_assets(): void
{
    $plugin = ZERTI_PLUGIN_FILE;
    $suffix = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '.min';

    wp_register_style(
        'zerti-wc-select2',
        plugins_url('assets/select2/select2.css', $plugin),
        [],
        zerti_asset_version('assets/select2/select2.css')
    );
    wp_register_style(
        'zerti-woocommerce-admin',
        plugins_url('assets/woocommerce/css/admin.css', $plugin),
        [],
        zerti_asset_version('assets/woocommerce/css/admin.css')
    );

    wp_register_script(
        'selectWoo',
        plugins_url('assets/selectwoo/selectWoo.full' . $suffix . '.js', $plugin),
        ['jquery'],
        zerti_asset_version('assets/selectwoo/selectWoo.full' . $suffix . '.js'),
        true
    );
    wp_register_script(
        'wc-enhanced-select',
        plugins_url('assets/woocommerce/js/admin/wc-enhanced-select' . $suffix . '.js', $plugin),
        ['jquery', 'selectWoo'],
        zerti_asset_version('assets/woocommerce/js/admin/wc-enhanced-select' . $suffix . '.js'),
        true
    );
    wp_register_script(
        'wc-admin-meta-boxes',
        plugins_url('assets/woocommerce/js/admin/meta-boxes' . $suffix . '.js', $plugin),
        ['jquery', 'jquery-ui-datepicker', 'wc-enhanced-select'],
        zerti_asset_version('assets/woocommerce/js/admin/meta-boxes' . $suffix . '.js'),
        true
    );
    wp_register_script(
        'wc-admin-coupon-meta-boxes',
        plugins_url('assets/woocommerce/js/admin/meta-boxes-coupon' . $suffix . '.js', $plugin),
        ['wc-admin-meta-boxes'],
        zerti_asset_version('assets/woocommerce/js/admin/meta-boxes-coupon' . $suffix . '.js'),
        true
    );
    wp_register_script(
        'wc-product-export',
        plugins_url('assets/woocommerce/js/admin/wc-product-export' . $suffix . '.js', $plugin),
        ['jquery'],
        zerti_asset_version('assets/woocommerce/js/admin/wc-product-export' . $suffix . '.js'),
        true
    );
    wp_register_script(
        'wc-product-import',
        plugins_url('assets/woocommerce/js/admin/wc-product-import' . $suffix . '.js', $plugin),
        ['jquery'],
        zerti_asset_version('assets/woocommerce/js/admin/wc-product-import' . $suffix . '.js'),
        true
    );

    wp_register_script(
        'zerti-ag-grid-no-cdn',
        plugins_url('assets/js/zerti-ag-grid-no-cdn.js', $plugin),
        [],
        zerti_asset_version('assets/js/zerti-ag-grid-no-cdn.js'),
        true
    );
}

/**
 * Ordered admin CSS layers (Phase 2 split). Manifest: assets/css/zerti-admin.css.
 *
 * @return list<string>
 */
function zerti_admin_css_layer_paths(): array
{
    return [
        'assets/css/layers/zerti-wp-chrome.css',
        'assets/css/layers/zerti-base.css',
        'assets/css/layers/zerti-layout.css',
        'assets/css/layers/zerti-components.css',
        'assets/css/layers/zerti-integrations-ag-grid.css',
        'assets/css/layers/zerti-integrations-widgets.css',
        'assets/css/layers/zerti-features-shop.css',
        'assets/css/layers/zerti-features-inventory.css',
        'assets/css/layers/zerti-features-misc.css',
    ];
}

/**
 * WP style handle for one admin CSS layer file.
 */
function zerti_admin_css_layer_handle(string $relative_path): string
{
    return 'zerti-admin-' . basename($relative_path, '.css');
}

/**
 * @return list<string>
 */
function zerti_admin_css_layer_handles(): array
{
    return array_map('zerti_admin_css_layer_handle', zerti_admin_css_layer_paths());
}

/**
 * Last layer handle — dependents (LTR overrides, Quill, Select2) attach here.
 */
function zerti_admin_css_stack_handle(): string
{
    $paths = zerti_admin_css_layer_paths();
    $last = end($paths);

    return $last !== false ? zerti_admin_css_layer_handle($last) : 'zerti-tokens';
}

/**
 * Register admin CSS layers in load order (each file is enqueued directly; no @import chain).
 *
 * @return string Handle of the last registered layer.
 */
function zerti_admin_register_css_layers(string $plugin): string
{
    $deps = ['zerti-tokens'];
    $last_handle = 'zerti-tokens';

    foreach (zerti_admin_css_layer_paths() as $relative_path) {
        $handle = zerti_admin_css_layer_handle($relative_path);
        wp_register_style(
            $handle,
            plugins_url($relative_path, $plugin),
            $deps,
            zerti_asset_version($relative_path)
        );
        $deps = [$handle];
        $last_handle = $handle;
    }

    return $last_handle;
}

/**
 * Cache-bust version for the full admin stylesheet stack (max mtime across layers + manifest).
 */
function zerti_admin_css_version(): string
{
    $paths = array_merge(['assets/css/zerti-admin.css'], zerti_admin_css_layer_paths());
    $max = 0;
    foreach ($paths as $relative_path) {
        $path = plugin_dir_path(ZERTI_PLUGIN_FILE) . ltrim($relative_path, '/');
        if (is_readable($path)) {
            $max = max($max, (int) filemtime($path));
        }
    }

    return $max > 0 ? (string) $max : ZERTI_VERSION;
}

/**
 * Public URLs for admin CSS layers (print invoice and other standalone pages).
 *
 * @return list<string>
 */
function zerti_admin_css_layer_urls(): array
{
    $urls = [];
    foreach (zerti_admin_css_layer_paths() as $relative_path) {
        $urls[] = plugins_url($relative_path, ZERTI_PLUGIN_FILE);
    }

    return $urls;
}

/**
 * Client config for inventory › categories (must load with core — lazy bundles skip wp_localize_script).
 *
 * @return array<string, mixed>
 */
function zerti_admin_inv_categories_client_config(): array
{
    return [
        'ajaxUrl' => admin_url('admin-ajax.php'),
        'nonce' => wp_create_nonce('zerti_product_categories'),
        'listAction' => 'zerti_product_categories_list',
        'saveAction' => 'zerti_product_category_save',
        'deleteAction' => 'zerti_product_category_delete',
        'reorderAction' => 'zerti_product_categories_reorder',
        'i18n' => [
            'loading' => __('Loading…', 'zerti'),
            'saving' => __('Saving…', 'zerti'),
            'loadError' => __('Failed to load categories.', 'zerti'),
            'emptyTree' => __('Nothing found. Click «Add category» to create a new item.', 'zerti'),
            'noResults' => __('No category matched this search.', 'zerti'),
            'newCategory' => __('New category', 'zerti'),
            'editCategory' => __('Edit category', 'zerti'),
            'editBtnLabel' => __('Edit', 'zerti'),
            'editorBarDefault' => __('Click to create a new category', 'zerti'),
            'editorBarNew' => __('Add new category', 'zerti'),
            'editorBarEdit' => __('Edit: ', 'zerti'),
            'saved' => __('Category saved.', 'zerti'),
            'saveError' => __('Could not save category.', 'zerti'),
            'deleteError' => __('Could not delete category.', 'zerti'),
            /* translators: %s: category name */
            'deleteConfirm' => __('Are you sure you want to delete category «%s»?', 'zerti'),
            'deleteHasChildren' => __('This category has subcategories; delete or move them first.', 'zerti'),
            'nameRequired' => __('Category name is required.', 'zerti'),
            'noImage' => __('No image', 'zerti'),
            'pickImage' => __('Select category image', 'zerti'),
            'useImage' => __('Use this image', 'zerti'),
            'productsCount' => __('Product count', 'zerti'),
            'expand' => __('Open', 'zerti'),
            'collapse' => __('Close', 'zerti'),
            'feedbackDurationMs' => 2200,
        ],
    ];
}

/**
 * Client config for inventory › tags.
 *
 * @return array<string, mixed>
 */
function zerti_admin_inv_tags_client_config(): array
{
    return [
        'ajaxUrl' => admin_url('admin-ajax.php'),
        'nonce' => wp_create_nonce('zerti_product_tags'),
        'listAction' => 'zerti_product_tags_list',
        'saveAction' => 'zerti_product_tag_save',
        'deleteAction' => 'zerti_product_tag_delete',
        'i18n' => [
            'loading' => __('Loading…', 'zerti'),
            'saving' => __('Saving…', 'zerti'),
            'loadError' => __('Failed to load tags.', 'zerti'),
            'emptyTree' => __('Nothing found. Click «Add tag» to create a new item.', 'zerti'),
            'noResults' => __('No tag matched this search.', 'zerti'),
            'newCategory' => __('New tag', 'zerti'),
            'editCategory' => __('Edit tag', 'zerti'),
            'editBtnLabel' => __('Edit', 'zerti'),
            'editorBarDefault' => __('Click to create a new tag', 'zerti'),
            'editorBarNew' => __('Add new tag', 'zerti'),
            'editorBarEdit' => __('Edit: ', 'zerti'),
            'saved' => __('Tag saved.', 'zerti'),
            'saveError' => __('Could not save tag.', 'zerti'),
            'deleteError' => __('Could not delete tag.', 'zerti'),
            /* translators: %s: tag name */
            'deleteConfirm' => __('Are you sure you want to delete tag «%s»?', 'zerti'),
            'nameRequired' => __('Tag name is required.', 'zerti'),
            'productsCount' => __('Product count', 'zerti'),
            'feedbackDurationMs' => 2200,
        ],
    ];
}

/**
 * Client config for inventory › brands.
 *
 * @return array<string, mixed>
 */
function zerti_admin_inv_brands_client_config(): array
{
    return [
        'ajaxUrl' => admin_url('admin-ajax.php'),
        'nonce' => wp_create_nonce('zerti_product_brands'),
        'listAction' => 'zerti_product_brands_list',
        'saveAction' => 'zerti_product_brand_save',
        'deleteAction' => 'zerti_product_brand_delete',
        'i18n' => [
            'loading' => __('Loading…', 'zerti'),
            'saving' => __('Saving…', 'zerti'),
            'loadError' => __('Failed to load brands.', 'zerti'),
            'emptyTree' => __('Nothing found. Click «Add brand» to create a new item.', 'zerti'),
            'noResults' => __('No brand matched this search.', 'zerti'),
            'newCategory' => __('New brand', 'zerti'),
            'editCategory' => __('Edit brand', 'zerti'),
            'editBtnLabel' => __('Edit', 'zerti'),
            'editorBarDefault' => __('Click to create a new brand', 'zerti'),
            'editorBarNew' => __('Add new brand', 'zerti'),
            'editorBarEdit' => __('Edit: ', 'zerti'),
            'saved' => __('Brand saved.', 'zerti'),
            'saveError' => __('Could not save brand.', 'zerti'),
            'deleteError' => __('Could not delete brand.', 'zerti'),
            /* translators: %s: brand name */
            'deleteConfirm' => __('Are you sure you want to delete brand «%s»?', 'zerti'),
            'deleteHasChildren' => __('This brand has child brands; delete or move them first.', 'zerti'),
            'nameRequired' => __('Brand name is required.', 'zerti'),
            'noImage' => __('No image', 'zerti'),
            'pickImage' => __('Select brand image', 'zerti'),
            'useImage' => __('Use this image', 'zerti'),
            'productsCount' => __('Product count', 'zerti'),
            'expand' => __('Open', 'zerti'),
            'collapse' => __('Close', 'zerti'),
            'feedbackDurationMs' => 2200,
        ],
    ];
}

/**
 * Client config for product reviews / comments grids.
 *
 * @return array<string, mixed>
 */
function zerti_admin_product_feedback_client_config(string $kind = 'review'): array
{
    if (!zerti_product_feedback_kind_is_valid($kind)) {
        $kind = 'review';
    }

    $is_review = $kind === 'review';

    if ($is_review) {
        $i18n_extra = [
            'loadError' => __('Failed to load reviews.', 'zerti'),
            'emptyList' => __('No reviews yet.', 'zerti'),
            'noResults' => __('No reviews matched this filter.', 'zerti'),
            'editorBarDefault' => __('Click a row in the list to edit', 'zerti'),
            'editorBarEdit' => __('Edit review: ', 'zerti'),
            'saved' => __('Review saved.', 'zerti'),
            'saveError' => __('Could not save review.', 'zerti'),
            'deleteError' => __('Could not delete review.', 'zerti'),
            /* translators: %s: review identifier */
            'deleteConfirm' => __('Are you sure you want to delete review «%s»?', 'zerti'),
            'noRowsToShow' => __('No reviews yet.', 'zerti'),
        ];
    } else {
        $i18n_extra = [
            'loadError' => __('Failed to load comments.', 'zerti'),
            'emptyList' => __('No comments yet.', 'zerti'),
            'noResults' => __('No comments matched this filter.', 'zerti'),
            'editorBarDefault' => __('Click a row in the list to edit', 'zerti'),
            'editorBarEdit' => __('Edit comment: ', 'zerti'),
            'saved' => __('Comment saved.', 'zerti'),
            'saveError' => __('Could not save comment.', 'zerti'),
            'deleteError' => __('Could not delete comment.', 'zerti'),
            /* translators: %s: comment identifier */
            'deleteConfirm' => __('Are you sure you want to delete comment «%s»?', 'zerti'),
            'noRowsToShow' => __('No comments yet.', 'zerti'),
        ];
    }

    return [
        'ajaxUrl' => admin_url('admin-ajax.php'),
        'nonce' => wp_create_nonce('zerti_product_reviews'),
        'kind' => $kind,
        'listAction' => 'zerti_product_reviews_list',
        'saveAction' => 'zerti_product_review_save',
        'deleteAction' => 'zerti_product_review_delete',
        'statusChoices' => zerti_product_review_status_choices(),
        'i18n' => array_merge(
            zerti_admin_grid_shared_i18n(),
            [
            'loading' => __('Loading…', 'zerti'),
            'colProduct' => __('Product', 'zerti'),
            'colAuthor' => __('Author', 'zerti'),
            'colRating' => __('Rating', 'zerti'),
            'colStatus' => __('Status', 'zerti'),
            'colDate' => __('Date', 'zerti'),
            'productLabel' => __('Product', 'zerti'),
            'feedbackDurationMs' => 2200,
            ],
            $i18n_extra
        ),
    ];
}

/**
 * Client config for inventory › comments (product reviews).
 *
 * @return array<string, mixed>
 */
function zerti_admin_inv_reviews_client_config(): array
{
    return zerti_admin_product_feedback_client_config('review');
}

/**
 * Client config for inventory › attribute groups.
 *
 * @return array<string, mixed>
 */
function zerti_admin_inv_attribute_groups_client_config(): array
{
    return [
        'ajaxUrl' => admin_url('admin-ajax.php'),
        'nonce' => wp_create_nonce('zerti_product_attribute_groups'),
        'listAction' => 'zerti_product_attribute_groups_list',
        'saveAction' => 'zerti_product_attribute_group_save',
        'deleteAction' => 'zerti_product_attribute_group_delete',
        'i18n' => [
            'loading' => __('Loading…', 'zerti'),
            'saving' => __('Saving…', 'zerti'),
            'loadError' => __('Failed to load attribute groups.', 'zerti'),
            'emptyTree' => __('Nothing found. Click «Add group» to create a new item.', 'zerti'),
            'noResults' => __('No group matched this search.', 'zerti'),
            'newCategory' => __('New attribute group', 'zerti'),
            'editCategory' => __('Edit attribute group', 'zerti'),
            'editBtnLabel' => __('Edit', 'zerti'),
            'editorBarDefault' => __('Click to create a new attribute group', 'zerti'),
            'editorBarNew' => __('Add new attribute group', 'zerti'),
            'editorBarEdit' => __('Edit: ', 'zerti'),
            'saved' => __('Attribute group saved.', 'zerti'),
            'saveError' => __('Could not save attribute group.', 'zerti'),
            'deleteError' => __('Delete failed.', 'zerti'),
            /* translators: %s: attribute group name */
            'deleteConfirm' => __('Are you sure you want to delete group «%s»?', 'zerti'),
            'attributesCount' => __('Attributes in group', 'zerti'),
            'nameRequired' => __('Group name is required.', 'zerti'),
            'feedbackDurationMs' => 2200,
        ],
    ];
}

/**
 * Client config for inventory › attributes.
 *
 * @return array<string, mixed>
 */
function zerti_admin_inv_attributes_client_config(): array
{
    return [
        'ajaxUrl' => admin_url('admin-ajax.php'),
        'nonce' => wp_create_nonce('zerti_product_attributes'),
        'listAction' => 'zerti_product_attributes_list',
        'saveAttrAction' => 'zerti_product_attribute_save',
        'deleteAttrAction' => 'zerti_product_attribute_delete',
        'saveTermAction' => 'zerti_product_attribute_term_save',
        'deleteTermAction' => 'zerti_product_attribute_term_delete',
        'i18n' => [
            'loading' => __('Loading…', 'zerti'),
            'saving' => __('Saving…', 'zerti'),
            'loadError' => __('Failed to load attributes.', 'zerti'),
            'emptyTree' => __('Nothing found. Click «Add attribute» to create a new item.', 'zerti'),
            'noResults' => __('No attribute matched this search.', 'zerti'),
            'newCategory' => __('New attribute', 'zerti'),
            'editCategory' => __('Edit attribute', 'zerti'),
            'editBtnLabel' => __('Edit', 'zerti'),
            'editorBarDefault' => __('Click to create a new attribute', 'zerti'),
            'editorBarNew' => __('Add new attribute', 'zerti'),
            'editorBarEdit' => __('Edit: ', 'zerti'),
            'saved' => __('Attribute saved.', 'zerti'),
            'saveError' => __('Could not save attribute.', 'zerti'),
            'deleteError' => __('Delete failed.', 'zerti'),
            /* translators: %s: attribute name */
            'deleteConfirm' => __('Are you sure you want to delete attribute «%s»?', 'zerti'),
            'termsCount' => __('Term count', 'zerti'),
            'nameRequired' => __('Attribute name is required.', 'zerti'),
            'termNameRequired' => __('Term name is required.', 'zerti'),
            'termSaved' => __('Term saved.', 'zerti'),
            'termSaveError' => __('Could not save term.', 'zerti'),
            /* translators: %s: attribute term name */
            'deleteTermConfirm' => __('Are you sure you want to delete term «%s»?', 'zerti'),
            'emptyTerms' => __('No terms defined for this attribute yet.', 'zerti'),
            'newTerm' => __('New term', 'zerti'),
            'editTerm' => __('Edit term: ', 'zerti'),
            'editTermBtn' => __('Edit', 'zerti'),
            'feedbackDurationMs' => 2200,
        ],
    ];
}

/**
 * Client config for inventory › product add/edit (must load with core — lazy bundles skip wp_localize_script).
 *
 * @return array<string, mixed>
 */
function zerti_admin_product_edit_client_config(): array
{
    return [
        'ajaxUrl' => admin_url('admin-ajax.php'),
        'nonce' => wp_create_nonce('zerti_product_save'),
        'saveAction' => 'zerti_product_save',
        'searchAction' => 'zerti_product_search',
        'tagsNonce' => wp_create_nonce('zerti_product_tags'),
        'tagsSearchAction' => 'zerti_product_tags_search',
        'brandsNonce' => wp_create_nonce('zerti_product_brands'),
        'brandsSearchAction' => 'zerti_product_brands_search',
        'attrTermsNonce' => wp_create_nonce('zerti_product_attributes'),
        'attrTermsAction' => 'zerti_product_edit_attribute_terms',
        'attrSaveTermAction' => 'zerti_product_attribute_term_save',
        'i18n' => [
            'saving' => __('Saving…', 'zerti'),
            'applying' => __('Applying…', 'zerti'),
            'saveError' => __('Could not save product.', 'zerti'),
            'pickImage' => __('Select product image', 'zerti'),
            'useImage' => __('Use this image', 'zerti'),
            'pickGallery' => __('Add images to gallery', 'zerti'),
            'addGallery' => __('Add to gallery', 'zerti'),
            'searchProducts' => __('Search product…', 'zerti'),
            'noProducts' => __('No products found.', 'zerti'),
            'noTags' => __('No tags found.', 'zerti'),
            'noBrands' => __('No brands found.', 'zerti'),
            'pickFile' => __('Select file', 'zerti'),
            'useFile' => __('Use file', 'zerti'),
            'addAttribute' => __('Add attribute', 'zerti'),
            'addDownload' => __('Add download file', 'zerti'),
            'remove' => __('Delete', 'zerti'),
            'attributeNamePlaceholder' => __('Attribute name', 'zerti'),
            'attributeValuesPlaceholder' => __('e.g. Blue | Large', 'zerti'),
            'selectValues' => __('Select values', 'zerti'),
            'selectAll' => __('Select all', 'zerti'),
            'selectNone' => __('Select none', 'zerti'),
            'createValue' => __('Create value', 'zerti'),
            'createValuePrompt' => __('Enter a name for the new value:', 'zerti'),
            'termSaveFailed' => __('Could not create value.', 'zerti'),
            'pickFileButton' => __('Select', 'zerti'),
            'usedForVariations' => __('Used for variations', 'zerti'),
            'variations' => __('Variations', 'zerti'),
            'generateVariations' => __('Generate variations', 'zerti'),
            'addVariation' => __('Add variation', 'zerti'),
            'variationLabel' => __('Variation', 'zerti'),
            'manageStock' => __('Manage stock', 'zerti'),
            'variationsHint' => __('Mark attributes as used for variations and add values on the Attributes tab first.', 'zerti'),
            'selectVariationValue' => __('Select a value for each variation attribute.', 'zerti'),
            'noNewVariations' => __('All possible variations already exist.', 'zerti'),
            'sku' => __('Product ID (SKU)', 'zerti'),
            'regularPrice' => __('Regular price', 'zerti'),
            'salePrice' => __('Sale price', 'zerti'),
            'enabled' => __('Enabled', 'zerti'),
            /* translators: %d: number of variations created */
            'variationsGenerated' => __('%d variations created. Set price and stock for each, then publish.', 'zerti'),
        ],
        'globalAttributes' => function_exists('zerti_product_edit_global_attribute_choices')
            ? zerti_product_edit_global_attribute_choices()
            : [],
        'calendar' => function_exists('zerti_get_calendar') ? zerti_get_calendar() : 'jalali',
    ];
}

/**
 * Core stylesheet handles for the admin shell (direction-aware).
 *
 * @return list<string>
 */
function zerti_admin_core_style_handles(): array
{
    $styles = [
        'zerti-bootstrap',
        'zerti-fontawesome',
        'zerti-vazirmatn',
        'zerti-tokens',
    ];
    if (function_exists('zerti_is_admin_rtl') && zerti_is_admin_rtl()) {
        array_splice($styles, 1, 0, ['zerti-bootstrap-rtl']);
    }
    $styles = array_merge($styles, zerti_admin_css_layer_handles());
    if (!function_exists('zerti_is_admin_rtl') || !zerti_is_admin_rtl()) {
        $styles[] = 'zerti-admin-ltr';
    }

    return $styles;
}

/**
 * Datepicker script handles for the active admin calendar.
 *
 * @return list<string>
 */
function zerti_admin_datepicker_script_handles(): array
{
    $calendar = function_exists('zerti_get_calendar') ? zerti_get_calendar() : 'jalali';
    if ($calendar === 'gregorian') {
        return ['zerti-gregorian-datepicker'];
    }
    if ($calendar === 'hijri') {
        return ['zerti-hijri-date', 'zerti-hijri-datepicker'];
    }

    return ['zerti-jalali-date', 'zerti-jalali-datepicker'];
}

/**
 * Primary datepicker script handle for the admin router (zerti-admin-datepicker deps).
 */
function zerti_admin_datepicker_router_handle(): string
{
    $calendar = function_exists('zerti_get_calendar') ? zerti_get_calendar() : 'jalali';
    if ($calendar === 'gregorian') {
        return 'zerti-gregorian-datepicker';
    }
    if ($calendar === 'hijri') {
        return 'zerti-hijri-datepicker';
    }

    return 'zerti-jalali-datepicker';
}

/**
 * Script deps for zerti-server-clock (calendar conversion library).
 *
 * @return list<string>
 */
function zerti_admin_clock_script_deps(): array
{
    $calendar = function_exists('zerti_get_calendar') ? zerti_get_calendar() : 'jalali';
    if ($calendar === 'hijri') {
        return ['zerti-localize-digits', 'zerti-hijri-date'];
    }
    if ($calendar === 'jalali') {
        return ['zerti-localize-digits', 'zerti-jalali-date'];
    }

    return ['zerti-localize-digits'];
}

/**
 * Core script handles for the admin shell (calendar-aware datepickers).
 *
 * @return list<string>
 */
function zerti_admin_core_script_handles(): array
{
    return array_merge(
        ['zerti-bootstrap-bundle'],
        zerti_admin_datepicker_script_handles(),
        ['zerti-localize-digits', 'zerti-admin-datepicker', 'zerti-server-clock', 'zerti-confirm-alert', 'zerti-grid-i18n', 'zerti-admin-components', 'zerti-global-search', 'zerti-admin-notes']
    );
}

/**
 * Asset bundles (styles + script handles) used for conditional load.
 *
 * @return array<string, array{styles:list<string>,scripts:list<string>,tab_deps:array<string,list<string>>}>
 */
function zerti_admin_asset_bundles(): array
{
    $bundles = [
        'core' => [
            'styles' => zerti_admin_core_style_handles(),
            'scripts' => zerti_admin_core_script_handles(),
        ],
        'grid' => [
            'styles' => [
                'zerti-ag-grid',
                'zerti-ag-grid-quartz',
            ],
            'scripts' => [
                'zerti-ag-grid',
                'zerti-shop-orders-grid',
                'zerti-customers-grid',
                'zerti-payments-grid',
                'zerti-products-grid',
                'zerti-sales-report-grid',
                'zerti-reviews-grid',
            ],
        ],
        'home-chart' => [
            'styles' => [],
            'scripts' => [
                'chart-js',
                'zerti-home-chart',
            ],
        ],
        'shop-detail' => [
            'styles' => [],
            'scripts' => [
                'zerti-shop-order-detail-actions',
            ],
        ],
        'inventory-categories' => [
            'styles' => [],
            'scripts' => [
                'zerti-inventory-categories',
            ],
        ],
        'inventory-tags' => [
            'styles' => [],
            'scripts' => [
                'zerti-inventory-tags',
            ],
        ],
        'inventory-brands' => [
            'styles' => [],
            'scripts' => [
                'zerti-inventory-brands',
            ],
        ],
        'inventory-reviews' => [
            'styles' => [],
            'scripts' => [
                'zerti-inventory-reviews',
            ],
        ],
        'inventory-attributes' => [
            'styles' => [],
            'scripts' => [
                'zerti-inventory-attributes',
            ],
        ],
        'inventory-attribute-groups' => [
            'styles' => [],
            'scripts' => [
                'zerti-inventory-attribute-groups',
            ],
        ],
        'inventory-product-edit' => [
            'styles' => [
                'quill-snow',
                'zerti-quill-theme',
                'zerti-wc-select2',
                'zerti-product-attr-select2',
            ],
            'scripts' => [
                'quill',
                'zerti-product-rich-editor',
                'wc-enhanced-select',
                'zerti-product-edit',
            ],
        ],
        'inventory-import-export' => [
            'styles' => ['zerti-wc-select2'],
            'scripts' => ['wc-enhanced-select', 'wc-product-export', 'zerti-inventory-import-export'],
        ],
        'financial-coupons' => [
            'styles' => ['zerti-woocommerce-admin', 'zerti-wc-select2', 'zerti-wc-coupon-form'],
            'scripts' => ['wc-enhanced-select', 'wc-admin-meta-boxes', 'wc-admin-coupon-meta-boxes', 'zerti-coupons-grid', 'zerti-financial-coupons'],
        ],
    ];

    return (array) apply_filters('zerti_admin_asset_bundles', $bundles);
}

/**
 * Which bundles each tab needs (SPA may load others lazily on first visit).
 *
 * @return array<string, list<string>>
 */
function zerti_admin_tab_bundle_map(): array
{
    $map = [
        'home' => ['core', 'home-chart'],
        'shop' => ['core', 'grid', 'shop-detail'],
        'customers' => ['core', 'grid'],
        'reviews' => ['core', 'grid', 'inventory-reviews'],
        'comments' => ['core', 'grid', 'inventory-reviews'],
        'inventory' => ['core', 'grid', 'inventory-categories', 'inventory-tags', 'inventory-brands', 'inventory-attributes', 'inventory-attribute-groups', 'inventory-product-edit', 'inventory-import-export'],
        'financial' => ['core', 'grid', 'financial-coupons'],
        'settings' => ['core'],
    ];

    return (array) apply_filters('zerti_admin_tab_bundle_map', $map);
}

/**
 * @return list<string>
 */
function zerti_admin_bundles_for_tab(string $tab): array
{
    $map = zerti_admin_tab_bundle_map();
    $bundles = $map[$tab] ?? ['core'];
    $out = ['core'];
    foreach ($bundles as $bundle) {
        if (!in_array($bundle, $out, true)) {
            $out[] = $bundle;
        }
    }

    return $out;
}

/**
 * Register all ZERTI admin assets (enqueue selectively per initial tab).
 */
function zerti_admin_register_assets(): void
{
    $plugin = ZERTI_PLUGIN_FILE;

    foreach (
        [
            'selectWoo',
            'wc-enhanced-select',
            'wc-admin-meta-boxes',
            'wc-admin-coupon-meta-boxes',
            'wc-product-export',
            'wc-product-import',
        ] as $script_handle
    ) {
        wp_deregister_script($script_handle);
    }
    foreach (['zerti-wc-select2', 'zerti-woocommerce-admin'] as $style_handle) {
        wp_deregister_style($style_handle);
    }

    zerti_register_bundled_plugin_assets();

    wp_register_style(
        'zerti-bootstrap',
        plugins_url('assets/bootstrap/css/bootstrap.min.css', $plugin),
        [],
        ZERTI_BOOTSTRAP_VERSION
    );
    wp_register_style(
        'zerti-bootstrap-rtl',
        plugins_url('assets/bootstrap/css/bootstrap.rtl.min.css', $plugin),
        ['zerti-bootstrap'],
        ZERTI_BOOTSTRAP_VERSION
    );
    wp_register_script(
        'zerti-bootstrap-bundle',
        plugins_url('assets/bootstrap/js/bootstrap.bundle.min.js', $plugin),
        [],
        ZERTI_BOOTSTRAP_VERSION,
        true
    );
    wp_register_style(
        'zerti-fontawesome',
        plugins_url('assets/fontawesome/css/all.min.css', $plugin),
        ['zerti-bootstrap'],
        ZERTI_FONTAWESOME_VERSION
    );
    wp_register_style(
        'zerti-vazirmatn',
        plugins_url('assets/css/zerti-vazirmatn.css', $plugin),
        ['zerti-fontawesome'],
        ZERTI_VERSION
    );
    wp_register_style(
        'zerti-ag-grid',
        plugins_url('assets/ag-grid/css/ag-grid.min.css', $plugin),
        ['zerti-vazirmatn'],
        zerti_asset_version('assets/ag-grid/css/ag-grid.min.css')
    );
    wp_register_style(
        'zerti-ag-grid-quartz',
        plugins_url('assets/ag-grid/css/ag-theme-quartz.min.css', $plugin),
        ['zerti-ag-grid', 'zerti-localize-digits'],
        zerti_asset_version('assets/ag-grid/css/ag-theme-quartz.min.css')
    );
    wp_register_style(
        'zerti-tokens',
        plugins_url('assets/css/zerti-tokens.css', $plugin),
        ['zerti-vazirmatn'],
        zerti_asset_version('assets/css/zerti-tokens.css')
    );
    $admin_css_stack = zerti_admin_register_css_layers($plugin);
    wp_register_style(
        'zerti-admin',
        plugins_url('assets/css/zerti-admin.css', $plugin),
        [$admin_css_stack],
        zerti_admin_css_version()
    );
    wp_register_style(
        'zerti-admin-ltr',
        plugins_url('assets/css/zerti-admin-ltr.css', $plugin),
        [$admin_css_stack],
        zerti_asset_version('assets/css/zerti-admin-ltr.css')
    );

    wp_register_script(
        'zerti-localize-digits',
        plugins_url('assets/js/zerti-localize-digits.js', $plugin),
        [],
        zerti_asset_version('assets/js/zerti-localize-digits.js'),
        true
    );
    wp_register_script(
        'zerti-ag-grid',
        plugins_url('assets/ag-grid/js/ag-grid-community.min.js', $plugin),
        ['zerti-ag-grid-no-cdn'],
        zerti_asset_version('assets/ag-grid/js/ag-grid-community.min.js'),
        true
    );
    wp_register_script(
        'zerti-shop-orders-grid',
        plugins_url('assets/js/zerti-shop-orders-grid.js', $plugin),
        ['zerti-ag-grid', 'zerti-localize-digits'],
        zerti_asset_version('assets/js/zerti-shop-orders-grid.js'),
        true
    );
    wp_register_script(
        'zerti-customers-grid',
        plugins_url('assets/js/zerti-customers-grid.js', $plugin),
        ['zerti-ag-grid', 'zerti-localize-digits'],
        zerti_asset_version('assets/js/zerti-customers-grid.js'),
        true
    );
    wp_register_script(
        'zerti-payments-grid',
        plugins_url('assets/js/zerti-payments-grid.js', $plugin),
        ['zerti-ag-grid', 'zerti-localize-digits'],
        zerti_asset_version('assets/js/zerti-payments-grid.js'),
        true
    );
    wp_register_script(
        'zerti-coupons-grid',
        plugins_url('assets/js/zerti-coupons-grid.js', $plugin),
        ['zerti-ag-grid', 'zerti-localize-digits'],
        zerti_asset_version('assets/js/zerti-coupons-grid.js'),
        true
    );
    wp_register_script(
        'zerti-financial-coupons',
        plugins_url('assets/js/zerti-financial-coupons.js', $plugin),
        ['jquery', 'zerti-admin-components', 'zerti-coupons-grid', 'zerti-confirm-alert'],
        zerti_asset_version('assets/js/zerti-financial-coupons.js'),
        true
    );
    wp_register_script(
        'zerti-products-grid',
        plugins_url('assets/js/zerti-products-grid.js', $plugin),
        ['zerti-ag-grid', 'zerti-localize-digits'],
        zerti_asset_version('assets/js/zerti-products-grid.js'),
        true
    );
    wp_register_script(
        'zerti-sales-report-grid',
        plugins_url('assets/js/zerti-sales-report-grid.js', $plugin),
        ['zerti-ag-grid', 'zerti-localize-digits'],
        zerti_asset_version('assets/js/zerti-sales-report-grid.js'),
        true
    );
    wp_register_script(
        'zerti-reviews-grid',
        plugins_url('assets/js/zerti-reviews-grid.js', $plugin),
        ['zerti-ag-grid', 'zerti-localize-digits', 'zerti-grid-i18n'],
        zerti_asset_version('assets/js/zerti-reviews-grid.js'),
        true
    );
    wp_register_script(
        'zerti-jalali-date',
        plugins_url('assets/js/zerti-jalali-date.js', $plugin),
        ['zerti-localize-digits'],
        zerti_asset_version('assets/js/zerti-jalali-date.js'),
        true
    );
    wp_register_script(
        'zerti-jalali-datepicker',
        plugins_url('assets/js/zerti-jalali-datepicker.js', $plugin),
        ['zerti-jalali-date'],
        zerti_asset_version('assets/js/zerti-jalali-datepicker.js'),
        true
    );
    wp_register_script(
        'zerti-gregorian-datepicker',
        plugins_url('assets/js/zerti-gregorian-datepicker.js', $plugin),
        [],
        zerti_asset_version('assets/js/zerti-gregorian-datepicker.js'),
        true
    );
    wp_register_script(
        'zerti-hijri-date',
        plugins_url('assets/js/zerti-hijri-date.js', $plugin),
        ['zerti-localize-digits'],
        zerti_asset_version('assets/js/zerti-hijri-date.js'),
        true
    );
    wp_register_script(
        'zerti-hijri-datepicker',
        plugins_url('assets/js/zerti-hijri-datepicker.js', $plugin),
        ['zerti-hijri-date'],
        zerti_asset_version('assets/js/zerti-hijri-datepicker.js'),
        true
    );
    wp_register_script(
        'zerti-admin-datepicker',
        plugins_url('assets/js/zerti-admin-datepicker.js', $plugin),
        [zerti_admin_datepicker_router_handle()],
        zerti_asset_version('assets/js/zerti-admin-datepicker.js'),
        true
    );
    wp_register_script(
        'zerti-server-clock',
        plugins_url('assets/js/zerti-server-clock.js', $plugin),
        zerti_admin_clock_script_deps(),
        zerti_asset_version('assets/js/zerti-server-clock.js'),
        true
    );
    wp_register_script(
        'zerti-admin-components',
        plugins_url('assets/js/zerti-admin-components.js', $plugin),
        ['zerti-bootstrap-bundle', 'zerti-localize-digits', 'zerti-admin-datepicker', 'zerti-server-clock'],
        zerti_asset_version('assets/js/zerti-admin-components.js'),
        true
    );
    wp_register_script(
        'zerti-global-search',
        plugins_url('assets/js/zerti-global-search.js', $plugin),
        ['zerti-admin-components'],
        zerti_asset_version('assets/js/zerti-global-search.js'),
        true
    );
    wp_register_script(
        'zerti-admin-notes',
        plugins_url('assets/js/zerti-admin-notes.js', $plugin),
        ['zerti-admin-components', 'zerti-confirm-alert'],
        zerti_asset_version('assets/js/zerti-admin-notes.js'),
        true
    );
    wp_register_script(
        'zerti-shop-order-detail-actions',
        plugins_url('assets/js/zerti-shop-order-detail-actions.js', $plugin),
        ['zerti-admin-components'],
        zerti_asset_version('assets/js/zerti-shop-order-detail-actions.js'),
        true
    );
    wp_register_script(
        'chart-js',
        plugins_url('assets/js/chart.umd.min.js', $plugin),
        [],
        '4.5.1',
        true
    );
    wp_register_script(
        'zerti-home-chart',
        plugins_url('assets/js/zerti-home-chart.js', $plugin),
        ['chart-js', 'zerti-admin-components'],
        zerti_asset_version('assets/js/zerti-home-chart.js'),
        true
    );
    wp_register_script(
        'zerti-grid-i18n',
        plugins_url('assets/js/zerti-grid-i18n.js', $plugin),
        [],
        zerti_asset_version('assets/js/zerti-grid-i18n.js'),
        true
    );
    wp_register_script(
        'zerti-confirm-alert',
        plugins_url('assets/js/zerti-confirm-alert.js', $plugin),
        [],
        zerti_asset_version('assets/js/zerti-confirm-alert.js'),
        true
    );
    wp_register_script(
        'zerti-inventory-categories',
        plugins_url('assets/js/zerti-inventory-categories.js', $plugin),
        ['zerti-admin-components', 'zerti-grid-i18n', 'zerti-confirm-alert'],
        zerti_asset_version('assets/js/zerti-inventory-categories.js'),
        true
    );
    wp_register_script(
        'zerti-inventory-tags',
        plugins_url('assets/js/zerti-inventory-tags.js', $plugin),
        ['zerti-admin-components', 'zerti-grid-i18n', 'zerti-confirm-alert'],
        zerti_asset_version('assets/js/zerti-inventory-tags.js'),
        true
    );
    wp_register_script(
        'zerti-inventory-brands',
        plugins_url('assets/js/zerti-inventory-brands.js', $plugin),
        ['zerti-admin-components', 'zerti-grid-i18n', 'zerti-confirm-alert'],
        zerti_asset_version('assets/js/zerti-inventory-brands.js'),
        true
    );
    wp_register_script(
        'zerti-inventory-reviews',
        plugins_url('assets/js/zerti-inventory-reviews.js', $plugin),
        ['zerti-admin-components', 'zerti-confirm-alert', 'zerti-reviews-grid'],
        zerti_asset_version('assets/js/zerti-inventory-reviews.js'),
        true
    );
    wp_register_script(
        'zerti-inventory-attributes',
        plugins_url('assets/js/zerti-inventory-attributes.js', $plugin),
        ['zerti-admin-components', 'zerti-grid-i18n', 'zerti-confirm-alert'],
        zerti_asset_version('assets/js/zerti-inventory-attributes.js'),
        true
    );
    wp_register_script(
        'zerti-inventory-attribute-groups',
        plugins_url('assets/js/zerti-inventory-attribute-groups.js', $plugin),
        ['zerti-admin-components', 'zerti-grid-i18n', 'zerti-confirm-alert', 'zerti-localize-digits'],
        zerti_asset_version('assets/js/zerti-inventory-attribute-groups.js'),
        true
    );
    wp_register_script(
        'quill',
        plugins_url('assets/quill/dist/quill.js', $plugin),
        [],
        zerti_asset_version('assets/quill/dist/quill.js'),
        true
    );
    wp_register_script(
        'zerti-product-rich-editor',
        plugins_url('assets/js/zerti-product-rich-editor.js', $plugin),
        ['quill'],
        zerti_asset_version('assets/js/zerti-product-rich-editor.js'),
        true
    );
    wp_register_script(
        'zerti-product-edit',
        plugins_url('assets/js/zerti-product-edit.js', $plugin),
        ['jquery', 'zerti-admin-components', 'zerti-product-rich-editor', 'zerti-grid-i18n', 'wc-enhanced-select'],
        zerti_asset_version('assets/js/zerti-product-edit.js'),
        true
    );
    wp_register_style(
        'quill-snow',
        plugins_url('assets/quill/dist/quill.snow.css', $plugin),
        [],
        zerti_asset_version('assets/quill/dist/quill.snow.css')
    );
    wp_register_style(
        'zerti-quill-theme',
        plugins_url('assets/css/zerti-quill-theme.css', $plugin),
        ['quill-snow', $admin_css_stack],
        zerti_asset_version('assets/css/zerti-quill-theme.css')
    );
    wp_register_script(
        'zerti-inventory-import-export',
        plugins_url('assets/js/zerti-inventory-import-export.js', $plugin),
        ['jquery', 'zerti-admin-components'],
        zerti_asset_version('assets/js/zerti-inventory-import-export.js'),
        true
    );

    wp_register_style(
        'zerti-product-attr-select2',
        plugins_url('assets/css/zerti-product-attr-select2.css', $plugin),
        [$admin_css_stack, 'zerti-wc-select2'],
        zerti_asset_version('assets/css/zerti-product-attr-select2.css')
    );
    wp_register_style(
        'zerti-wc-coupon-form',
        plugins_url('assets/css/zerti-wc-coupon-form.css', $plugin),
        [$admin_css_stack, 'zerti-wc-select2'],
        zerti_asset_version('assets/css/zerti-wc-coupon-form.css')
    );

    wp_register_script(
        'zerti-admin-theme-boot',
        plugins_url('assets/js/zerti-admin-theme-boot.js', $plugin),
        [],
        zerti_asset_version('assets/js/zerti-admin-theme-boot.js'),
        false
    );
    wp_register_script(
        'zerti-admin-theme',
        plugins_url('assets/js/zerti-admin-theme.js', $plugin),
        ['zerti-admin-components'],
        zerti_asset_version('assets/js/zerti-admin-theme.js'),
        true
    );

    wp_register_style(
        'zerti-print-shipping',
        plugins_url('assets/css/zerti-print-shipping.css', $plugin),
        [],
        zerti_asset_version('assets/css/zerti-print-shipping.css')
    );
    wp_register_style(
        'zerti-print-invoice',
        plugins_url('assets/css/zerti-print-invoice.css', $plugin),
        ['zerti-admin'],
        zerti_asset_version('assets/css/zerti-print-invoice.css')
    );
    wp_register_script(
        'zerti-print-auto',
        plugins_url('assets/js/zerti-print-auto.js', $plugin),
        [],
        zerti_asset_version('assets/js/zerti-print-auto.js'),
        true
    );

    do_action('zerti_admin_register_pro_assets');
}

/**
 * Enqueue assets for standalone shop order print windows (admin-ajax).
 */
function zerti_enqueue_shop_order_print_assets(string $doc): void
{
    zerti_admin_register_assets();

    if ($doc === 'shipping') {
        wp_enqueue_style('zerti-print-shipping');
        wp_enqueue_script('zerti-print-auto');

        return;
    }

    wp_enqueue_style('zerti-bootstrap-rtl');
    wp_enqueue_style('zerti-fontawesome');
    wp_enqueue_style('zerti-admin');
    wp_enqueue_style('zerti-print-invoice');
    wp_enqueue_script('zerti-print-auto');
}

/**
 * Enqueue WooCommerce CSV import/export assets on the backup sub-view (SSR).
 */
function zerti_maybe_enqueue_product_import_export_assets(string $hook_suffix): void
{
    if ($hook_suffix !== 'toplevel_page_' . ZERTI_ADMIN_PAGE_SLUG) {
        return;
    }
    $route = zerti_route_from_request();
    if (($route['tab'] ?? '') !== 'inventory' || ($route['inv'] ?? '') !== 'import-export') {
        return;
    }
    if (!function_exists('zerti_enqueue_product_import_export_assets')) {
        return;
    }
    zerti_enqueue_product_import_export_assets();
    $cfg = zerti_admin_inv_import_export_client_config();
    wp_localize_script('zerti-inventory-import-export', 'zertiInvImportExport', $cfg);
    wp_localize_script('zerti-admin-components', 'zertiInvImportExport', $cfg);
}

/**
 * @return list<string>
 */
function zerti_admin_all_non_core_bundle_ids(): array
{
    $ids = [];
    foreach (array_keys(zerti_admin_asset_bundles()) as $bundle_id) {
        if ($bundle_id !== 'core') {
            $ids[] = $bundle_id;
        }
    }

    return $ids;
}

/**
 * Non-core bundle IDs not loaded on the initial admin tab.
 *
 * @param list<string> $enqueued_bundle_ids
 * @return list<string>
 */
function zerti_admin_deferred_bundle_ids(array $enqueued_bundle_ids): array
{
    $deferred = [];
    foreach (zerti_admin_all_non_core_bundle_ids() as $bundle_id) {
        if (!in_array($bundle_id, $enqueued_bundle_ids, true)) {
            $deferred[] = $bundle_id;
        }
    }

    return $deferred;
}

/**
 * @param list<string> $bundle_ids
 * @return array<string, array{styles:list<array{handle:string,src:string}>,scripts:list<array{handle:string,src:string,deps:list<string>}>}>
 */
function zerti_admin_lazy_bundle_manifest_for_ids(array $bundle_ids): array
{
    $full = zerti_admin_lazy_bundle_manifest();
    $manifest = [];
    foreach ($bundle_ids as $bundle_id) {
        if (isset($full[$bundle_id])) {
            $manifest[$bundle_id] = $full[$bundle_id];
        }
    }

    return $manifest;
}

/**
 * Globals required when deferred admin bundles are loaded client-side.
 *
 * @return array<string, array<string, mixed>>
 */
function zerti_admin_deferred_bundle_script_config(): array
{
    $config = [];

    if (function_exists('zerti_admin_inv_import_export_client_config')) {
        $config['inventory-import-export'] = [
            'zertiInvImportExport' => zerti_admin_inv_import_export_client_config(),
            'zerti_product_export_params' => [
                'export_nonce' => wp_create_nonce('wc-product-export'),
            ],
        ];
    }

    if (function_exists('zerti_wc_coupon_enhanced_select_params')) {
        $config['financial-coupons'] = [
            'zerti_wc_enhanced_select_params' => zerti_wc_coupon_enhanced_select_params(),
            'zerti_woocommerce_admin_meta_boxes_coupon' => [
                'generate_button_text' => esc_html__('Generate coupon code', 'zerti'),
                'characters' => apply_filters('woocommerce_coupon_code_generator_characters', 'ABCDEFGHJKMNPQRSTUVWXYZ23456789'),
                'char_length' => apply_filters('woocommerce_coupon_code_generator_character_length', 8),
                'prefix' => apply_filters('woocommerce_coupon_code_generator_prefix', ''),
                'suffix' => apply_filters('woocommerce_coupon_code_generator_suffix', ''),
            ],
        ];
    }

    return $config;
}

/**
 * Client-side lazy-load manifest (registered handles not enqueued on first paint).
 *
 * @return array<string, array{styles:list<array{handle:string,src:string}>,scripts:list<array{handle:string,src:string,deps:list<string>}>}>
 */
function zerti_admin_lazy_bundle_manifest(): array
{
    $wp_scripts = wp_scripts();
    $wp_styles = wp_styles();
    $manifest = [];
    foreach (zerti_admin_asset_bundles() as $bundle_id => $bundle) {
        if ($bundle_id === 'core') {
            continue;
        }
        $entry = ['styles' => [], 'scripts' => []];
        foreach ($bundle['styles'] as $handle) {
            if (isset($wp_styles->registered[$handle])) {
                $reg = $wp_styles->registered[$handle];
                $entry['styles'][] = [
                    'handle' => $handle,
                    'src' => $reg->src,
                ];
            }
        }
        foreach ($bundle['scripts'] as $handle) {
            if (isset($wp_scripts->registered[$handle])) {
                $reg = $wp_scripts->registered[$handle];
                $entry['scripts'][] = [
                    'handle' => $handle,
                    'src' => $reg->src,
                    'deps' => array_values(array_filter((array) $reg->deps)),
                ];
            }
        }
        $manifest[$bundle_id] = $entry;
    }

    return $manifest;
}

/**
 * @param list<string> $bundle_ids
 */
function zerti_admin_enqueue_bundles(array $bundle_ids): void
{
    $defs = zerti_admin_asset_bundles();
    foreach ($bundle_ids as $bundle_id) {
        if (!isset($defs[$bundle_id])) {
            continue;
        }
        foreach ($defs[$bundle_id]['styles'] as $handle) {
            wp_enqueue_style($handle);
        }
        foreach ($defs[$bundle_id]['scripts'] as $handle) {
            wp_enqueue_script($handle);
        }
    }

    if (
        in_array('financial-coupons', $bundle_ids, true)
        && function_exists('zerti_localize_wc_coupon_form_scripts')
    ) {
        zerti_localize_wc_coupon_form_scripts();
    }

    if (
        in_array('inventory-import-export', $bundle_ids, true)
        && function_exists('zerti_admin_inv_import_export_client_config')
    ) {
        $import_export_cfg = zerti_admin_inv_import_export_client_config();
        wp_localize_script('zerti-inventory-import-export', 'zertiInvImportExport', $import_export_cfg);
        if (wp_script_is('zerti-admin-components', 'enqueued')) {
            wp_localize_script('zerti-admin-components', 'zertiInvImportExport', $import_export_cfg);
        }
        wp_localize_script(
            'wc-product-export',
            'zerti_product_export_params',
            [
                'export_nonce' => wp_create_nonce('wc-product-export'),
            ]
        );
    }
}

/**
 * Enqueue Bootstrap, Font Awesome, Vazirmatn, and ZERTI admin assets on the ZERTI screen only.
 */
function zerti_enqueue_admin_assets(string $hook_suffix): void
{
    if ($hook_suffix !== 'toplevel_page_' . ZERTI_ADMIN_PAGE_SLUG) {
        return;
    }

    zerti_ensure_fontawesome_webfonts();
    zerti_admin_register_assets();

    $theme_client_cfg = [
        'storageKey' => ZERTI_THEME_STORAGE_KEY,
    ];
    wp_enqueue_script('zerti-admin-theme-boot');
    wp_enqueue_script('zerti-admin-theme');
    wp_localize_script('zerti-admin-theme-boot', 'zertiAdminTheme', $theme_client_cfg);
    wp_localize_script('zerti-admin-theme', 'zertiAdminTheme', $theme_client_cfg);
    if (function_exists('zerti_enqueue_visual_theme_inline_styles')) {
        zerti_enqueue_visual_theme_inline_styles();
    }

    $initial_route = zerti_route_from_request();
    $initial_tab = $initial_route['tab'] ?? 'home';
    $initial_bundles = zerti_admin_bundles_for_tab($initial_tab);
    zerti_admin_enqueue_bundles($initial_bundles);
    $deferred_bundle_ids = zerti_admin_deferred_bundle_ids($initial_bundles);

    if (zerti_user_can_manage_product_categories() || zerti_user_can_view_products_grid()) {
        wp_enqueue_media();
    }

    wp_localize_script(
        'zerti-admin-components',
        'zertiShopOrdersGrid',
        apply_filters(
            'zerti_shop_orders_grid_client_config',
            array_merge(
                [
                'ajaxUrl' => admin_url('admin-ajax.php'),
                'nonce' => wp_create_nonce('zerti_shop_orders_grid'),
                'action' => 'zerti_shop_orders_grid',
                'pageSize' => 50,
                'paramSearch' => 'zerti_shop_search',
                'paramOrderCol' => 'zerti_shop_order_col',
                'paramOrderDir' => 'zerti_shop_order_dir',
                'paramShopStatus' => 'zerti_shop_status',
                'statusLabels' => function_exists('zerti_wc_order_status_choices') ? zerti_wc_order_status_choices() : [],
                'gatewayLabels' => function_exists('zerti_payments_grid_gateway_labels') ? zerti_payments_grid_gateway_labels() : [],
                'searchAriaLabel' => __('Search orders table', 'zerti'),
                'searchPlaceholder' => __('Search orders', 'zerti'),
                'i18n' => array_merge(
                    zerti_admin_grid_shared_i18n(),
                    [
                    'statusFilterProcessing' => __('Processing orders only', 'zerti'),
                    'statusFilterClear' => __('Show all orders', 'zerti'),
                    'alertOk' => __('OK', 'zerti'),
                    'colId' => __('ID', 'zerti'),
                    'colDate' => __('Date', 'zerti'),
                    'colCustomer' => __('Customer name', 'zerti'),
                    'colTotal' => __('Order total', 'zerti'),
                    'colGateway' => __('Payment gateway', 'zerti'),
                    'colStatus' => __('Order status', 'zerti'),
                    'colStatusShort' => __('Status', 'zerti'),
                    'colDownloadTitle' => __('Print', 'zerti'),
                    'noRowsToShow' => __('No custom items to display', 'zerti'),
                    ]
                ),
                ],
                zerti_rest_client_config('shop-orders')
            )
        )
    );
    wp_localize_script(
        'zerti-admin-components',
        'zertiCustomersGrid',
        apply_filters(
            'zerti_customers_grid_client_config',
            array_merge(
                [
                'ajaxUrl' => admin_url('admin-ajax.php'),
                'nonce' => wp_create_nonce('zerti_customers_grid'),
                'action' => 'zerti_customers_grid',
                'pageSize' => 50,
                'paramSearch' => 'zerti_customers_search',
                'paramOrderCol' => 'zerti_customers_order_col',
                'paramOrderDir' => 'zerti_customers_order_dir',
                'searchAriaLabel' => __('Search customers table', 'zerti'),
                'searchPlaceholder' => __('Search customers', 'zerti'),
                'i18n' => array_merge(
                    zerti_admin_grid_shared_i18n(),
                    [
                    'alertOk' => __('OK', 'zerti'),
                    'colId' => __('ID', 'zerti'),
                    'colName' => __('Name', 'zerti'),
                    'colEmail' => __('Email', 'zerti'),
                    'colPhone' => __('Phone', 'zerti'),
                    'colUsername' => __('Username', 'zerti'),
                    'colRegistered' => __('Registration date', 'zerti'),
                    'noRowsToShow' => __('No customers to display', 'zerti'),
                    ]
                ),
                ],
                zerti_rest_client_config('customers')
            )
        )
    );
    wp_localize_script(
        'zerti-admin-components',
        'zertiPaymentsGrid',
        apply_filters(
            'zerti_payments_grid_client_config',
            array_merge(
                [
                'ajaxUrl' => admin_url('admin-ajax.php'),
                'nonce' => wp_create_nonce('zerti_payments_grid'),
                'action' => 'zerti_payments_grid',
                'pageSize' => 50,
                'paramSearch' => 'zerti_payments_search',
                'paramOrderCol' => 'zerti_payments_order_col',
                'paramOrderDir' => 'zerti_payments_order_dir',
                'paramPaymentsScope' => 'zerti_payments_scope',
                'paymentsScopeSlugs' => function_exists('zerti_payments_scope_slugs') ? zerti_payments_scope_slugs() : ['today_success', 'period_success'],
                'searchAriaLabel' => __('Search payments table', 'zerti'),
                'searchPlaceholder' => __('Search payments', 'zerti'),
                'statusLabels' => function_exists('zerti_wc_order_status_choices') ? zerti_wc_order_status_choices() : [],
                'gatewayLabels' => function_exists('zerti_payments_grid_gateway_labels') ? zerti_payments_grid_gateway_labels() : [],
                'i18n' => array_merge(
                    zerti_admin_grid_shared_i18n(),
                    [
                    'scopeFilterTodaySuccess' => __('Successful payments today only', 'zerti'),
                    'scopeFilterPeriodSuccess' => __('Successful payments in current period only', 'zerti'),
                    'scopeFilterClear' => __('Show all payments', 'zerti'),
                    'alertOk' => __('OK', 'zerti'),
                    'colOrderId' => __('Order ID', 'zerti'),
                    'colDate' => __('Payment date', 'zerti'),
                    'colDateShort' => __('Date', 'zerti'),
                    'colCustomer' => __('Customer', 'zerti'),
                    'colAmount' => __('Amount', 'zerti'),
                    'colGateway' => __('Payment gateway', 'zerti'),
                    'colTransactionId' => __('Transaction ID', 'zerti'),
                    'colStatus' => __('Status', 'zerti'),
                    'noRowsToShow' => __('No payments to display', 'zerti'),
                    ]
                ),
                ],
                zerti_rest_client_config('payments')
            )
        )
    );
    wp_localize_script(
        'zerti-admin-components',
        'zertiCouponsGrid',
        [
            'ajaxUrl' => admin_url('admin-ajax.php'),
            'nonce' => wp_create_nonce('zerti_wc_coupons'),
            'action' => 'zerti_wc_coupons_grid',
            'pageSize' => 50,
            'paramSearch' => 'zerti_coupons_search',
            'couponTypeLabels' => array_values(zerti_wc_coupon_type_choices()),
            'searchAriaLabel' => __('Search coupons table', 'zerti'),
            'searchPlaceholder' => __('Search coupons', 'zerti'),
            'i18n' => array_merge(
                zerti_admin_grid_shared_i18n(),
                [
                    'colCode' => __('Code', 'zerti'),
                    'colType' => __('Coupon type', 'zerti'),
                    'colAmount' => __('Coupon amount', 'zerti'),
                    'colDescription' => __('Description', 'zerti'),
                    'colProducts' => __('Product IDs', 'zerti'),
                    'colUsage' => __('Usage / Limit', 'zerti'),
                    'colExpiry' => __('Expiry date', 'zerti'),
                    'noRowsToShow' => __('No coupons to display', 'zerti'),
                    'sectionGeneral' => __('General', 'zerti'),
                    'sectionUsageRestriction' => __('Usage restriction', 'zerti'),
                    'sectionUsageLimits' => __('Usage limits', 'zerti'),
                    'couponEditorTabs' => __('Coupon editor sections', 'zerti'),
                    'addCouponTitle' => __('Add coupon', 'zerti'),
                    'editCouponTitle' => __('Edit coupon', 'zerti'),
                    'loading' => __('Loading…', 'zerti'),
                    'loadFailed' => __('Failed to load coupon.', 'zerti'),
                    'saveSuccess' => __('Coupon saved.', 'zerti'),
                    'saveFailed' => __('Could not save coupon.', 'zerti'),
                    'saving' => __('Saving…', 'zerti'),
                    'deleteSuccess' => __('Coupon deleted.', 'zerti'),
                    /* translators: %s: coupon code */
                    'deleteConfirm' => __('Are you sure you want to delete coupon «%s»?', 'zerti'),
                    'deleteFailed' => __('Could not delete coupon.', 'zerti'),
                ]
            ),
        ]
    );
    if (function_exists('zerti_localize_wc_coupon_form_scripts')) {
        zerti_localize_wc_coupon_form_scripts();
    }
    wp_localize_script(
        'zerti-admin-components',
        'zertiSalesReportGrid',
        apply_filters(
            'zerti_sales_report_grid_client_config',
            [
            'ajaxUrl' => admin_url('admin-ajax.php'),
            'nonce' => wp_create_nonce('zerti_sales_report_grid'),
            'action' => 'zerti_sales_report_grid',
            'pageSize' => 50,
            'paramSearch' => 'zerti_sales_report_search',
            'paramOrderCol' => 'zerti_sales_report_order_col',
            'paramOrderDir' => 'zerti_sales_report_order_dir',
            'paramSalesScope' => 'zerti_sales_scope',
            'salesScopeSlugs' => function_exists('zerti_sales_report_scope_slugs') ? zerti_sales_report_scope_slugs() : ['period'],
            'searchAriaLabel' => __('Search sales report', 'zerti'),
            'searchPlaceholder' => __('Search sales report', 'zerti'),
            'i18n' => array_merge(
                zerti_admin_grid_shared_i18n(),
                [
                'scopeFilterPeriod' => __('Sold items only — current period', 'zerti'),
                'scopeFilterClear' => __('Show all sales', 'zerti'),
                'colRow' => __('Row', 'zerti'),
                'colProductId' => __('Product ID', 'zerti'),
                'colName' => __('Name', 'zerti'),
                'colSku' => __('Item ID (SKU)', 'zerti'),
                'colSaleDate' => __('Sale date', 'zerti'),
                'colDate' => __('Date', 'zerti'),
                'colSaleAmount' => __('Sales amount', 'zerti'),
                'colOrderId' => __('Order ID', 'zerti'),
                'noRowsToShow' => __('Nothing to display', 'zerti'),
                ]
            ),
            ]
        )
    );
    wp_localize_script(
        'zerti-admin-components',
        'zertiProductsGrid',
        apply_filters(
            'zerti_products_grid_client_config',
            array_merge(
                [
                'ajaxUrl' => admin_url('admin-ajax.php'),
                'nonce' => wp_create_nonce('zerti_products_grid'),
                'action' => 'zerti_products_grid',
                'pageSize' => 50,
                'paramSearch' => 'zerti_products_search',
                'paramOrderCol' => 'zerti_products_order_col',
                'paramOrderDir' => 'zerti_products_order_dir',
                'paramProductsStock' => 'zerti_products_stock',
                'searchAriaLabel' => __('Search products table', 'zerti'),
                'searchPlaceholder' => __('Search products', 'zerti'),
                'updateAction' => 'zerti_product_quick_update',
                'inventorySub' => 'warehouse',
                'i18n' => array_merge(
                    zerti_admin_grid_shared_i18n(),
                    [
                    'working' => __('Saving…', 'zerti'),
                    'salePriceNeedsRegularPrice' => __('To set a sale price, enter the regular product price first.', 'zerti'
                    ),
                'stockFilterZero' => __('Items with zero stock only', 'zerti'),
                'stockFilterOne' => __('Items with stock of one only', 'zerti'),
                'stockFilterAvailable' => __('In-stock items only', 'zerti'),
                'stockFilterClear' => __('Show all products', 'zerti'),
                'alertOk' => __('OK', 'zerti'),
                'colId' => __('ID', 'zerti'),
                'colImage' => __('Image', 'zerti'),
                'colName' => __('Name', 'zerti'),
                'colType' => __('Product type', 'zerti'),
                'colTypeShort' => __('Type', 'zerti'),
                'colStatus' => __('Product status', 'zerti'),
                'colStatusShort' => __('Status', 'zerti'),
                'colSku' => __('Product ID', 'zerti'),
                'colSkuShort' => __('Warehouse ID', 'zerti'),
                'colPrice' => __('Price', 'zerti'),
                'colSalePrice' => __('Sale price', 'zerti'),
                'colStock' => __('Stock', 'zerti'),
                'noRowsToShow' => __('No products to display', 'zerti'),
                ]
            ),
            ],
            zerti_rest_client_config('products')
            )
        )
    );
    wp_localize_script(
        'zerti-admin-components',
        'zertiShopOrder',
        [
            'ajaxUrl' => admin_url('admin-ajax.php'),
            'nonce' => wp_create_nonce('zerti_shop_order'),
            'action' => 'zerti_shop_order_action',
            'componentNonce' => wp_create_nonce('zerti_component'),
            'componentAction' => 'zerti_load_component',
            'invoiceAllowedStatuses' => function_exists('zerti_shop_order_invoice_allowed_statuses')
                ? zerti_shop_order_invoice_allowed_statuses()
                : ['completed', 'processing', 'pending'],
            'i18n' => [
                'statusUpdated' => __('Order status updated.', 'zerti'),
                'statusUnchanged' => __('Selected status is the same as current.', 'zerti'),
                'statusError' => __('Status change failed.', 'zerti'),
                'reloadError' => __('Status saved but failed to reload details.', 'zerti'),
                'invoiceUnavailable' => __('Invoice is only available for completed, processing, or pending payment orders.', 'zerti'),
                'feedbackDurationMs' => 2000,
                'printError' => __('Could not open print document.', 'zerti'),
                'emailSent' => __('Invoice email sent.', 'zerti'),
                'emailError' => __('Email could not be sent.', 'zerti'),
                'working' => __('In progress…', 'zerti'),
                'noteAdded' => __('Note added.', 'zerti'),
                'noteError' => __('Could not add note.', 'zerti'),
                'noteRequired' => __('Enter note text.', 'zerti'),
            ],
        ]
    );

    $currency_symbol = function_exists('get_woocommerce_currency_symbol')
        ? get_woocommerce_currency_symbol()
        : '';
    wp_localize_script(
        'zerti-home-chart',
        'zertiHomeChart',
        [
            'datasetLabel' => __('Total sales amount — last 30 days', 'zerti'),
            'decimals' => function_exists('wc_get_price_decimals') ? wc_get_price_decimals() : 0,
            'currencySymbol' => html_entity_decode((string) $currency_symbol, ENT_QUOTES, 'UTF-8'),
            'currencyCode' => function_exists('get_woocommerce_currency') ? get_woocommerce_currency() : '',
            'amountFirst' => zerti_wc_is_persian_currency() ? 1 : 0,
        ]
    );

    wp_localize_script(
        'zerti-admin-components',
        'zertiHomeLeaderboards',
        [
            'noData' => __('No data for this period.', 'zerti'),
            'topCategories' => __('Top categories - Items sold', 'zerti'),
            'topProducts' => __('Top products - Items sold', 'zerti'),
            'headers' => [
                'category' => __('Category', 'zerti'),
                'product' => __('Product', 'zerti'),
                'itemsSold' => __('Items sold', 'zerti'),
                'netSales' => __('Net sales', 'zerti'),
            ],
        ]
    );

    $inv_categories_cfg = zerti_admin_inv_categories_client_config();
    wp_localize_script('zerti-admin-components', 'zertiInvCategories', $inv_categories_cfg);
    wp_localize_script('zerti-inventory-categories', 'zertiInvCategories', $inv_categories_cfg);

    $inv_tags_cfg = zerti_admin_inv_tags_client_config();
    wp_localize_script('zerti-admin-components', 'zertiInvTags', $inv_tags_cfg);
    wp_localize_script('zerti-inventory-tags', 'zertiInvTags', $inv_tags_cfg);

    $inv_brands_cfg = zerti_admin_inv_brands_client_config();
    wp_localize_script('zerti-admin-components', 'zertiInvBrands', $inv_brands_cfg);
    wp_localize_script('zerti-inventory-brands', 'zertiInvBrands', $inv_brands_cfg);

    $inv_reviews_cfg = zerti_admin_product_feedback_client_config('review');
    wp_localize_script('zerti-admin-components', 'zertiInvReviews', $inv_reviews_cfg);
    wp_localize_script('zerti-inventory-reviews', 'zertiInvReviews', $inv_reviews_cfg);

    $inv_comments_cfg = zerti_admin_product_feedback_client_config('comment');
    wp_localize_script('zerti-admin-components', 'zertiInvComments', $inv_comments_cfg);
    wp_localize_script('zerti-inventory-reviews', 'zertiInvComments', $inv_comments_cfg);

    $inv_attributes_cfg = zerti_admin_inv_attributes_client_config();
    wp_localize_script('zerti-admin-components', 'zertiInvAttributes', $inv_attributes_cfg);
    wp_localize_script('zerti-inventory-attributes', 'zertiInvAttributes', $inv_attributes_cfg);

    $inv_attribute_groups_cfg = zerti_admin_inv_attribute_groups_client_config();
    wp_localize_script('zerti-admin-components', 'zertiInvAttributeGroups', $inv_attribute_groups_cfg);
    wp_localize_script('zerti-inventory-attribute-groups', 'zertiInvAttributeGroups', $inv_attribute_groups_cfg);

    wp_localize_script(
        'zerti-product-rich-editor',
        'zertiRichEditor',
        [
            'i18n' => [
                'mediaTitle' => __('Add media from library', 'zerti'),
                'mediaButton' => __('Insert into text', 'zerti'),
            ],
            'pickerLabels' => [
                'font' => [
                    '' => __('Sans', 'zerti'),
                    'serif' => __('Serif', 'zerti'),
                    'monospace' => __('Single space', 'zerti'),
                ],
                'size' => [
                    '' => __('Normal', 'zerti'),
                    'small' => __('Small', 'zerti'),
                    'large' => __('Large', 'zerti'),
                    'huge' => __('Extra large', 'zerti'),
                ],
                'header' => [
                    '' => __('Normal', 'zerti'),
                    '1' => __('Title 1', 'zerti'),
                    '2' => __('Title 2', 'zerti'),
                    '3' => __('Title 3', 'zerti'),
                    '4' => __('Title 4', 'zerti'),
                    '5' => __('Title 5', 'zerti'),
                    '6' => __('Title 6', 'zerti'),
                ],
            ],
        ]
    );

    $product_edit_cfg = zerti_admin_product_edit_client_config();
    wp_localize_script('zerti-admin-components', 'zertiProductEdit', $product_edit_cfg);
    wp_localize_script('zerti-product-edit', 'zertiProductEdit', $product_edit_cfg);

    wp_localize_script(
        'zerti-localize-digits',
        'zertiDigitLocale',
        function_exists('zerti_digit_locale_client_config') ? zerti_digit_locale_client_config() : ['script' => 'persian', 'locale' => 'fa_IR']
    );

    wp_localize_script(
        'zerti-admin-datepicker',
        'zertiCalendarI18n',
        function_exists('zerti_admin_datepicker_i18n') ? zerti_admin_datepicker_i18n() : []
    );

    wp_localize_script(
        'zerti-confirm-alert',
        'zertiConfirmAlertI18n',
        function_exists('zerti_admin_confirm_alert_i18n') ? zerti_admin_confirm_alert_i18n() : []
    );

    wp_localize_script(
        'zerti-server-clock',
        'zertiAdminClock',
        [
            'serverUnix' => time(),
            'timeZone' => zerti_get_timezone()->getName(),
            'calendar' => function_exists('zerti_get_calendar') ? zerti_get_calendar() : 'jalali',
        ]
    );

    wp_localize_script(
        'zerti-global-search',
        'zertiGlobalSearch',
        function_exists('zerti_global_search_client_config') ? zerti_global_search_client_config() : []
    );

    wp_localize_script(
        'zerti-admin-notes',
        'zertiAdminNotes',
        [
            'ajaxUrl' => admin_url('admin-ajax.php'),
            'nonce' => wp_create_nonce('zerti_admin_notes'),
            'listAction' => 'zerti_admin_notes_list',
            'saveAction' => 'zerti_admin_note_save',
            'deleteAction' => 'zerti_admin_note_delete',
            'notes' => function_exists('zerti_get_admin_notes_for_client') ? zerti_get_admin_notes_for_client() : [],
            'i18n' => [
                'save' => __('Save', 'zerti'),
                'cancel' => __('Cancel', 'zerti'),
                'edit' => __('Edit', 'zerti'),
                'delete' => __('Delete', 'zerti'),
                'confirmDelete' => __('Delete this note?', 'zerti'),
                'unknownUser' => __('Unknown user', 'zerti'),
                'error' => __('Request failed.', 'zerti'),
                /* translators: %s: number of notes */
                'toggleLabel' => __('Fast notes (%s)', 'zerti'),
            ],
        ]
    );

    wp_localize_script(
        'zerti-admin-components',
        'zertiComponents',
        apply_filters(
            'zerti_components_client_config',
            [
            'ajaxUrl' => admin_url('admin-ajax.php'),
            'nonce' => wp_create_nonce('zerti_component'),
            'action' => 'zerti_load_component',
            'settingsAction' => 'zerti_save_settings',
            'settingsNonce' => wp_create_nonce('zerti_save_settings'),
            'postalPdfSaveAction' => 'zerti_save_postal_pdf_settings',
            'postalPdfSaveNonce' => wp_create_nonce('zerti_save_postal_pdf_settings'),
            'initialTab' => $initial_route['tab'],
            'initialRoute' => $initial_route,
            'adminBaseUrl' => zerti_admin_base_url(),
            'allowedTabs' => zerti_admin_nav_slugs(),
            'routes' => zerti_routes_client_config(),
            'tabBundles' => zerti_admin_tab_bundle_map(),
            'initialBundles' => array_values(
                array_filter(
                    $initial_bundles,
                    static function (string $bundle_id): bool {
                        return $bundle_id !== 'core';
                    }
                )
            ),
            'lazyBundleManifest' => zerti_admin_lazy_bundle_manifest_for_ids($deferred_bundle_ids),
            'deferredScriptConfig' => zerti_admin_deferred_bundle_script_config(),
            'textDirection' => function_exists('zerti_get_text_direction') ? zerti_get_text_direction() : 'rtl',
            'calendar' => function_exists('zerti_get_calendar') ? zerti_get_calendar() : 'jalali',
            'adminLocale' => function_exists('zerti_get_admin_locale') ? zerti_get_admin_locale() : '',
            'directionManual' => !empty(zerti_get_plugin_settings()['general']['direction_manual']),
            'calendarManual' => !empty(zerti_get_plugin_settings()['general']['calendar_manual']),
            'digitsFormat' => function_exists('zerti_get_digits_format') ? zerti_get_digits_format() : 'auto',
            'digitsFormatManual' => !empty(zerti_get_plugin_settings()['general']['digits_format_manual']),
            'visualTheme' => function_exists('zerti_get_visual_theme') ? zerti_get_visual_theme() : 'zerti',
            'localeRegionalDefaults' => function_exists('zerti_locale_regional_defaults_client_config')
                ? zerti_locale_regional_defaults_client_config()
                : [],
            'processingOrdersAction' => 'zerti_shop_processing_orders_count',
            'pendingReviewsAction' => 'zerti_product_pending_reviews_count',
            'pendingCommentsAction' => 'zerti_product_pending_comments_count',
            'pendingFeedbackCountsAction' => 'zerti_product_pending_feedback_counts',
            'homeStatsAction' => 'zerti_home_dashboard_stats',
            'i18n' => [
                'loading' => __('Loading…', 'zerti'),
                'saving' => __('Saving settings…', 'zerti'),
                'retry' => __('Retry', 'zerti'),
                /* translators: %s: processing order count */
                'processingOrdersBadge' => __('Processing orders: %s', 'zerti'),
                /* translators: %s: pending review count */
                'pendingReviewsBadge' => __('Reviews pending review: %s', 'zerti'),
                /* translators: %s: pending comment count */
                'pendingCommentsBadge' => __('Comments pending review: %s', 'zerti'),
                /* translators: %s: combined pending reviews and comments count */
                'pendingCustomerRelationsBadge' => __('Pending reviews and comments: %s', 'zerti'),
                'bulkActionSafetyPhrase' => __('I understand', 'zerti'),
                'bulkActionSafetyMismatch' => __('Please type the exact phrase to continue.', 'zerti'),
            ],
        ]
        )
    );

    do_action('zerti_admin_localize_pro_assets', $initial_tab, $initial_route);
}

add_action('init', 'zerti_register_bundled_plugin_assets', 5);
