<?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\Support\AssetCatalog;
use APD\Support\RequestData;

defined('ABSPATH') || exit;

class FontsPage
{
    use CatalogPageTrait;

    private function defaults() : array
    {
        return [
            'id' => '',
            'label' => '',
            'family' => '',
            'category' => '',
            'source' => 'google',
            'cssUrl' => '',
            'fileUrl' => '',
            'weights' => '400',
            'enabled' => true,
        ];
    }

    public function render() : void
    {
        $catalog = (new AssetCatalog())->all();
        $items = (array) ($catalog['fonts'] ?? []);
        $pageSlug = 'apd-fonts';

        $this->pageShellStart(
            __('Typography', 'asuka-product-designer'),
            __('Font library', 'asuka-product-designer'),
            __('Create a clean, reusable font catalog for the designer. Add and edit actions now open on their own dedicated pages.', 'asuka-product-designer')
        );
        $this->renderCatalogNotice();

        echo '<section class="apd-card apd-fonts-shell">';
        echo '<div class="apd-card-head apd-card-head-stack">';
        echo '<div>';
        echo '<h2>' . esc_html__('Reusable fonts', 'asuka-product-designer') . '</h2>';
        echo '<p>' . esc_html__('Browse the list here, then open a dedicated page to add or edit one font at a time.', 'asuka-product-designer') . '</p>';
        echo '</div>';
        echo '<div class="apd-inline-actions apd-inline-actions-wrap">';
        echo '<a class="button button-primary" href="' . esc_url($this->getCatalogEditorUrl('apd-fonts-editor', 'fonts', 'new')) . '">' . esc_html__('Add font', 'asuka-product-designer') . '</a>';
        echo '<button type="button" class="button button-secondary" data-apd-import-toggle="fonts">' . esc_html__('Bulk import', 'asuka-product-designer') . '</button>';
        echo '<form method="post" action="' . esc_url(admin_url('admin-post.php')) . '" class="apd-inline-form">';
        wp_nonce_field('apd_export_catalog_items');
        echo '<input type="hidden" name="action" value="apd_export_catalog_items">';
        echo '<input type="hidden" name="apd_collection" value="fonts">';
        echo '<button type="submit" class="button button-secondary">' . esc_html__('Export JSON', 'asuka-product-designer') . '</button>';
        echo '</form>';
        echo '</div>';
        echo '</div>';

        $this->renderCrudToolbar('fonts', $items);
        $this->renderBulkImportPanel($pageSlug, 'fonts');
        $this->renderFontList($pageSlug, $items, 'apd-fonts-editor');
        echo '</section>';

        $this->pageShellEnd();
    }

    public function renderEditor() : void
    {
        $catalog = (new AssetCatalog())->all();
        $items = (array) ($catalog['fonts'] ?? []);
        $defaults = $this->defaults();
        $query = RequestData::query();
        $currentAction = sanitize_key((string) ($query['apd_action'] ?? 'new'));
        if (! in_array($currentAction, ['new', 'edit'], true)) {
            $currentAction = 'new';
        }
        $currentIndex = isset($query['apd_index']) ? max(0, (int) $query['apd_index']) : null;
        $editorItem = $defaults;
        $editorTitle = $currentAction === 'edit' ? __('Edit font', 'asuka-product-designer') : __('Add font', 'asuka-product-designer');
        if ($currentAction === 'edit' && $currentIndex !== null && isset($items[$currentIndex])) {
            $editorItem = wp_parse_args((array) $items[$currentIndex], $defaults);
        } elseif ($currentAction === 'edit') {
            $currentAction = 'new';
            $currentIndex = null;
            $editorTitle = __('Add font', 'asuka-product-designer');
        }

        $this->pageShellStart(
            __('Typography', 'asuka-product-designer'),
            __('Font editor', 'asuka-product-designer'),
            __('Create or update one font at a time in a dedicated page, then return to the library list.', 'asuka-product-designer')
        );
        $this->renderCatalogNotice();

        echo '<section class="apd-card apd-fonts-shell">';
        echo '<div class="apd-card-head apd-card-head-stack">';
        echo '<div>';
        echo '<h2>' . esc_html__('Reusable fonts', 'asuka-product-designer') . '</h2>';
        echo '<p>' . esc_html__('Use this focused editor page for a single font entry.', 'asuka-product-designer') . '</p>';
        echo '</div>';
        echo '<div class="apd-inline-actions apd-inline-actions-wrap">';
        echo '<a class="button button-secondary" href="' . esc_url($this->getCatalogPageUrl('apd-fonts', ['apd_collection' => 'fonts'])) . '">' . esc_html__('Back to list', 'asuka-product-designer') . '</a>';
        echo '</div>';
        echo '</div>';

        $this->renderAdaptiveFontEditor('apd-fonts', $editorTitle, $editorItem, $currentAction === 'edit' ? $currentIndex : null);
        echo '</section>';

        $this->pageShellEnd();
    }

    private function renderAdaptiveFontEditor(string $pageSlug, string $title, array $item, ?int $index = null) : void
    {
        $previewText = __('The quick brown fox jumps over the lazy dog', 'asuka-product-designer');
        $label = (string) ($item['label'] ?? '');
        $family = (string) ($item['family'] ?? '');
        $source = sanitize_key((string) ($item['source'] ?? 'google')) ?: 'google';
        $cssUrl = (string) ($item['cssUrl'] ?? '');
        $fileUrl = (string) ($item['fileUrl'] ?? '');
        $weights = is_array($item['weights'] ?? null) ? implode(', ', array_map('strval', (array) $item['weights'])) : (string) ($item['weights'] ?? '400');
        $styles = is_array($item['styles'] ?? null) ? implode(', ', array_map('strval', (array) $item['styles'])) : (string) ($item['styles'] ?? 'normal');
        $format = sanitize_key((string) ($item['format'] ?? ''));
        $weight = (string) ($item['weight'] ?? '400');
        $style = sanitize_key((string) ($item['style'] ?? 'normal'));
        $customDelivery = $fileUrl !== '' || $cssUrl === '' ? 'file' : 'stylesheet';
        $settings = (new AdminSettings())->all();
        $hasGoogleApiKey = trim((string) ($settings['google_fonts_api_key'] ?? '')) !== '';

        echo '<div class="apd-crud-editor apd-font-editor apd-catalog-editor-v2" data-apd-font-editor data-apd-font-source="' . esc_attr($source) . '">';
        echo '<div class="apd-crud-editor__head">';
        echo '<div><span class="apd-editor-eyebrow">' . esc_html__('Typography source', 'asuka-product-designer') . '</span><h3>' . esc_html($title) . '</h3><p>' . esc_html__('Choose a source and the editor will expose only the settings supported by that font type.', 'asuka-product-designer') . '</p></div>';
        echo '<a class="button button-secondary" href="' . esc_url($this->getCatalogPageUrl($pageSlug)) . '">' . esc_html__('Close editor', 'asuka-product-designer') . '</a>';
        echo '</div>';

        echo '<form method="post" action="' . esc_url(admin_url('admin-post.php')) . '" class="apd-font-editor__form">';
        wp_nonce_field('apd_save_catalog_item');
        echo '<input type="hidden" name="action" value="apd_save_catalog_item">';
        echo '<input type="hidden" name="apd_page" value="' . esc_attr($pageSlug) . '">';
        echo '<input type="hidden" name="apd_collection" value="fonts">';
        if ($index !== null) {
            echo '<input type="hidden" name="apd_index" value="' . esc_attr((string) $index) . '">';
        }
        echo '<input type="hidden" name="item[source]" value="' . esc_attr($source) . '" data-apd-font-source-input>';
        echo '<input type="hidden" name="item[family]" value="' . esc_attr($family) . '" data-apd-font-sync="family">';
        echo '<input type="hidden" name="item[weights]" value="' . esc_attr($weights) . '" data-apd-font-sync="weights">';
        echo '<input type="hidden" name="item[styles]" value="' . esc_attr($styles) . '" data-apd-font-sync="styles">';

        echo '<div class="apd-font-editor__layout">';
        echo '<aside class="apd-font-editor__preview-panel">';
        echo '<div class="apd-editor-section-heading"><span class="apd-chip apd-chip-soft">' . esc_html__('Live preview', 'asuka-product-designer') . '</span><span data-apd-font-preview-source>' . esc_html($this->labelForSource($source)) . '</span></div>';
        echo '<div class="apd-font-preview-card" data-apd-font-preview-card>';
        echo '<div class="apd-font-preview-card__label">' . esc_html($label !== '' ? $label : __('Untitled font', 'asuka-product-designer')) . '</div>';
        echo '<div class="apd-font-preview-card__meta" data-apd-font-preview-meta>' . esc_html($family !== '' ? $family : __('Font family not set yet', 'asuka-product-designer')) . '</div>';
        echo '<div class="apd-font-preview-card__sample" data-apd-font-preview-sample style="font-family:' . esc_attr($family !== '' ? $family : 'inherit') . '">' . esc_html($previewText) . '</div>';
        echo '</div>';
        echo '<label class="apd-field apd-field-full"><span>' . esc_html__('Preview text', 'asuka-product-designer') . '</span><input type="text" value="' . esc_attr($previewText) . '" data-apd-font-preview-input><small>' . esc_html__('This sample is only used in the editor.', 'asuka-product-designer') . '</small></label>';
        echo '<div class="apd-editor-note"><strong>' . esc_html__('Runtime ready', 'asuka-product-designer') . '</strong><p>' . esc_html__('The saved entry uses the same font contract in Fabric and Babylon views.', 'asuka-product-designer') . '</p></div>';
        echo '</aside>';

        echo '<div class="apd-font-editor__fields">';
        echo '<div class="apd-font-source-picker">';
        $this->renderFontSourceOption('google', __('Google Fonts', 'asuka-product-designer'), __('Search the complete live catalog.', 'asuka-product-designer'));
        $this->renderFontSourceOption('system', __('System font', 'asuka-product-designer'), __('Use a cross-platform font stack.', 'asuka-product-designer'));
        $this->renderFontSourceOption('custom', __('Own font', 'asuka-product-designer'), __('Upload a file or provide CSS.', 'asuka-product-designer'));
        echo '</div>';

        echo '<section class="apd-source-workspace" data-apd-font-source-only="google">';
        echo '<div class="apd-source-workspace__head"><div><span class="apd-editor-eyebrow">' . esc_html__('Google Fonts catalog', 'asuka-product-designer') . '</span><h4>' . esc_html__('Find a family', 'asuka-product-designer') . '</h4><p>' . esc_html__('Search the official catalog, then choose exactly which weights and styles the designer may load.', 'asuka-product-designer') . '</p></div><span class="apd-live-indicator' . ($hasGoogleApiKey ? ' is-ready' : '') . '">' . esc_html($hasGoogleApiKey ? __('API connected', 'asuka-product-designer') : __('API key required', 'asuka-product-designer')) . '</span></div>';
        echo '<div class="apd-font-combobox" data-apd-google-font-combobox>';
        echo '<label class="apd-field"><span>' . esc_html__('Google Font family', 'asuka-product-designer') . '</span><input type="search" value="' . esc_attr($family) . '" autocomplete="off" role="combobox" aria-autocomplete="list" aria-expanded="false" aria-controls="apd-google-font-results" placeholder="' . esc_attr__('Search Montserrat, Inter, Roboto...', 'asuka-product-designer') . '" data-apd-google-font-search><small>' . esc_html__('The full list is fetched dynamically and cached by WordPress.', 'asuka-product-designer') . '</small></label>';
        echo '<div id="apd-google-font-results" class="apd-font-results" role="listbox" data-apd-google-font-results hidden></div>';
        echo '</div>';
        echo '<div class="apd-font-catalog-status" data-apd-google-font-status>';
        if ($hasGoogleApiKey) {
            echo esc_html__('The catalog will load when this source is selected.', 'asuka-product-designer');
        } else {
            echo esc_html__('Add a Google Fonts API key to browse the complete catalog.', 'asuka-product-designer') . ' <a href="' . esc_url(admin_url('admin.php?page=apd-settings')) . '">' . esc_html__('Open settings', 'asuka-product-designer') . '</a>';
        }
        echo '</div>';
        echo '<div class="apd-font-selection-summary" data-apd-google-font-selection' . ($family === '' ? ' hidden' : '') . '><div><strong data-apd-google-selected-family>' . esc_html($family) . '</strong><span data-apd-google-selected-category>' . esc_html((string) ($item['category'] ?? '')) . '</span></div><span class="apd-chip apd-chip-success">' . esc_html__('Selected', 'asuka-product-designer') . '</span></div>';
        echo '<div class="apd-option-builder"><div><strong>' . esc_html__('Weights', 'asuka-product-designer') . '</strong><p>' . esc_html__('Load only the weights your products use.', 'asuka-product-designer') . '</p></div><div class="apd-choice-grid" data-apd-google-font-weights></div></div>';
        echo '<div class="apd-option-builder"><div><strong>' . esc_html__('Styles', 'asuka-product-designer') . '</strong><p>' . esc_html__('Normal and italic are shown when supported.', 'asuka-product-designer') . '</p></div><div class="apd-choice-grid" data-apd-google-font-styles></div></div>';
        echo '</section>';

        echo '<section class="apd-source-workspace" data-apd-font-source-only="system">';
        echo '<div class="apd-source-workspace__head"><div><span class="apd-editor-eyebrow">' . esc_html__('Cross-platform presets', 'asuka-product-designer') . '</span><h4>' . esc_html__('Choose a system family', 'asuka-product-designer') . '</h4><p>' . esc_html__('These presets use reliable browser and operating-system fallbacks without a download.', 'asuka-product-designer') . '</p></div></div>';
        echo '<label class="apd-field"><span>' . esc_html__('Filter presets', 'asuka-product-designer') . '</span><input type="search" placeholder="' . esc_attr__('Search sans serif, serif, monospace...', 'asuka-product-designer') . '" data-apd-system-font-search></label>';
        echo '<div class="apd-system-font-grid" data-apd-system-font-list>';
        foreach ($this->systemFontPresets() as $preset) {
            $active = $source === 'system' && $family === $preset['family'];
            echo '<button type="button" class="apd-system-font-option' . ($active ? ' is-active' : '') . '" data-apd-system-font-option data-family="' . esc_attr($preset['family']) . '" data-stack="' . esc_attr($preset['stack']) . '" data-category="' . esc_attr($preset['category']) . '" data-search="' . esc_attr(strtolower($preset['family'] . ' ' . $preset['category'])) . '">';
            echo '<span class="apd-system-font-option__sample" style="font-family:' . esc_attr($preset['stack']) . '">Aa</span><span><strong>' . esc_html($preset['family']) . '</strong><small>' . esc_html($preset['category']) . '</small><em data-apd-system-font-availability></em></span></button>';
        }
        echo '</div>';
        echo '</section>';

        echo '<section class="apd-source-workspace" data-apd-font-source-only="custom">';
        echo '<div class="apd-source-workspace__head"><div><span class="apd-editor-eyebrow">' . esc_html__('Self-hosted typography', 'asuka-product-designer') . '</span><h4>' . esc_html__('Connect your own font', 'asuka-product-designer') . '</h4><p>' . esc_html__('Use a direct WOFF2, WOFF, TTF or OTF file, or a stylesheet that declares the family.', 'asuka-product-designer') . '</p></div></div>';
        echo '<label class="apd-field"><span>' . esc_html__('CSS font-family name', 'asuka-product-designer') . '</span><input type="text" value="' . esc_attr($family) . '" placeholder="' . esc_attr__('My Brand Sans', 'asuka-product-designer') . '" data-apd-custom-font-family><small>' . esc_html__('It must match the family declared by the file or stylesheet.', 'asuka-product-designer') . '</small></label>';
        echo '<div class="apd-segmented-control" data-apd-custom-delivery="' . esc_attr($customDelivery) . '"><button type="button" data-apd-custom-delivery-option="file">' . esc_html__('Direct font file', 'asuka-product-designer') . '</button><button type="button" data-apd-custom-delivery-option="stylesheet">' . esc_html__('CSS stylesheet', 'asuka-product-designer') . '</button></div>';
        echo '<div class="apd-custom-font-panel" data-apd-custom-delivery-only="file">';
        echo '<label class="apd-field apd-field-full"><span>' . esc_html__('Font file', 'asuka-product-designer') . '</span><div class="apd-media-field"><input type="text" name="item[fileUrl]" value="' . esc_attr($fileUrl) . '" placeholder="https://example.com/fonts/brand.woff2" data-apd-field="fileUrl" data-apd-font-sync="fileUrl"><div class="apd-inline-actions apd-media-picker-row"><button type="button" class="button button-secondary js-apd-media-pick" data-apd-media-open data-apd-media-type="file">' . esc_html__('Select or upload', 'asuka-product-designer') . '</button><button type="button" class="button button-link js-apd-media-clear" data-apd-media-clear>' . esc_html__('Clear', 'asuka-product-designer') . '</button></div></div><small>' . esc_html__('WOFF2 is recommended for modern browsers.', 'asuka-product-designer') . '</small></label>';
        echo '<div class="apd-form-grid apd-form-grid-3">';
        echo '<label class="apd-field"><span>' . esc_html__('File format', 'asuka-product-designer') . '</span><select name="item[format]">';
        foreach (['' => __('Auto detect', 'asuka-product-designer'), 'woff2' => 'WOFF2', 'woff' => 'WOFF', 'ttf' => 'TTF', 'otf' => 'OTF'] as $value => $caption) {
            echo '<option value="' . esc_attr($value) . '" ' . selected($format, $value, false) . '>' . esc_html($caption) . '</option>';
        }
        echo '</select></label><label class="apd-field"><span>' . esc_html__('Font weight', 'asuka-product-designer') . '</span><select name="item[weight]">';
        foreach (['100', '200', '300', '400', '500', '600', '700', '800', '900'] as $fontWeight) {
            echo '<option value="' . esc_attr($fontWeight) . '" ' . selected($weight, $fontWeight, false) . '>' . esc_html($fontWeight) . '</option>';
        }
        echo '</select></label><label class="apd-field"><span>' . esc_html__('Font style', 'asuka-product-designer') . '</span><select name="item[style]"><option value="normal" ' . selected($style, 'normal', false) . '>' . esc_html__('Normal', 'asuka-product-designer') . '</option><option value="italic" ' . selected($style, 'italic', false) . '>' . esc_html__('Italic', 'asuka-product-designer') . '</option></select></label></div>';
        echo '</div>';
        echo '</section>';

        echo '<section class="apd-source-workspace apd-source-workspace--details">';
        echo '<div class="apd-source-workspace__head"><div><span class="apd-editor-eyebrow">' . esc_html__('Catalog details', 'asuka-product-designer') . '</span><h4>' . esc_html__('Name and organize this font', 'asuka-product-designer') . '</h4></div></div>';
        echo '<div class="apd-form-grid apd-form-grid-2 apd-font-form-grid">';
        $this->renderCrudField('label', ['label' => __('Public label', 'asuka-product-designer'), 'placeholder' => 'Montserrat', 'help' => __('Name shown to administrators and inside the designer.', 'asuka-product-designer'), 'attributes' => ['data-apd-font-sync' => 'label']], $label);
        $this->renderCrudField('id', ['label' => __('ID', 'asuka-product-designer'), 'placeholder' => 'montserrat', 'help' => __('Generated from the label until you edit it.', 'asuka-product-designer'), 'attributes' => ['data-apd-font-sync' => 'id']], (string) ($item['id'] ?? ''));
        $this->renderCrudField('category', ['label' => __('Category', 'asuka-product-designer'), 'placeholder' => __('Sans serif', 'asuka-product-designer'), 'help' => __('Optional grouping label for catalog filters.', 'asuka-product-designer'), 'attributes' => ['data-apd-font-sync' => 'category']], (string) ($item['category'] ?? ''));
        $this->renderCrudField('enabled', ['label' => __('Visibility', 'asuka-product-designer'), 'type' => 'checkbox', 'checkbox_label' => __('Expose this font in the designer', 'asuka-product-designer'), 'full' => true], ! empty($item['enabled']));
        echo '</div>';
        echo '<details class="apd-advanced-details" data-apd-font-source-only="google custom"><summary>' . esc_html__('Advanced stylesheet URL', 'asuka-product-designer') . '</summary><div class="apd-advanced-details__body"><label class="apd-field apd-field-full"><span>' . esc_html__('CSS URL', 'asuka-product-designer') . '</span><input type="text" name="item[cssUrl]" value="' . esc_attr($cssUrl) . '" placeholder="https://fonts.googleapis.com/css2?family=Montserrat&display=swap" data-apd-font-sync="cssUrl"><small>' . esc_html__('Generated automatically for Google Fonts. For an own font, use it when the stylesheet already contains @font-face.', 'asuka-product-designer') . '</small></label></div></details>';
        echo '</section>';

        echo '<div class="apd-inline-actions apd-editor-actions">';
        submit_button(__('Save font', 'asuka-product-designer'), 'primary', 'submit', false);
        echo '<a class="button button-secondary" href="' . esc_url($this->getCatalogPageUrl($pageSlug)) . '">' . esc_html__('Cancel', 'asuka-product-designer') . '</a></div>';
        echo '</div></div></form></div>';
    }

    private function renderFontSourceOption(string $source, string $label, string $description) : void
    {
        echo '<button type="button" class="apd-font-source-option" data-apd-font-source-option="' . esc_attr($source) . '"><span class="apd-font-source-option__icon" aria-hidden="true">' . esc_html(strtoupper(substr($label, 0, 1))) . '</span><span><strong>' . esc_html($label) . '</strong><small>' . esc_html($description) . '</small></span></button>';
    }

    private function systemFontPresets() : array
    {
        return [
            ['family' => 'system-ui', 'stack' => 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif', 'category' => __('System UI', 'asuka-product-designer')],
            ['family' => 'Arial', 'stack' => 'Arial, Helvetica, sans-serif', 'category' => __('Sans serif', 'asuka-product-designer')],
            ['family' => 'Helvetica', 'stack' => 'Helvetica, Arial, sans-serif', 'category' => __('Sans serif', 'asuka-product-designer')],
            ['family' => 'Verdana', 'stack' => 'Verdana, Geneva, sans-serif', 'category' => __('Sans serif', 'asuka-product-designer')],
            ['family' => 'Tahoma', 'stack' => 'Tahoma, Verdana, sans-serif', 'category' => __('Sans serif', 'asuka-product-designer')],
            ['family' => 'Trebuchet MS', 'stack' => '"Trebuchet MS", Arial, sans-serif', 'category' => __('Sans serif', 'asuka-product-designer')],
            ['family' => 'Arial Black', 'stack' => '"Arial Black", Arial, sans-serif', 'category' => __('Display', 'asuka-product-designer')],
            ['family' => 'Georgia', 'stack' => 'Georgia, "Times New Roman", serif', 'category' => __('Serif', 'asuka-product-designer')],
            ['family' => 'Times New Roman', 'stack' => '"Times New Roman", Times, serif', 'category' => __('Serif', 'asuka-product-designer')],
            ['family' => 'Palatino Linotype', 'stack' => '"Palatino Linotype", Palatino, Georgia, serif', 'category' => __('Serif', 'asuka-product-designer')],
            ['family' => 'Courier New', 'stack' => '"Courier New", Courier, monospace', 'category' => __('Monospace', 'asuka-product-designer')],
            ['family' => 'Impact', 'stack' => 'Impact, Haettenschweiler, sans-serif', 'category' => __('Display', 'asuka-product-designer')],
        ];
    }

    private function renderFontList(string $pageSlug, array $items, string $editorPageSlug) : void
    {
        echo '<div class="apd-font-list">';
        if (empty($items)) {
            echo '<div class="apd-callout"><strong>' . esc_html__('No fonts yet', 'asuka-product-designer') . '</strong><p>' . esc_html__('Add your first reusable font to start building a curated typography library for your custom products.', 'asuka-product-designer') . '</p></div>';
            echo '</div>';
            return;
        }

        echo '<div class="apd-font-list__toolbar">';
        echo '<div class="apd-chip-row">';
        echo '<span class="apd-chip apd-chip-soft">' . esc_html(sprintf(/* translators: Placeholder values are populated from the current administration record. */ _n('%d font', '%d fonts', count($items), 'asuka-product-designer'), count($items))) . '</span>';
        echo '</div>';
        echo '</div>';

        echo '<div class="apd-font-cards" data-apd-catalog-list="fonts">';
        foreach (array_values($items) as $index => $item) {
            $label = (string) ($item['label'] ?? $item['family'] ?? $item['id'] ?? __('Untitled font', 'asuka-product-designer'));
            $family = (string) ($item['family'] ?? $label);
            $category = (string) ($item['category'] ?? '');
            $source = sanitize_key((string) ($item['source'] ?? 'custom')) ?: 'custom';
            $weights = is_array($item['weights'] ?? null) ? implode(', ', array_map('strval', (array) $item['weights'])) : (string) ($item['weights'] ?? '400');
            $enabled = ! isset($item['enabled']) || ! empty($item['enabled']);
            $meta = array_filter([
                $category,
                $this->labelForSource($source),
                $weights !== '' ? sprintf(/* translators: Placeholder values are populated from the current administration record. */ __('Weights: %s', 'asuka-product-designer'), $weights) : '',
            ]);

            $search = strtolower(trim($label . ' ' . $family . ' ' . $category . ' ' . $source));
            echo '<article class="apd-font-card" data-apd-search="' . esc_attr($search) . '" data-apd-category="' . esc_attr($category) . '">';
            echo '<div class="apd-font-card__preview" style="font-family:' . esc_attr($family) . ', sans-serif">';
            echo '<span>Aa</span>';
            echo '</div>';
            echo '<div class="apd-font-card__content">';
            echo '<div class="apd-font-card__head">';
            echo '<div>';
            echo '<h3>' . esc_html($label) . '</h3>';
            echo '<p>' . esc_html($family) . '</p>';
            echo '</div>';
            echo $enabled ? '<span class="apd-chip apd-chip-success">' . esc_html__('Visible', 'asuka-product-designer') . '</span>' : '<span class="apd-chip apd-chip-soft">' . esc_html__('Hidden', 'asuka-product-designer') . '</span>';
            echo '</div>';
            if ($meta !== []) {
                echo '<div class="apd-chip-row apd-chip-row-wrap">';
                foreach ($meta as $chip) {
                    echo '<span class="apd-chip apd-chip-soft">' . esc_html((string) $chip) . '</span>';
                }
                echo '</div>';
            }
            echo '<div class="apd-inline-actions apd-inline-actions-wrap apd-row-actions">';
            $this->renderCatalogEditorButton($editorPageSlug, 'fonts', $index, __('Edit', 'asuka-product-designer'));
            $this->renderCatalogActionButton('apd_duplicate_catalog_item', $pageSlug, 'fonts', $index, __('Duplicate', 'asuka-product-designer'), 'apd_duplicate_catalog_item');
            $this->renderCatalogActionButton('apd_delete_catalog_item', $pageSlug, 'fonts', $index, __('Delete', 'asuka-product-designer'), 'apd_delete_catalog_item', [], __('Delete this font?', 'asuka-product-designer'));
            echo '</div>';
            echo '</div>';
            echo '</article>';
        }
        echo '</div>';
        echo '</div>';
    }

    private function labelForSource(string $source) : string
    {
        return match ($source) {
            'google' => __('Google Fonts', 'asuka-product-designer'),
            'system' => __('System font', 'asuka-product-designer'),
            default => __('Custom file', 'asuka-product-designer'),
        };
    }
}
