<?php

declare(strict_types=1);

namespace PrettyLinks\Pro\Admin;

use PrettyLinks\Admin\Assets as LiteAssets;
use PrettyLinks\Support\HasStaticContainer;
use PrettyLinks\Support\StaticContainerAwareness;

/**
 * Pretty Links Pro admin asset enqueue.
 *
 * Pro bundles live in `pro/assets/js/build/<name>.{js,asset.php}` and
 * `pro/assets/css/build/<name>.css`. They mount into placeholder divs that
 * the Lite page renders unconditionally, so the bundle can no-op cleanly
 * if the target element is missing (e.g. Pro deactivated mid-session).
 *
 * Each Pro bundle reads `window.prliAdmin` directly. For pages that ALSO
 * have a Lite bundle (e.g. Click History) the Lite enqueue layer already
 * localizes `prliAdmin`, so we skip it. For Pro-only pages (e.g. Split
 * Test Reports) there is no Lite bundle on the page — the
 * `PRO_ONLY_PAGES` set below picks those up so we localize `prliAdmin`
 * ourselves via `LiteAssets::bootstrapData()` (the public bootstrap
 * builder, identical shape).
 *
 * @var array<string, string>
 */
class Assets implements StaticContainerAwareness
{
    use HasStaticContainer;

    /**
     * Admin hook-suffix → Pro bundle handle(s) map. Mirrors the Lite map in
     * `PrettyLinks\Admin\Assets::BUNDLES` but only for pages that have a
     * Pro extension. Each bundle is enqueued IN ADDITION to the Lite
     * bundle for the same hook. Values may be a single handle string or
     * an array of handles for hooks that need multiple Pro bundles.
     *
     * @var array<string, string|list<string>>
     */
    private const BUNDLES = [
        'toplevel_page_pretty-link'                    => 'dashboard-pro',
        'pretty-links_page_pretty-link-clicks'         => 'clicks-pro-extras',
        // SplitTestReport registers with an EMPTY parent (it's hidden from
        // the menu, reached via the Links row action). WordPress generates
        // the hook as `admin_page_<slug>` rather than `<parent>_page_<slug>`
        // for empty-parent submenus.
        'admin_page_pretty-link-split-test'            => 'split-test-report',
        'pretty-links_page_pretty-link-custom-reports' => 'custom-reports',
        // Pro-only primary bundles — the page registers pro-side and has
        // no Lite counterpart. Lives at pro/assets/js/build/<name>.js.
        'pretty-links_page_pretty-link-categories'     => 'categories',
        'pretty-links_page_pretty-link-tags'           => 'tags',
        // Lite renders the Links list / Pay Links list via the same
        // `LinksApp` component. The Pro `links-pro-extras` bundle hydrates
        // the row-action slot (Split Test Report anchor) for
        // split-test-enabled rows on each of those pages.
        'pretty-links_page_pretty-link-links'          => 'links-pro-extras',
        'pretty-links_page_pretty-link-pay-links'      => 'links-pro-extras',
        // Lite renders the link add / edit form on the same Add New hook
        // (an `id` query param flips the form into edit mode). The Pro
        // `link-form-pro-extras` bundle mounts the split-test config panel
        // into the slot inside the form's Pro tab.
        'pretty-links_page_pretty-link-add-new'        => 'link-form-pro-extras',
        // Options page gets its Pro sections (Public / Pretty Bar /
        // Replacements / Auto-Create / QR / Health / Social) plus the
        // URL-formatting Pro field group from `options-pro-sections`, and
        // the Bookmarklet / Duplicate / MU-dispatch tool cards from
        // `tools-pro-extras` (the Tools section now lives under Options).
        'pretty-links_page_pretty-link-options'        => [
            'options-pro-sections',
            'tools-pro-extras',
        ],
    ];

    /**
     * Hook suffixes whose page is Pro-only (no Lite bundle on the same
     * hook). For these we must localize `prliAdmin` ourselves because
     * `PrettyLinks\Admin\Assets::enqueue()` short-circuits with no
     * bundle to attach the localization to.
     *
     * @var array<int, string>
     */
    private const PRO_ONLY_PAGES = [
        'admin_page_pretty-link-split-test',
        'pretty-links_page_pretty-link-custom-reports',
        'pretty-links_page_pretty-link-categories',
        'pretty-links_page_pretty-link-tags',
    ];

    /**
     * Enqueue the Pro bundle (if any) registered for the current admin
     * hook. Reuses the bootstrap data localized for the Lite bundle on
     * the same page — no Pro-specific global is added.
     *
     * @param string $hookSuffix The current admin page hook suffix.
     *
     * @return void
     */
    public static function enqueue(string $hookSuffix): void
    {
        if (!isset(self::BUNDLES[$hookSuffix])) {
            return;
        }
        $bundles  = (array) self::BUNDLES[$hookSuffix];
        $basePath = self::getContainer()->get('BASE_PATH');
        $baseUrl  = self::getContainer()->get('BASE_URL');

        foreach ($bundles as $bundle) {
            self::enqueueBundle((string) $bundle, $hookSuffix, $basePath, $baseUrl);
        }
    }

    /**
     * Register and enqueue a single Pro bundle and its dependencies.
     *
     * @param string $bundle     The bundle handle/slug to enqueue.
     * @param string $hookSuffix The current admin page hook suffix.
     * @param string $basePath   Absolute filesystem path to the plugin base.
     * @param string $baseUrl    Public URL to the plugin base.
     *
     * @return void
     */
    private static function enqueueBundle(string $bundle, string $hookSuffix, string $basePath, string $baseUrl): void
    {
        // Pro bundles consume `@shared` via the `prli-shared` external
        // exactly like Lite — register the shared library first so it
        // loads before the Pro bundle and `prliAdmin` lands on the right
        // <script> tag (see LiteAssets::enqueueSharedLibrary()).
        LiteAssets::enqueueSharedLibrary($basePath, $baseUrl);

        $jsRel    = "pro/assets/js/build/{$bundle}.js";
        $cssRel   = "pro/assets/css/build/{$bundle}.css";
        $assetRel = "pro/assets/js/build/{$bundle}.asset.php";
        $assetAbs = $basePath . $assetRel;

        $asset = is_file($assetAbs) ? require $assetAbs : null;
        $deps  = is_array($asset) && isset($asset['dependencies']) && is_array($asset['dependencies'])
            ? $asset['dependencies']
            : ['wp-element', 'wp-components', 'wp-i18n', 'wp-api-fetch', 'wp-data'];
        if (!in_array(LiteAssets::SHARED_HANDLE, $deps, true)) {
            $deps[] = LiteAssets::SHARED_HANDLE;
        }
        $version = is_array($asset) && isset($asset['version']) ? (string) $asset['version'] : \PrettyLinks\Bootstrap::version();

        $handle = 'prli-admin-pro-' . $bundle;

        if (is_file($basePath . $jsRel)) {
            wp_enqueue_script(
                $handle,
                $baseUrl . $jsRel,
                $deps,
                $version,
                true
            );
            wp_set_script_translations($handle, 'pretty-link-pro');
        }

        if (is_file($basePath . $cssRel)) {
            wp_enqueue_style(
                $handle,
                $baseUrl . $cssRel,
                ['wp-components', LiteAssets::SHARED_HANDLE],
                $version
            );
        }

        if (in_array($bundle, ['clicks-pro-extras', 'link-form-pro-extras'], true)) {
            LiteAssets::enqueueFlagIcons($basePath, $baseUrl);
        }

        // Pro-only page: no Lite bundle ran on this hook, so `prliAdmin`
        // hasn't been localized onto the shared handle yet. Attach the
        // standard bootstrap shape so the shared-bundle's bootstrap.js
        // reader sees the data when it evaluates.
        if (in_array($hookSuffix, self::PRO_ONLY_PAGES, true) && is_file($basePath . $jsRel)) {
            wp_localize_script(
                LiteAssets::SHARED_HANDLE,
                'prliAdmin',
                LiteAssets::bootstrapData($bundle)
            );
        }
    }
}
