<?php

declare(strict_types=1);

namespace CliqThemes\StoreLocator\Data\Definition;

defined('ABSPATH') || exit;

use CliqThemes\ORM\Form\FieldStorageDescriptor;
use CliqThemes\ORM\Form\FieldStorageMap;
use CliqThemes\ORM\Form\SchemaPersistenceCoordinator;
use CliqThemes\ORM\Form\StorageStrategyRegistry;
use CliqThemes\ORM\Form\Storage\JsonColumnStrategy;
use CliqThemes\ORM\Form\Storage\PassthroughStrategy;
use CliqThemes\ORM\Form\Storage\PivotStorageStrategy;
use CliqThemes\StoreLocator\Models\CustomField;
use CliqThemes\UI\Data\DataProviderRegistry;
use CliqThemes\UI\Data\SchemaAwareOrmProvider;

/**
 * Provider definition for the Custom Field manager (schema-aware placement + options).
 */
final class CustomFieldProviderDefinition implements ProviderDefinition
{
    public function key(): string
    {
        return 'custom-fields';
    }

    /**
     * @return array<string, mixed>
     */
    public function register(DataProviderRegistry $registry, ProviderContext $context): array
    {
        $categoryOptions = $context->categoryOptions();
        $storeTabSections = $context->storeTabSections();

        global $wpdb;

        // Custom Fields manager (schema-aware: persists category links + options)
        $customFieldsTable = $wpdb->prefix . 'cliq_sl_custom_fields';
        $customFieldCategoryTable = $wpdb->prefix . 'cliq_sl_custom_field_category';

        // Build a dependent section <select> per tab (shown when that tab is
        // chosen), listing the tab's sections plus "New section".
        $placementSectionFields = [];
        foreach ($storeTabSections as $tabId => $tab) {
            $sectionOptions = [];
            foreach ($tab['groups'] as $groupId => $groupLabel) {
                $sectionOptions[] = ['value' => $groupId, 'label' => $groupLabel];
            }
            $sectionOptions[] = ['value' => '__new', 'label' => __('➕ New section', 'cliq-store-locator')];

            $placementSectionFields[] = [
                'name' => 'placement_section_when_' . $tabId,
                'type' => 'conditional',
                'conditions' => [['field' => 'placement_tab', 'operator' => 'equals', 'value' => $tabId]],
                'conditionLogic' => 'or',
                'fields' => [
                    [
                        'name' => 'placement_section__' . $tabId,
                        'label' => __('Section', 'cliq-store-locator'),
                        'type' => 'select',
                        'default' => '',
                        'storage' => ['target' => 'json', 'table' => $customFieldsTable, 'column' => 'config', 'key_column' => 'id'],
                        'options' => $sectionOptions,
                    ],
                ],
            ];
        }

        $customFieldForm = [
            'primaryKey' => 'id',
            'label' => __('Custom Field', 'cliq-store-locator'),
            'submitLabels' => [
                'create' => __('Add Field', 'cliq-store-locator'),
                'update' => __('Update Field', 'cliq-store-locator'),
            ],
            'fields' => [
                ['name' => 'label', 'label' => __('Label', 'cliq-store-locator'), 'type' => 'text', 'required' => true],
                ['name' => 'field_key', 'label' => __('Key', 'cliq-store-locator'), 'type' => 'text', 'required' => true, 'help' => __('Unique machine key, e.g. warranty_years', 'cliq-store-locator')],
                ['name' => 'entity', 'label' => __('Applies To', 'cliq-store-locator'), 'type' => 'select', 'default' => 'store', 'options' => [
                    ['value' => 'store', 'label' => __('Stores', 'cliq-store-locator')],
                    ['value' => 'brand', 'label' => __('Brands', 'cliq-store-locator')],
                ], 'help' => __('Brand fields are shown on every brand; store fields can be scoped to categories below.', 'cliq-store-locator')],
                ['name' => 'type', 'label' => __('Field Type', 'cliq-store-locator'), 'type' => 'select', 'default' => 'text', 'options' => [
                    ['value' => 'text', 'label' => __('Text', 'cliq-store-locator')],
                    ['value' => 'textarea', 'label' => __('Textarea', 'cliq-store-locator')],
                    ['value' => 'number', 'label' => __('Number', 'cliq-store-locator')],
                    ['value' => 'url', 'label' => __('URL', 'cliq-store-locator')],
                    ['value' => 'email', 'label' => __('Email', 'cliq-store-locator')],
                    ['value' => 'date', 'label' => __('Date', 'cliq-store-locator')],
                    ['value' => 'select', 'label' => __('Select', 'cliq-store-locator')],
                    ['value' => 'checkboxes', 'label' => __('Checkboxes', 'cliq-store-locator')],
                    ['value' => 'radio', 'label' => __('Radio', 'cliq-store-locator')],
                    ['value' => 'toggle', 'label' => __('Toggle', 'cliq-store-locator')],
                    ['value' => 'color', 'label' => __('Color', 'cliq-store-locator')],
                    ['value' => 'image', 'label' => __('Image', 'cliq-store-locator')],
                    ['value' => 'repeater', 'label' => __('Repeater', 'cliq-store-locator')],
                ]],
                [
                    'name' => 'options_when_choice',
                    'type' => 'conditional',
                    'conditions' => [
                        ['field' => 'type', 'operator' => 'equals', 'value' => 'select'],
                        ['field' => 'type', 'operator' => 'equals', 'value' => 'checkboxes'],
                        ['field' => 'type', 'operator' => 'equals', 'value' => 'radio'],
                    ],
                    'conditionLogic' => 'or',
                    'fields' => [
                        [
                            'name' => 'options',
                            'label' => __('Choices', 'cliq-store-locator'),
                            'type' => 'repeater',
                            'default' => [],
                            'storage' => ['target' => 'json', 'table' => $customFieldsTable, 'column' => 'config', 'key_column' => 'id'],
                            'addButtonLabel' => __('Add choice', 'cliq-store-locator'),
                            'emptyMessage' => __('No choices yet.', 'cliq-store-locator'),
                            // Compact: label + value side by side; value auto-fills
                            // from the slugified label until edited by hand.
                            'itemColumns' => 2,
							'showColumnHeaders' => true,
							'compactAddIcon' => false,
                            'fields' => [
                                ['name' => 'label', 'label' => __('Label', 'cliq-store-locator'), 'type' => 'text', 'default' => '', 'placeholder' => __('Label', 'cliq-store-locator')],
                                ['name' => 'value', 'label' => __('Value', 'cliq-store-locator'), 'type' => 'text', 'default' => '', 'slugFrom' => 'label', 'placeholder' => __('value', 'cliq-store-locator')],
                            ],
                        ],
                    ],
                ],
                [
                    'name' => 'subfields_when_repeater',
                    'type' => 'conditional',
                    'conditions' => [
                        ['field' => 'type', 'operator' => 'equals', 'value' => 'repeater'],
                    ],
                    'conditionLogic' => 'or',
                    'fields' => [
                        [
                            'name' => 'fields',
                            'label' => __('Repeater Sub-fields', 'cliq-store-locator'),
                            'type' => 'repeater',
                            'default' => [],
                            'storage' => ['target' => 'json', 'table' => $customFieldsTable, 'column' => 'config', 'key_column' => 'id'],
                            'addButtonLabel' => __('Add sub-field', 'cliq-store-locator'),
                            'emptyMessage' => __('Define the fields that repeat for each row.', 'cliq-store-locator'),
                            'help' => __('Each row in the store form will contain these fields.', 'cliq-store-locator'),
                            'fields' => [
                                ['name' => 'name', 'label' => __('Field Key', 'cliq-store-locator'), 'type' => 'text', 'default' => ''],
                                ['name' => 'label', 'label' => __('Label', 'cliq-store-locator'), 'type' => 'text', 'default' => ''],
                                ['name' => 'type', 'label' => __('Type', 'cliq-store-locator'), 'type' => 'select', 'default' => 'text', 'options' => [
                                    ['value' => 'text', 'label' => __('Text', 'cliq-store-locator')],
                                    ['value' => 'textarea', 'label' => __('Textarea', 'cliq-store-locator')],
                                    ['value' => 'number', 'label' => __('Number', 'cliq-store-locator')],
                                    ['value' => 'url', 'label' => __('URL', 'cliq-store-locator')],
                                    ['value' => 'email', 'label' => __('Email', 'cliq-store-locator')],
                                    ['value' => 'date', 'label' => __('Date', 'cliq-store-locator')],
                                    ['value' => 'image', 'label' => __('Image', 'cliq-store-locator')],
                                ]],
                            ],
                        ],
                    ],
                ],
                [
                    'name' => 'categories_when_store',
                    'type' => 'conditional',
                    'conditions' => [
                        ['field' => 'entity', 'operator' => 'equals', 'value' => 'store'],
                    ],
                    'conditionLogic' => 'or',
                    'fields' => [
                        [
                            'name' => 'categories',
                            'label' => __('Show for categories', 'cliq-store-locator'),
                            'type' => 'multiselect',
                            'default' => [],
                            'options' => $categoryOptions,
                            'storage' => ['target' => 'pivot', 'table' => $customFieldCategoryTable, 'foreign_key' => 'field_id', 'related_key' => 'category_id'],
                            'help' => __('Type to search. Leave empty to show the field for stores in every category.', 'cliq-store-locator'),
                        ],
                    ],
                ],
                [
                    'name' => 'placement_when_store',
                    'type' => 'conditional',
                    'columns' => 2,
                    'conditions' => [
                        ['field' => 'entity', 'operator' => 'equals', 'value' => 'store'],
                    ],
                    'conditionLogic' => 'or',
                    'fields' => [
                        [
                            'name' => 'placement_tab',
                            'label' => __('Show in tab', 'cliq-store-locator'),
                            'type' => 'select',
                            'default' => 'store-details',
                            'storage' => ['target' => 'json', 'table' => $customFieldsTable, 'column' => 'config', 'key_column' => 'id'],
                            'options' => [
                                ['value' => 'store-details', 'label' => __('Store Details', 'cliq-store-locator')],
                                ['value' => 'store-location', 'label' => __('Location', 'cliq-store-locator')],
                                ['value' => 'contact', 'label' => __('Contact', 'cliq-store-locator')],
                                ['value' => 'store-operations', 'label' => __('Store Operations', 'cliq-store-locator')],
                                ['value' => '__new', 'label' => __('➕ New tab…', 'cliq-store-locator')],
                            ],
                            'help' => __('Pick an existing tab or create a new one for this field.', 'cliq-store-locator'),
                        ],
                        [
                            'name' => 'placement_tab_new',
                            'type' => 'conditional',
                            'conditions' => [
                                ['field' => 'placement_tab', 'operator' => 'equals', 'value' => '__new'],
                            ],
                            'conditionLogic' => 'or',
                            'fields' => [
                                [
                                    'name' => 'placement_tab_label',
                                    'label' => __('New tab name', 'cliq-store-locator'),
                                    'type' => 'text',
                                    'storage' => ['target' => 'json', 'table' => $customFieldsTable, 'column' => 'config', 'key_column' => 'id'],
                                    'placeholder' => __('e.g. Compliance', 'cliq-store-locator'),
                                ],
                            ],
                        ],
                        ...$placementSectionFields,
                        [
                            'name' => 'is_filterable',
                            'label' => __('Show in list filters', 'cliq-store-locator'),
                            'type' => 'toggle',
                            'default' => false,
                            'storage' => ['target' => 'json', 'table' => $customFieldsTable, 'column' => 'config', 'key_column' => 'id'],
                            'help' => __('Add this field to the Filters bar on the Stores list.', 'cliq-store-locator'),
                        ],
                    ],
                ],
                ['name' => 'section', 'label' => __('New section name', 'cliq-store-locator'), 'type' => 'text', 'help' => __('Used when the section above is "New section" (or for a new tab).', 'cliq-store-locator')],
                ['name' => 'ordering', 'label' => __('Order', 'cliq-store-locator'), 'type' => 'number', 'default' => 0],
                ['name' => 'is_active', 'label' => __('Active', 'cliq-store-locator'), 'type' => 'toggle', 'default' => true],
            ],
        ];

        // FieldStorageMap reads form sections, so mirror the flat fields into a
        // single section/group for the storage map + renderer.
        $customFieldForm['sections'] = [
            [
                'id' => 'definition',
                'label' => __('Field Definition', 'cliq-store-locator'),
                'render' => 'regular',
                'groups' => [
                    [
                        'id' => 'main',
                        'layout' => 'grid',
                        'columns' => 2,
                        'fields' => $customFieldForm['fields'],
                    ],
                ],
            ],
        ];

        $customFieldStrategies = new StorageStrategyRegistry();
        $customFieldStrategies->register('base', static fn () => new PassthroughStrategy(new CustomField()));
        $customFieldStrategies->register('pivot', static fn (FieldStorageDescriptor $descriptor, array $context = []): PivotStorageStrategy => new PivotStorageStrategy($descriptor->options));
        $customFieldStrategies->register('json', static fn (FieldStorageDescriptor $descriptor, array $context = []): JsonColumnStrategy => new JsonColumnStrategy($descriptor->options));

        $customFieldCoordinator = new SchemaPersistenceCoordinator(
            CustomField::class,
            FieldStorageMap::fromForm($customFieldForm),
            $customFieldStrategies
        );

        $registry->register('custom-fields', new SchemaAwareOrmProvider(
            $customFieldCoordinator,
            columns: [
                'label' => ['label' => __('Field', 'cliq-store-locator')],
                'field_key' => ['label' => __('Key', 'cliq-store-locator')],
                'entity' => ['label' => __('Applies To', 'cliq-store-locator')],
                'type' => ['label' => __('Type', 'cliq-store-locator')],
            ],
            filters: [],
        ));

        return $customFieldForm;
    }
}
