<?php

// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedNamespaceFound -- APD is the established namespace shared with the Pro add-on and retained for backward compatibility.
namespace APD\Admin;

use APD\PostTypes\ThemePostType;
use APD\Repositories\TemplateRepository;
use APD\Support\Assets;
use APD\Support\CommercialRuntimeConfig;
use APD\Support\DesignerAssets;
use APD\Support\RequestData;
use APD\Theme\DesignerTheme;

defined('ABSPATH') || exit;

class AdminAssets
{
    public function enqueue(string $hook) : void
    {
        // The top-level plugin icon is visible throughout wp-admin, including
        // screens that do not load the full Asuka Designer administration UI.
        wp_enqueue_style(
            'apd-admin-menu',
            ASUKA_PRODUCT_DESIGNER_ASSETS_URL . 'css/admin-menu.css',
            [],
            Assets::version('assets/css/admin-menu.css')
        );

        $context = $this->detectContext($hook);
        if (! $context['is_apd']) {
            return;
        }

        $screenId = $context['screen_id'];
        $postType = $context['post_type'];
        $isConfigScreen = $context['is_config'];
        $isProductScreen = $context['is_product'];
        $isStudioScreen = $context['is_studio'];
        $settings = (new AdminSettings())->all();
        $runtimeConfig = (new CommercialRuntimeConfig())->build($settings);

        wp_enqueue_style('apd-admin', ASUKA_PRODUCT_DESIGNER_ASSETS_URL . 'css/admin.css', [], Assets::version('assets/css/admin.css'));
        wp_enqueue_media();

        $adminDeps = [];
        $moduleScriptHandles = [];
        if ($isConfigScreen || $isStudioScreen || $isProductScreen) {
            $styleFile = DesignerAssets::styleFile();
            $coreFile = DesignerAssets::coreFile();
            wp_enqueue_style('apd-vendor', DesignerAssets::url($styleFile), [], DesignerAssets::version($styleFile));
            wp_enqueue_script('apd-vendor', DesignerAssets::url($coreFile), [], DesignerAssets::version($coreFile), true);
            wp_enqueue_script('apd-runtime-bridge', ASUKA_PRODUCT_DESIGNER_ASSETS_URL . 'js/runtime-bridge.js', ['apd-vendor'], Assets::version('assets/js/runtime-bridge.js'), true);
            $adminDeps[] = 'apd-runtime-bridge';
            $moduleScriptHandles = ['apd-vendor', 'apd-runtime-bridge'];

        }

        wp_enqueue_script('apd-admin', ASUKA_PRODUCT_DESIGNER_ASSETS_URL . 'js/admin-app.js', $adminDeps, Assets::version('assets/js/admin-app.js'), true);
        $moduleScriptHandles[] = 'apd-admin';
        foreach (array_unique($moduleScriptHandles) as $moduleHandle) {
            wp_script_add_data($moduleHandle, 'type', 'module');
        }

        wp_localize_script('apd-admin', 'APDAdminConfig', [
            'screenId' => $screenId,
            'postType' => $postType,
            'sampleConfigUrl' => ASUKA_PRODUCT_DESIGNER_URL . 'docs/SAMPLE_PRODUCT_CONFIG.json',
            'restUploadUrl' => esc_url_raw(add_query_arg('apd_source', 'admin', rest_url('asuka-designer/v1/upload'))),
            'restNonce' => \APD\Support\Nonces::runtime(),
            'jsI18n' => (new \APD\I18n\JsTranslationManager())->buildRuntimeConfig(determine_locale(), true),
            'integrations' => $this->buildPublicIntegrations($settings),
            'adminDesigner' => $this->buildAdminDesignerConfig($settings),
            'runtimeConfig' => $runtimeConfig,
            'fontCatalog' => [
                'endpoint' => admin_url('admin-ajax.php'),
                'action' => 'apd_google_fonts_catalog',
                'nonce' => wp_create_nonce('apd_google_fonts_catalog'),
                'hasApiKey' => trim((string) ($settings['google_fonts_api_key'] ?? '')) !== '',
                'settingsUrl' => admin_url('admin.php?page=apd-settings'),
            ],
            'labels' => [
                'copied' => __('Sample JSON copied to clipboard.', 'asuka-product-designer'),
                'copiedShort' => __('Copied', 'asuka-product-designer'),
                'copyFailed' => __('Unable to copy automatically. You can copy it manually from the document.', 'asuka-product-designer'),
                'copyFailedShort' => __('Copy failed', 'asuka-product-designer'),
                'mediaFrameTitleImage' => __('Choose an image', 'asuka-product-designer'),
                'mediaFrameTitleFile' => __('Choose a file', 'asuka-product-designer'),
                'mediaFrameButton' => __('Use this file', 'asuka-product-designer'),
                'mediaImportTitle' => __('Choose media items', 'asuka-product-designer'),
                'mediaImportButton' => __('Import selected media', 'asuka-product-designer'),
                'mediaImportEmpty' => __('Please select at least one media item.', 'asuka-product-designer'),
                'mediaImportNoneSelected' => __('No media selected yet.', 'asuka-product-designer'),
                'allCategories' => __('All categories', 'asuka-product-designer'),
                'emptyPreview' => __('No preview yet', 'asuka-product-designer'),
                'newItem' => __('New item', 'asuka-product-designer'),
                'updateSelectedEntrySavePage' => __('Update the selected entry, then save the page.', 'asuka-product-designer'),
                'itemN' => __('Item {n}', 'asuka-product-designer'),
                'advancedJsonMode' => __('Advanced JSON mode', 'asuka-product-designer'),
                'advancedJsonModeHelp' => __('You control the conditions array manually for this rule.', 'asuka-product-designer'),
                'pricingWatching' => __('Watching', 'asuka-product-designer'),
                'pricingAdds' => __('adds', 'asuka-product-designer'),
                'pricingEachStepOf' => __('each step of', 'asuka-product-designer'),
                'pricingAxisWidth' => __('width', 'asuka-product-designer'),
                'pricingAxisHeight' => __('height', 'asuka-product-designer'),
                'pricingAxisValue' => __('value', 'asuka-product-designer'),
                'untitledFont' => __('Untitled font', 'asuka-product-designer'),
                'untitledItem' => __('Untitled item', 'asuka-product-designer'),
                'fontFamilyNotSetYet' => __('Font family not set yet', 'asuka-product-designer'),
                'fontPreviewSample' => __('The quick brown fox jumps over the lazy dog', 'asuka-product-designer'),
                'fontCatalogLoading' => __('Loading the complete Google Fonts catalog…', 'asuka-product-designer'),
                'fontCatalogLoaded' => __('{count} Google Font families available.', 'asuka-product-designer'),
                'fontCatalogNoResults' => __('No font family matches this search.', 'asuka-product-designer'),
                'fontCatalogError' => __('The Google Fonts catalog could not be loaded.', 'asuka-product-designer'),
                'fontCatalogMissingKey' => __('Add a Google Fonts API key in Settings to browse the complete live catalog.', 'asuka-product-designer'),
                'fontAvailableHere' => __('Available on this device', 'asuka-product-designer'),
                'fontFallbackHere' => __('Uses the browser fallback on this device', 'asuka-product-designer'),
                'paletteColorCount' => __('{count} colors', 'asuka-product-designer'),
                'paletteOneColor' => __('1 color', 'asuka-product-designer'),
                'paletteAllColors' => __('All colors', 'asuka-product-designer'),
                'paletteNoColors' => __('No color palette', 'asuka-product-designer'),
                'previewMountLoading' => __('AsukaDesigner is loading in this admin preview…', 'asuka-product-designer'),
                'previewLoadingStatus' => __('Preview loading', 'asuka-product-designer'),
                'previewRefreshedStatus' => __('Preview refreshed', 'asuka-product-designer'),
                'previewErrorStatus' => __('Preview error', 'asuka-product-designer'),
                'previewMountError' => __('The preview could not be mounted with the current configuration. Check your JSON blocks and try again.', 'asuka-product-designer'),
                'runtimeDesignerMounted' => __('Designer mounted.', 'asuka-product-designer'),
                'runtimeDesignerMountFailed' => __('Designer mount failed.', 'asuka-product-designer'),
                'runtimeWaitingForDesigner' => __('Waiting for AsukaDesigner…', 'asuka-product-designer'),
                'runtimeDesignerUnavailable' => __('AsukaDesigner could not be loaded in this context yet.', 'asuka-product-designer'),
                'runtimeDesignPayloadSynchronized' => __('Design payload synchronized.', 'asuka-product-designer'),
                'templateActiveCount' => __('{count} active', 'asuka-product-designer'),
                'templatePortalMissing' => __('Add a selector before assigning modules to the shared portal.', 'asuka-product-designer'),
                'templatePortalFound' => __('Portal found on this page.', 'asuka-product-designer'),
                'templatePortalValid' => __('Valid selector. The portal will be resolved on the customer page.', 'asuka-product-designer'),
                'templatePortalInvalid' => __('This CSS selector is not valid.', 'asuka-product-designer'),
                'templatePortalNotConfigured' => __('not configured', 'asuka-product-designer'),
                'themePublished' => __('Published', 'asuka-product-designer'),
                'themeUnpublished' => __('Unpublished changes', 'asuka-product-designer'),
                'themeEditingDraft' => __('Editing draft', 'asuka-product-designer'),
                'themeComparingPublished' => __('Comparing published', 'asuka-product-designer'),
                'themeComparePublished' => __('Compare published theme', 'asuka-product-designer'),
                'themeReturnToDraft' => __('Return to draft preview', 'asuka-product-designer'),
                'themeCopied' => __('Theme JSON copied.', 'asuka-product-designer'),
                'themeImportError' => __('This file does not contain a valid AsukaDesigner theme.', 'asuka-product-designer'),
                'themeJsonApplied' => __('Theme JSON applied to the draft.', 'asuka-product-designer'),
                'themeColorInvalid' => __('Enter a valid CSS color.', 'asuka-product-designer'),
                /* translators: %d: Number of theme tokens that differ from the published theme. */
                'themeUnsavedOne' => __('%d token differs from the published theme.', 'asuka-product-designer'),
                /* translators: %d: Number of theme tokens that differ from the published theme. */
                'themeUnsavedMany' => __('%d tokens differ from the published theme.', 'asuka-product-designer'),
            ],
        ]);
    }

    private function buildAdminDesignerConfig(array $settings) : array
    {
        $templateId = absint($settings['admin_designer_template_id'] ?? 0);
        $templatePayload = (new TemplateRepository())->getMetaPayload($templateId);
        $builtinWorkspace = (new AdminDesignerWorkspace())->config();
        $themeService = new DesignerTheme();
        $themeId = sanitize_key((string) ($settings['admin_designer_theme_id'] ?? ''));
        if (! $themeService->hasTheme($themeId)) {
            $themeId = $themeService->defaultThemeId();
        }

        $template = $templatePayload !== [] ? [
                'configured' => true,
                'builtin' => false,
                'layout' => $this->decodeJsonArray($templatePayload['_apd_layout'] ?? ''),
                'moduleConfig' => $this->decodeJsonArray($templatePayload['_apd_modules'] ?? ''),
                'selectionMenu' => $this->decodeJsonArray($templatePayload['_apd_selection_menu'] ?? ''),
                'ui' => $this->decodeJsonArray($templatePayload['_apd_ui'] ?? ''),
            ] : $builtinWorkspace;

        return [
            'templateId' => $templatePayload !== [] ? (string) $templateId : AdminDesignerWorkspace::ID,
            'templateTitle' => $templatePayload !== []
                ? (string) ($templatePayload['title'] ?? '')
                : __('Built-in administration workspace', 'asuka-product-designer'),
            'template' => $template,
            'themeId' => $themeId,
            'theme' => $themeService->published($themeId),
        ];
    }

    private function decodeJsonArray(mixed $value) : array
    {
        if (is_array($value)) {
            return $value;
        }
        $decoded = json_decode((string) $value, true);
        return is_array($decoded) ? $decoded : [];
    }

    private function buildPublicIntegrations(array $settings) : array
    {
        $integrations = [
            'pixabay' => ['apiKey' => (string) ($settings['pixabay_api_key'] ?? '')],
            'pexels' => ['apiKey' => (string) ($settings['pexels_api_key'] ?? '')],
            'unsplash' => ['accessKey' => (string) ($settings['unsplash_access_key'] ?? '')],
            'facebook' => ['appId' => (string) ($settings['facebook_app_id'] ?? '')],
            'googleFonts' => ['apiKey' => (string) ($settings['google_fonts_api_key'] ?? '')],
        ];

        foreach ($integrations as $providerId => $providerConfig) {
            $providerConfig = array_filter(
                $providerConfig,
                static fn($value) => is_string($value) ? trim($value) !== '' : ! empty($value)
            );

            if ($providerConfig === []) {
                unset($integrations[$providerId]);
                continue;
            }

            $integrations[$providerId] = $providerConfig;
        }

        if ($integrations !== []) {
            $integrations['assetProviders'] = $integrations;
        }

        return $integrations;
    }

    public function adminBodyClass(string $classes) : string
    {
        $context = $this->detectContext();
        if (! $context['is_apd']) {
            return $classes;
        }

        $settings = (new AdminSettings())->all();
        $classes = trim($classes . ' apd-admin-screen apd-admin-theme-' . sanitize_html_class((string) ($settings['admin_theme'] ?? 'light')));

        if ($context['is_plugin']) {
            $classes .= ' apd-admin-screen--plugin';
        }
        if ($context['is_config']) {
            $classes .= ' apd-admin-screen--config';
        }
        if ($context['is_product']) {
            $classes .= ' apd-admin-screen--product';
        }
        if (! empty($context['is_order'])) {
            $classes .= ' apd-admin-screen--order';
        }
        if ($context['is_studio']) {
            $classes .= ' apd-admin-screen--studio';
        }
        if ($context['screen_id'] !== '') {
            $classes .= ' apd-screen-' . sanitize_html_class(str_replace([':', '/'], '-', $context['screen_id']));
        }
        if ($context['post_type'] !== '') {
            $classes .= ' apd-post-type-' . sanitize_html_class($context['post_type']);
        }

        return trim($classes);
    }

    protected function detectContext(string $hook = '') : array
    {
        $screen = function_exists('get_current_screen') ? get_current_screen() : null;
        $screenId = $screen ? (string) $screen->id : '';
        $postType = $screen ? (string) $screen->post_type : '';
        $isPluginScreen = str_contains($hook, 'apd-')
            || str_contains($screenId, 'apd-')
            || $postType === ThemePostType::TYPE;
        $isConfigScreen = $postType === 'apd_product_config' || $postType === 'apd_custom_product' || $postType === 'apd_template' || str_contains($screenId, 'apd_product_config') || str_contains($screenId, 'apd_custom_product') || str_contains($screenId, 'apd_template');
        $isProductScreen = $postType === 'product' || str_contains($screenId, 'product');
        $isOrderScreen = $postType === 'shop_order' || $screenId === 'woocommerce_page_wc-orders' || str_contains($screenId, 'shop_order') || str_contains($screenId, 'wc-orders');
        $query = RequestData::query();
        $isStudioScreen = isset($query['page']) && sanitize_key((string) $query['page']) === 'apd-designer-studio';

        return [
            'screen_id' => $screenId,
            'post_type' => $postType,
            'is_plugin' => $isPluginScreen,
            'is_config' => $isConfigScreen,
            'is_product' => $isProductScreen,
            'is_order' => $isOrderScreen,
            'is_studio' => $isStudioScreen,
            'is_apd' => $isPluginScreen || $isConfigScreen || $isProductScreen || $isOrderScreen || $isStudioScreen,
        ];
    }

}
