<?php

declare(strict_types=1);

namespace CliqThemes\StoreLocator\Data\Definition;

defined('ABSPATH') || exit;

use CliqThemes\ORM\Form\FieldStorageMap;
use CliqThemes\ORM\Form\SchemaPersistenceCoordinator;
use CliqThemes\StoreLocator\I18n\ContentTranslator;
use CliqThemes\StoreLocator\Models\Brand;
use CliqThemes\StoreLocator\Repository\CustomFieldsRepository;
use CliqThemes\UI\Data\DataProviderRegistry;
use CliqThemes\UI\Data\SchemaAwareOrmProvider;

/**
 * Provider definition for the Brand entity (schema-aware: logo/website on the table, custom fields in meta).
 */
final class BrandProviderDefinition implements ProviderDefinition
{
    public function key(): string
    {
        return 'brands';
    }

    /**
     * @return array<string, mixed>
     */
    public function register(DataProviderRegistry $registry, ProviderContext $context): array
    {
        global $wpdb;

        // Brands (schema-aware: logo + description + website on the brands
        // table, plus admin-defined custom fields stored as JSON in meta).
        $brandsTable = $wpdb->prefix . 'cliq_sl_brands';

        $brandForm = [
            'primaryKey' => 'id',
            'label' => __('Brand', 'cliq-store-locator'),
            'submitLabels' => [
                'create' => __('Add Brand', 'cliq-store-locator'),
                'update' => __('Update Brand', 'cliq-store-locator'),
            ],
            'sections' => [
                [
                    'id' => 'brand-details',
                    'label' => __('Brand', 'cliq-store-locator'),
                    'render' => 'regular',
                    'groups' => [
                        [
                            'id' => 'identity',
                            'label' => __('Identity', 'cliq-store-locator'),
                            'columns' => 2,
                            'fields' => [
                                ['name' => 'name', 'label' => __('Name', 'cliq-store-locator'), 'type' => 'text', 'required' => true],
                                ['name' => 'slug', 'label' => __('Slug', 'cliq-store-locator'), 'type' => 'text', 'required' => true, 'slugFrom' => 'name', 'help' => __('Auto-filled from the name; edit to override.', 'cliq-store-locator')],
                                ['name' => 'website', 'label' => __('Website', 'cliq-store-locator'), 'type' => 'url'],
                            ],
                        ],
                        [
                            'id' => 'branding',
                            'label' => __('Branding', 'cliq-store-locator'),
                            'columns' => 2,
                            'fields' => [
                                [
                                    'name' => 'logo',
                                    'label' => __('Logo', 'cliq-store-locator'),
                                    'type' => 'image',
                                    'returnFormat' => 'url',
                                    'mediaLibrary' => ['type' => 'image'],
                                    'help' => __('Upload the brand logo.', 'cliq-store-locator'),
                                ],
                                ['name' => 'description', 'label' => __('Description', 'cliq-store-locator'), 'type' => 'textarea', 'rows' => 3],
                            ],
                        ],
                    ],
                ],
            ],
        ];

        // Inject admin-defined brand custom fields (defined once in the Custom
        // Field manager with Applies To = Brands, reused by every brand). Values
        // are stored per-brand in brands.meta under custom_fields.<key>.
        $brandCustomFieldDefs = [];
        try {
            foreach ((new CustomFieldsRepository())->forEntity('brand') as $brandField) {
                if (empty($brandField['field_key']) || empty($brandField['type'])) {
                    continue;
                }
                $brandCustomFieldDefs[] = (new CustomFieldsRepository())->toBrandFormField($brandField, $brandsTable);
            }
        } catch (\Throwable $e) {
            $brandCustomFieldDefs = [];
        }

        if ($brandCustomFieldDefs !== []) {
            $brandForm['sections'][0]['groups'][] = [
                'id' => 'brand-custom-fields',
                'label' => __('Custom Fields', 'cliq-store-locator'),
                'columns' => 2,
                'fields' => $brandCustomFieldDefs,
            ];
        }

        $brandForm['fields'] = array_values(array_reduce(
            $brandForm['sections'],
            static function (array $carry, array $section): array {
                foreach ($section['groups'] ?? [] as $group) {
                    foreach ($group['fields'] ?? [] as $field) {
                        $carry[] = $field;
                    }
                }

                return $carry;
            },
            []
        ));

        $brandCoordinator = new SchemaPersistenceCoordinator(
            Brand::class,
            FieldStorageMap::fromForm($brandForm),
            $context->strategyRegistry(new Brand())
        );

        $brandProvider = new SchemaAwareOrmProvider(
            $brandCoordinator,
            columns: [
                'logo' => ['label' => __('Logo', 'cliq-store-locator'), 'sortable' => false],
                'name' => ['label' => __('Brand', 'cliq-store-locator')],
                'website' => ['label' => __('Website', 'cliq-store-locator')],
            ],
            filters: [
                'q' => [
                    'label' => __('Search', 'cliq-store-locator'),
                    'type' => 'text',
                    'operator' => 'search',
                    'fields' => ['name', 'website', 'slug'],
                ],
                'name' => [
                    'label' => __('Brand', 'cliq-store-locator'),
                    'type' => 'text',
                    'operator' => 'contains',
                ],
            ],
        );

        // Scope-only: keep translation rows out of the grid (brand-name overlay
        // in the grid is deferred; BrandRepository overlays elsewhere).
        $brandProvider->addListProcessor(ContentTranslator::listProcessor('cliq_sl_brands'));
        $registry->register('brands', $brandProvider);

        return $brandForm;
    }
}
