<?php

declare(strict_types=1);

namespace CliqThemes\StoreLocator\Support;

defined('ABSPATH') || exit;

// Token discovery reads distinct keys from the plugin-owned metadata table.
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching

/**
 * Store-locator domain tokens for the (generic) cliq-ui builder. Defined here in
 * the plugin — the framework knows nothing about these; it just renders by the
 * `format`/`source` hints the host supplies. Shared by the admin data layer and
 * the public frontend so both resolve fields identically.
 */
final class DesignTokens
{
    /**
     * Per-request map of custom-field key => token format, populated from the store
     * form field types (see Plugin) so a WYSIWYG renders HTML and an "Opening Hours"
     * field renders a schedule — on the frontend AND the builder identically.
     *
     * @var array<string, string>
     */
    private static array $customFormats = [];

    /** @param array<string, string> $map */
    public static function setCustomFormats(array $map): void
    {
        self::$customFormats = $map;
    }

    /** Map a custom field input TYPE to the token format the renderer uses. */
    public static function formatForType(string $type): string
    {
        switch ($type) {
            case 'wysiwyg':
                return 'html';
            case 'hours':
                return 'schedule';
            case 'toggle':
                return 'toggle';
            case 'image':
                return 'media';
            default:
                return 'text';
        }
    }

    /**
     * Core store fields available as layout content tokens.
     *
     * @return array<int, array<string, string>>
     */
    public static function core(): array
    {
        return [
            ['value' => 'name', 'label' => __('Store name', 'cliq-store-locator')],
            ['value' => 'description', 'label' => __('Description', 'cliq-store-locator'), 'format' => 'html'],
            // value stays 'logo' (saved designs reference this token); only the label
            // changes. Its source is the store's hero_media, so it IS the hero image.
            ['value' => 'logo', 'label' => __('Hero image', 'cliq-store-locator'), 'format' => 'media', 'source' => 'hero_media', 'fallback' => 'logo'],
            ['value' => 'gallery', 'label' => __('Gallery', 'cliq-store-locator'), 'format' => 'gallery', 'source' => 'meta.gallery_media'],
            ['value' => 'address', 'label' => __('Address', 'cliq-store-locator'), 'format' => 'address'],
            ['value' => 'city', 'label' => __('City', 'cliq-store-locator')],
            ['value' => 'country', 'label' => __('Country', 'cliq-store-locator')],
            ['value' => 'status', 'label' => __('Status', 'cliq-store-locator')],
            ['value' => 'distance', 'label' => __('Distance from visitor', 'cliq-store-locator'), 'format' => 'distance'],
            ['value' => 'phone', 'label' => __('Phone', 'cliq-store-locator')],
            ['value' => 'email', 'label' => __('Email', 'cliq-store-locator')],
            ['value' => 'website', 'label' => __('Website', 'cliq-store-locator')],
            ['value' => 'category', 'label' => __('Category', 'cliq-store-locator'), 'format' => 'category'],
            ['value' => 'brand', 'label' => __('Brand name', 'cliq-store-locator'), 'source' => 'brand.name'],
            ['value' => 'brand_logo', 'label' => __('Brand logo', 'cliq-store-locator'), 'format' => 'media', 'source' => 'brand.logo'],
            // The weekly schedule and the current open/closed badge are separate
            // tokens. `opening_hours` also restores older saved card designs.
            ['value' => 'opening_hours', 'label' => __('Opening hours', 'cliq-store-locator'), 'format' => 'schedule', 'source' => 'opening_hours'],
            ['value' => 'hours', 'label' => __('Open/closed status', 'cliq-store-locator'), 'format' => 'open_status'],
            ['value' => 'rating', 'label' => __('Rating', 'cliq-store-locator'), 'format' => 'rating'],
            ['value' => 'directions', 'label' => __('Directions button', 'cliq-store-locator'), 'format' => 'button'],
            ['value' => 'details', 'label' => __('Details button', 'cliq-store-locator'), 'format' => 'button'],
        ];
    }

    /**
     * Category fields available as 'category_tile' layout content tokens —
     * the same shape PublicController::categories() already returns
     * ({id, name, slug, parent_id, icon, count}), so no extra
     * resolution/mapping is needed on the record side.
     *
     * @return array<int, array<string, string>>
     */
    public static function categoryCore(): array
    {
        return [
            ['value' => 'name', 'label' => __('Category name', 'cliq-store-locator')],
            ['value' => 'icon', 'label' => __('Icon', 'cliq-store-locator'), 'format' => 'media'],
            ['value' => 'count', 'label' => __('Store count', 'cliq-store-locator')],
        ];
    }

    /**
     * Distinct custom (meta) field keys present on stores, as content tokens.
     *
     * @return array<int, array<string, string>>
     */
    public static function customFromMeta(): array
    {
        global $wpdb;
        $keys = $wpdb->get_col(
            "SELECT DISTINCT meta_key FROM {$wpdb->prefix}cliq_sl_store_meta WHERE meta_key NOT IN ('hero_media', 'opening_hours', '_cliq_sl_demo_store') ORDER BY meta_key ASC"
        ) ?: [];

        return array_map(static function (string $key): array {
            return [
                'value' => $key,
                'label' => ucwords(str_replace('_', ' ', $key)),
                'format' => self::$customFormats[$key] ?? 'text',
                'source' => 'meta.' . $key,
            ];
        }, $keys);
    }
}
