<?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 ColorsPage
{
    use CatalogPageTrait;

    private function colorColumns() : array
    {
        return [
            'id' => ['label' => __('ID', 'asuka-product-designer'), 'placeholder' => 'navy'],
            'label' => ['label' => __('Label', 'asuka-product-designer'), 'placeholder' => __('Navy', 'asuka-product-designer')],
            'value' => ['label' => __('Color value', 'asuka-product-designer'), 'placeholder' => '#223056'],
            'type' => ['label' => __('Type', 'asuka-product-designer'), 'type' => 'select', 'options' => [
                'solid' => __('Solid color', 'asuka-product-designer'),
                'gradient' => __('Gradient', 'asuka-product-designer'),
                'pattern' => __('Pattern', 'asuka-product-designer'),
                'image' => __('Image', 'asuka-product-designer'),
            ]],
            'isDefault' => ['label' => __('Default', 'asuka-product-designer'), 'type' => 'checkbox', 'checkbox_label' => __('Use as the default color when possible', 'asuka-product-designer')],
            'group' => ['label' => __('Group', 'asuka-product-designer'), 'placeholder' => __('Classic', 'asuka-product-designer')],
            'price' => ['label' => __('Extra price', 'asuka-product-designer'), 'placeholder' => '0'],
            'enabled' => ['label' => __('Visibility', 'asuka-product-designer'), 'type' => 'checkbox', 'checkbox_label' => __('Expose this color', 'asuka-product-designer')],
        ];
    }

    private function colorDefaults() : array
    {
        return ['type' => 'solid', 'price' => '0', 'isDefault' => false, 'enabled' => true];
    }

    private function printingMethodColumns() : array
    {
        return [
            'id' => ['label' => __('ID', 'asuka-product-designer'), 'placeholder' => 'dtg'],
            'label' => ['label' => __('Label', 'asuka-product-designer'), 'placeholder' => __('DTG', 'asuka-product-designer')],
            'price' => ['label' => __('Extra price', 'asuka-product-designer'), 'placeholder' => '0'],
            'category' => ['label' => __('Category', 'asuka-product-designer'), 'placeholder' => __('Digital print', 'asuka-product-designer')],
            'colorIds' => ['label' => __('Allowed color IDs', 'asuka-product-designer'), 'placeholder' => 'navy, white', 'help' => __('Comma-separated color IDs from the palette above.', 'asuka-product-designer')],
            'description' => ['label' => __('Description', 'asuka-product-designer'), 'type' => 'textarea', 'full' => true],
            'enabled' => ['label' => __('Visibility', 'asuka-product-designer'), 'type' => 'checkbox', 'checkbox_label' => __('Expose this printing method', 'asuka-product-designer')],
        ];
    }

    private function printingMethodDefaults() : array
    {
        return ['price' => '0', 'colorIds' => '', 'enabled' => true];
    }

    public function render() : void
    {
        $catalog = (new AssetCatalog())->all();
        $this->pageShellStart(
            __('Color and print catalog', 'asuka-product-designer'),
            __('Colors and printing methods', 'asuka-product-designer'),
            __('Manage the global color palette and the printing methods that can be filtered per custom product.', 'asuka-product-designer')
        );
        $this->renderCatalogNotice();

        echo '<div class="apd-grid">';
        $this->renderCrudSection(
            'apd-colors',
            'colors',
            __('Global colors', 'asuka-product-designer'),
            __('Browse the color palette here, then open a dedicated page to add or edit one color at a time.', 'asuka-product-designer'),
            (array) ($catalog['colors'] ?? []),
            $this->colorColumns(),
            $this->colorDefaults(),
            'apd-colors-editor'
        );

        $this->renderCrudSection(
            'apd-colors',
            'printing_methods',
            __('Global printing methods', 'asuka-product-designer'),
            __('Browse printing methods here, then open a dedicated page to add or edit one method at a time.', 'asuka-product-designer'),
            (array) ($catalog['printing_methods'] ?? []),
            $this->printingMethodColumns(),
            $this->printingMethodDefaults(),
            'apd-printing-methods-editor'
        );
        echo '</div>';

        $this->pageShellEnd();
    }

    public function renderColorEditor() : void
    {
        $catalog = (new AssetCatalog())->all();
        $this->pageShellStart(
            __('Color and print catalog', 'asuka-product-designer'),
            __('Color editor', 'asuka-product-designer'),
            __('Create or update one global color at a time, then return to the shared palette list.', 'asuka-product-designer')
        );
        $this->renderCatalogNotice();
        $this->renderAdaptiveColorEditor(
            (array) ($catalog['colors'] ?? []),
            (array) ($catalog['printing_methods'] ?? [])
        );
        $this->pageShellEnd();
    }

    public function renderPrintingMethodEditor() : void
    {
        $catalog = (new AssetCatalog())->all();
        $this->pageShellStart(
            __('Color and print catalog', 'asuka-product-designer'),
            __('Printing method editor', 'asuka-product-designer'),
            __('Create or update one printing method at a time, then return to the shared method list.', 'asuka-product-designer')
        );
        $this->renderCatalogNotice();
        $this->renderAdaptivePrintingMethodEditor(
            (array) ($catalog['printing_methods'] ?? []),
            (array) ($catalog['colors'] ?? [])
        );
        $this->pageShellEnd();
    }

    private function renderAdaptiveColorEditor(array $items, array $printingMethods) : void
    {
        [$item, $index, $isEdit] = $this->resolveEditorItem($items, $this->colorDefaults());
        $type = sanitize_key((string) ($item['type'] ?? 'solid')) ?: 'solid';
        $value = (string) ($item['value'] ?? '#223056');
        $solidValue = preg_match('/^#[0-9a-f]{6}$/i', $value) ? $value : '#223056';
        [$gradientAngle, $gradientStart, $gradientEnd] = $this->parseGradientValue($value);
        $relationMode = sanitize_key((string) ($item['printingMethodMode'] ?? ''));
        $selectedMethodIds = $this->stringIds($item['printingMethodIds'] ?? []);
        if (! in_array($relationMode, ['all', 'restricted', 'none'], true)) {
            $relationMode = $selectedMethodIds !== [] ? 'restricted' : 'all';
        }

        echo '<section class="apd-card apd-crud-card apd-crud-card-editor">';
        echo '<div class="apd-card-head apd-card-head-stack"><div><h2>' . esc_html__('Global colors', 'asuka-product-designer') . '</h2><p>' . esc_html__('Build the visual value and its printing compatibility in one place.', 'asuka-product-designer') . '</p></div><a class="button button-secondary" href="' . esc_url($this->getCatalogPageUrl('apd-colors', ['apd_collection' => 'colors'])) . '">' . esc_html__('Back to list', 'asuka-product-designer') . '</a></div>';
        echo '<div class="apd-crud-editor apd-catalog-editor-v2 apd-color-editor" data-apd-color-editor data-apd-color-type="' . esc_attr($type) . '">';
        echo '<div class="apd-crud-editor__head"><div><span class="apd-editor-eyebrow">' . esc_html__('Palette color', 'asuka-product-designer') . '</span><h3>' . esc_html($isEdit ? __('Edit color', 'asuka-product-designer') : __('Add color', 'asuka-product-designer')) . '</h3><p>' . esc_html__('The form changes with the selected color source and previews the final runtime value.', 'asuka-product-designer') . '</p></div></div>';
        echo '<form method="post" action="' . esc_url(admin_url('admin-post.php')) . '" class="apd-color-editor__form">';
        $this->renderCatalogFormHiddenFields('colors', $index);
        echo '<input type="hidden" name="item[type]" value="' . esc_attr($type) . '" data-apd-color-type-input>';
        echo '<input type="hidden" name="item[value]" value="' . esc_attr($value) . '" data-apd-color-value>';
        echo '<input type="hidden" name="item[printingMethodMode]" value="' . esc_attr($relationMode) . '" data-apd-color-method-mode>';

        echo '<div class="apd-catalog-editor-layout">';
        echo '<aside class="apd-catalog-preview-panel"><div class="apd-editor-section-heading"><span class="apd-chip apd-chip-soft">' . esc_html__('Live preview', 'asuka-product-designer') . '</span><span data-apd-color-preview-type>' . esc_html(ucfirst($type)) . '</span></div>';
        echo '<div class="apd-color-preview" data-apd-color-preview><span data-apd-color-preview-label>' . esc_html((string) ($item['label'] ?? __('Untitled color', 'asuka-product-designer'))) . '</span><code data-apd-color-preview-value>' . esc_html($value) . '</code></div>';
        echo '<div class="apd-editor-note"><strong>' . esc_html__('Pricing aware', 'asuka-product-designer') . '</strong><p>' . esc_html__('The extra price is charged only when this color is compatible with the printing method used by the layer.', 'asuka-product-designer') . '</p></div></aside>';

        echo '<div class="apd-catalog-editor-fields">';
        echo '<div class="apd-color-type-picker">';
        foreach ([
            'solid' => [__('Solid', 'asuka-product-designer'), __('A hexadecimal or CSS color.', 'asuka-product-designer')],
            'gradient' => [__('Gradient', 'asuka-product-designer'), __('Two colors and a direction.', 'asuka-product-designer')],
            'pattern' => [__('Pattern', 'asuka-product-designer'), __('A repeatable image asset.', 'asuka-product-designer')],
            'image' => [__('Image', 'asuka-product-designer'), __('A full image-based color value.', 'asuka-product-designer')],
        ] as $typeId => $copy) {
            echo '<button type="button" data-apd-color-type-option="' . esc_attr($typeId) . '"><strong>' . esc_html($copy[0]) . '</strong><small>' . esc_html($copy[1]) . '</small></button>';
        }
        echo '</div>';

        echo '<section class="apd-source-workspace" data-apd-color-type-only="solid"><div class="apd-source-workspace__head"><div><span class="apd-editor-eyebrow">' . esc_html__('Solid color', 'asuka-product-designer') . '</span><h4>' . esc_html__('Choose an exact value', 'asuka-product-designer') . '</h4></div></div><div class="apd-color-input-row"><input type="color" value="' . esc_attr($solidValue) . '" data-apd-solid-color-picker aria-label="' . esc_attr__('Color picker', 'asuka-product-designer') . '"><label class="apd-field"><span>' . esc_html__('Hex or CSS value', 'asuka-product-designer') . '</span><input type="text" value="' . esc_attr($value) . '" placeholder="#223056" data-apd-solid-color-text></label></div></section>';

        echo '<section class="apd-source-workspace" data-apd-color-type-only="gradient"><div class="apd-source-workspace__head"><div><span class="apd-editor-eyebrow">' . esc_html__('Linear gradient', 'asuka-product-designer') . '</span><h4>' . esc_html__('Compose the transition', 'asuka-product-designer') . '</h4></div></div><div class="apd-form-grid apd-form-grid-3">';
        echo '<label class="apd-field"><span>' . esc_html__('Direction', 'asuka-product-designer') . '</span><div class="apd-number-suffix"><input type="number" min="0" max="360" step="1" value="' . esc_attr((string) $gradientAngle) . '" data-apd-gradient-angle><span>deg</span></div></label>';
        echo '<label class="apd-field"><span>' . esc_html__('Start color', 'asuka-product-designer') . '</span><div class="apd-color-value-control"><input type="color" value="' . esc_attr($gradientStart) . '" data-apd-gradient-start data-apd-gradient-color-picker="start" aria-label="' . esc_attr__('Start color picker', 'asuka-product-designer') . '"><input type="text" value="' . esc_attr($gradientStart) . '" placeholder="#2563eb" spellcheck="false" autocomplete="off" data-apd-gradient-color-text="start" aria-label="' . esc_attr__('Start color HEX value', 'asuka-product-designer') . '"></div></label>';
        echo '<label class="apd-field"><span>' . esc_html__('End color', 'asuka-product-designer') . '</span><div class="apd-color-value-control"><input type="color" value="' . esc_attr($gradientEnd) . '" data-apd-gradient-end data-apd-gradient-color-picker="end" aria-label="' . esc_attr__('End color picker', 'asuka-product-designer') . '"><input type="text" value="' . esc_attr($gradientEnd) . '" placeholder="#11bfae" spellcheck="false" autocomplete="off" data-apd-gradient-color-text="end" aria-label="' . esc_attr__('End color HEX value', 'asuka-product-designer') . '"></div></label>';
        echo '</div><label class="apd-field"><span>' . esc_html__('Generated CSS value', 'asuka-product-designer') . '</span><input type="text" value="' . esc_attr($value) . '" data-apd-gradient-css><small>' . esc_html__('You can fine-tune the CSS value manually; supported linear gradients are reflected back into the controls.', 'asuka-product-designer') . '</small></label></section>';

        foreach (['pattern' => __('Pattern image', 'asuka-product-designer'), 'image' => __('Image asset', 'asuka-product-designer')] as $assetType => $assetLabel) {
            echo '<section class="apd-source-workspace" data-apd-color-type-only="' . esc_attr($assetType) . '"><div class="apd-source-workspace__head"><div><span class="apd-editor-eyebrow">' . esc_html($assetLabel) . '</span><h4>' . esc_html__('Select the source asset', 'asuka-product-designer') . '</h4><p>' . esc_html($assetType === 'pattern' ? __('Use a seamless image when the color should repeat cleanly.', 'asuka-product-designer') : __('Use a production-ready image URL or choose it from the Media Library.', 'asuka-product-designer')) . '</p></div></div>';
            echo '<label class="apd-field"><span>' . esc_html__('Image URL', 'asuka-product-designer') . '</span><div class="apd-media-field"><input type="text" value="' . esc_attr(in_array($type, ['pattern', 'image'], true) ? $value : '') . '" placeholder="https://example.com/assets/texture.webp" data-apd-field="value" data-apd-color-media-url><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="image">' . 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></label></section>';
        }

        echo '<section class="apd-source-workspace apd-source-workspace--details"><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 price this color', 'asuka-product-designer') . '</h4></div></div><div class="apd-form-grid apd-form-grid-2">';
        $this->renderCrudField('label', ['label' => __('Public label', 'asuka-product-designer'), 'placeholder' => __('Navy', 'asuka-product-designer'), 'attributes' => ['data-apd-color-sync' => 'label']], (string) ($item['label'] ?? ''));
        $this->renderCrudField('id', ['label' => __('ID', 'asuka-product-designer'), 'placeholder' => 'navy', 'help' => __('Generated from the label until edited.', 'asuka-product-designer'), 'attributes' => ['data-apd-color-sync' => 'id']], (string) ($item['id'] ?? ''));
        $this->renderCrudField('group', ['label' => __('Group', 'asuka-product-designer'), 'placeholder' => __('Classic', 'asuka-product-designer')], (string) ($item['group'] ?? ''));
        $this->renderCrudField('price', ['label' => __('Extra price', 'asuka-product-designer'), 'type' => 'number', 'placeholder' => '0', 'attributes' => ['step' => '0.01', 'min' => '0']], (string) ($item['price'] ?? '0'));
        echo '</div></section>';

        echo '<section class="apd-source-workspace"><div class="apd-source-workspace__head"><div><span class="apd-editor-eyebrow">' . esc_html__('Printing compatibility', 'asuka-product-designer') . '</span><h4>' . esc_html__('Where can this color be used?', 'asuka-product-designer') . '</h4><p>' . esc_html__('This relation is shared with printing method palettes and the pricing engine.', 'asuka-product-designer') . '</p></div></div>';
        $this->renderRelationModeControl('color', $relationMode, [
            'all' => __('All methods', 'asuka-product-designer'),
            'restricted' => __('Selected methods', 'asuka-product-designer'),
            'none' => __('No method', 'asuka-product-designer'),
        ]);
        echo '<div class="apd-relation-grid" data-apd-color-method-options>';
        if ($printingMethods === []) {
            echo '<div class="apd-empty-inline">' . esc_html__('No printing method exists yet. Save this color, then add one from the catalog.', 'asuka-product-designer') . '</div>';
        }
        foreach ($printingMethods as $method) {
            if (! is_array($method)) {
                continue;
            }
            $methodId = sanitize_key((string) ($method['id'] ?? ''));
            if ($methodId === '') {
                continue;
            }
            echo '<label class="apd-relation-option"><input type="checkbox" name="item[printingMethodIds][]" value="' . esc_attr($methodId) . '" ' . checked(in_array($methodId, $selectedMethodIds, true), true, false) . '><span><strong>' . esc_html((string) ($method['label'] ?? $methodId)) . '</strong><small>' . esc_html((string) ($method['category'] ?? __('Printing method', 'asuka-product-designer'))) . '</small></span></label>';
        }
        echo '</div></section>';

        echo '<section class="apd-source-workspace apd-visibility-row">';
        $this->renderCrudField('isDefault', ['label' => __('Default color', 'asuka-product-designer'), 'type' => 'checkbox', 'checkbox_label' => __('Use this color by default when possible', 'asuka-product-designer')], ! empty($item['isDefault']));
        $this->renderCrudField('enabled', ['label' => __('Visibility', 'asuka-product-designer'), 'type' => 'checkbox', 'checkbox_label' => __('Expose this color in the designer', 'asuka-product-designer')], ! empty($item['enabled']));
        echo '</section>';
        echo '<div class="apd-inline-actions apd-editor-actions">';
        submit_button(__('Save color', 'asuka-product-designer'), 'primary', 'submit', false);
        echo '<a class="button button-secondary" href="' . esc_url($this->getCatalogPageUrl('apd-colors', ['apd_collection' => 'colors'])) . '">' . esc_html__('Cancel', 'asuka-product-designer') . '</a></div>';
        echo '</div></div></form></div></section>';
    }

    private function renderAdaptivePrintingMethodEditor(array $items, array $colors) : void
    {
        [$item, $index, $isEdit] = $this->resolveEditorItem($items, $this->printingMethodDefaults());
        $colorIds = $this->stringIds($item['colorIds'] ?? []);
        $paletteMode = sanitize_key((string) ($item['palette']['mode'] ?? ''));
        if (! in_array($paletteMode, ['all', 'restricted', 'none'], true)) {
            $paletteMode = $colorIds !== [] ? 'restricted' : 'all';
        }

        echo '<section class="apd-card apd-crud-card apd-crud-card-editor">';
        echo '<div class="apd-card-head apd-card-head-stack"><div><h2>' . esc_html__('Global printing methods', 'asuka-product-designer') . '</h2><p>' . esc_html__('Configure pricing and the exact palette exposed by a printing process.', 'asuka-product-designer') . '</p></div><a class="button button-secondary" href="' . esc_url($this->getCatalogPageUrl('apd-colors', ['apd_collection' => 'printing_methods'])) . '">' . esc_html__('Back to list', 'asuka-product-designer') . '</a></div>';
        echo '<div class="apd-crud-editor apd-catalog-editor-v2 apd-printing-method-editor" data-apd-printing-method-editor data-apd-palette-mode="' . esc_attr($paletteMode) . '">';
        echo '<div class="apd-crud-editor__head"><div><span class="apd-editor-eyebrow">' . esc_html__('Production method', 'asuka-product-designer') . '</span><h3>' . esc_html($isEdit ? __('Edit printing method', 'asuka-product-designer') : __('Add printing method', 'asuka-product-designer')) . '</h3><p>' . esc_html__('Keep the customer palette, production constraint, and price adjustment synchronized.', 'asuka-product-designer') . '</p></div></div>';
        echo '<form method="post" action="' . esc_url(admin_url('admin-post.php')) . '">';
        $this->renderCatalogFormHiddenFields('printing_methods', $index);
        echo '<input type="hidden" name="item[palette][mode]" value="' . esc_attr($paletteMode) . '" data-apd-palette-mode-input>';
        echo '<div class="apd-catalog-editor-layout">';
        echo '<aside class="apd-catalog-preview-panel"><div class="apd-editor-section-heading"><span class="apd-chip apd-chip-soft">' . esc_html__('Palette preview', 'asuka-product-designer') . '</span><span data-apd-palette-count></span></div><div class="apd-method-preview"><span class="apd-method-preview__title" data-apd-method-preview-label>' . esc_html((string) ($item['label'] ?? __('Untitled method', 'asuka-product-designer'))) . '</span><div class="apd-method-preview__swatches" data-apd-method-preview-swatches></div><strong data-apd-method-preview-price></strong></div><div class="apd-editor-note"><strong>' . esc_html__('One shared contract', 'asuka-product-designer') . '</strong><p>' . esc_html__('Saving this method updates the compatible methods on each color as well.', 'asuka-product-designer') . '</p></div></aside>';
        echo '<div class="apd-catalog-editor-fields">';
        echo '<section class="apd-source-workspace apd-source-workspace--details"><div class="apd-source-workspace__head"><div><span class="apd-editor-eyebrow">' . esc_html__('Method details', 'asuka-product-designer') . '</span><h4>' . esc_html__('Name and price this process', 'asuka-product-designer') . '</h4></div></div><div class="apd-form-grid apd-form-grid-2">';
        $this->renderCrudField('label', ['label' => __('Public label', 'asuka-product-designer'), 'placeholder' => __('Direct to garment', 'asuka-product-designer'), 'attributes' => ['data-apd-method-sync' => 'label']], (string) ($item['label'] ?? ''));
        $this->renderCrudField('id', ['label' => __('ID', 'asuka-product-designer'), 'placeholder' => 'dtg', 'help' => __('Generated from the label until edited.', 'asuka-product-designer'), 'attributes' => ['data-apd-method-sync' => 'id']], (string) ($item['id'] ?? ''));
        $this->renderCrudField('category', ['label' => __('Category', 'asuka-product-designer'), 'placeholder' => __('Digital print', 'asuka-product-designer')], (string) ($item['category'] ?? ''));
        $this->renderCrudField('price', ['label' => __('Extra price', 'asuka-product-designer'), 'type' => 'number', 'placeholder' => '0', 'attributes' => ['data-apd-method-sync' => 'price', 'step' => '0.01', 'min' => '0']], (string) ($item['price'] ?? '0'));
        $this->renderCrudField('description', ['label' => __('Description', 'asuka-product-designer'), 'type' => 'textarea', 'full' => true, 'rows' => 4], (string) ($item['description'] ?? ''));
        echo '</div></section>';

        echo '<section class="apd-source-workspace"><div class="apd-source-workspace__head"><div><span class="apd-editor-eyebrow">' . esc_html__('Customer palette', 'asuka-product-designer') . '</span><h4>' . esc_html__('Which colors does this method allow?', 'asuka-product-designer') . '</h4><p>' . esc_html__('Choose all colors, a curated subset, or no color palette for methods that do not expose color choices.', 'asuka-product-designer') . '</p></div></div>';
        $this->renderRelationModeControl('palette', $paletteMode, [
            'all' => __('All colors', 'asuka-product-designer'),
            'restricted' => __('Selected colors', 'asuka-product-designer'),
            'none' => __('No palette', 'asuka-product-designer'),
        ]);
        echo '<div class="apd-relation-grid apd-relation-grid--colors" data-apd-palette-color-options>';
        if ($colors === []) {
            echo '<div class="apd-empty-inline">' . esc_html__('No global color exists yet. Add colors before creating a restricted palette.', 'asuka-product-designer') . '</div>';
        }
        foreach ($colors as $color) {
            if (! is_array($color)) {
                continue;
            }
            $colorId = sanitize_key((string) ($color['id'] ?? ''));
            if ($colorId === '') {
                continue;
            }
            $colorValue = (string) ($color['value'] ?? '#dce6f5');
            echo '<label class="apd-relation-option apd-relation-option--color"><input type="checkbox" name="item[colorIds][]" value="' . esc_attr($colorId) . '" data-color-value="' . esc_attr($colorValue) . '" data-color-label="' . esc_attr((string) ($color['label'] ?? $colorId)) . '" ' . checked(in_array($colorId, $colorIds, true), true, false) . '><span><i style="background:' . esc_attr($colorValue) . '"></i><strong>' . esc_html((string) ($color['label'] ?? $colorId)) . '</strong><small>' . esc_html((string) ($color['group'] ?? $colorId)) . '</small></span></label>';
        }
        echo '</div></section>';
        echo '<section class="apd-source-workspace apd-visibility-row">';
        $this->renderCrudField('enabled', ['label' => __('Visibility', 'asuka-product-designer'), 'type' => 'checkbox', 'checkbox_label' => __('Expose this printing method in the designer', 'asuka-product-designer')], ! empty($item['enabled']));
        echo '</section>';
        echo '<div class="apd-inline-actions apd-editor-actions">';
        submit_button(__('Save printing method', 'asuka-product-designer'), 'primary', 'submit', false);
        echo '<a class="button button-secondary" href="' . esc_url($this->getCatalogPageUrl('apd-colors', ['apd_collection' => 'printing_methods'])) . '">' . esc_html__('Cancel', 'asuka-product-designer') . '</a></div>';
        echo '</div></div></form></div></section>';
    }

    private function renderCatalogFormHiddenFields(string $collection, ?int $index) : void
    {
        wp_nonce_field('apd_save_catalog_item');
        echo '<input type="hidden" name="action" value="apd_save_catalog_item"><input type="hidden" name="apd_page" value="apd-colors"><input type="hidden" name="apd_collection" value="' . esc_attr($collection) . '">';
        if ($index !== null) {
            echo '<input type="hidden" name="apd_index" value="' . esc_attr((string) $index) . '">';
        }
    }

    private function renderRelationModeControl(string $context, string $mode, array $labels) : void
    {
        echo '<div class="apd-relation-mode" data-apd-relation-mode="' . esc_attr($context) . '">';
        foreach ($labels as $value => $label) {
            echo '<button type="button" data-apd-relation-mode-option="' . esc_attr($value) . '" ' . ($mode === $value ? 'class="is-active"' : '') . '>' . esc_html($label) . '</button>';
        }
        echo '</div>';
    }

    private function resolveEditorItem(array $items, array $defaults) : array
    {
        $query = RequestData::query();
        $action = sanitize_key((string) ($query['apd_action'] ?? 'new'));
        $index = isset($query['apd_index']) ? max(0, (int) $query['apd_index']) : null;
        $isEdit = $action === 'edit' && $index !== null && isset($items[$index]);
        return [
            $isEdit ? wp_parse_args((array) $items[$index], $defaults) : $defaults,
            $isEdit ? $index : null,
            $isEdit,
        ];
    }

    private function parseGradientValue(string $value) : array
    {
        if (preg_match('/linear-gradient\(\s*(-?\d+(?:\.\d+)?)deg\s*,\s*(#[0-9a-f]{6})\s*,\s*(#[0-9a-f]{6})\s*\)/i', $value, $match)) {
            return [(int) round((float) $match[1]), $match[2], $match[3]];
        }
        return [90, '#2563eb', '#11bfae'];
    }

    private function stringIds(mixed $value) : array
    {
        if (is_string($value)) {
            $value = preg_split('/[\s,]+/', $value) ?: [];
        }
        if (! is_array($value)) {
            return [];
        }
        return array_values(array_unique(array_filter(array_map(
            static fn($id) => sanitize_key((string) $id),
            $value
        ))));
    }
}
