<?php

declare(strict_types=1);

namespace CliqThemes\StoreLocator\Support;

defined('ABSPATH') || exit;

/**
 * Builds and resolves the public store-detail route slug.
 *
 * The database slug remains an editable, backwards-compatible identifier.
 * Public detail URLs use the ordered core fields configured in settings.
 */
final class StoreDetailUrl
{
    /**
     * @param array<string, mixed>      $store
     * @param array<string, mixed>|null $location
     */
    public static function slug(array $store, ?array $location = null): string
    {
        $fields = SettingsService::get('store_detail_slug_fields', ['city', 'name']);
        if (! is_array($fields) || $fields === []) {
            $fields = ['city', 'name'];
        }

        $parts = [];
        foreach ($fields as $field) {
            if (! is_string($field)) {
                continue;
            }

            $value = match ($field) {
                'name' => $store['name'] ?? '',
                'city' => $location['city'] ?? $store['city'] ?? '',
                'state' => $location['state'] ?? $store['state'] ?? '',
                'postal_code' => $location['postal_code'] ?? $store['postal_code'] ?? '',
                'country' => $location['country'] ?? $store['country'] ?? '',
                default => '',
            };
            $value = trim((string) $value);
            if ($value !== '') {
                $parts[] = $value;
            }
        }

        $slug = sanitize_title(implode('-', $parts));
        if ($slug !== '') {
            return $slug;
        }

        return sanitize_title((string) ($store['slug'] ?? ''));
    }

    /**
     * Resolve a configured route slug to its canonical store id.
     *
     * This path runs only on a single-store detail request. It deliberately
     * loads the small URL-source projection rather than full store payloads.
     */
    public static function resolveStoreId(string $routeSlug): ?int
    {
        $routeSlug = sanitize_title($routeSlug);
        if ($routeSlug === '') {
            return null;
        }

        global $wpdb;

        $stores = $wpdb->prefix . 'cliq_sl_stores';
        $locations = $wpdb->prefix . 'cliq_sl_store_locations';
        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Identifiers are escaped by %i.
        $sql = $wpdb->prepare(
            'SELECT s.id, s.name, s.slug, s.city, s.country,
                    l.city AS location_city, l.state, l.postal_code, l.country AS location_country
             FROM %i s
             LEFT JOIN %i l ON l.store_id = s.id AND l.is_primary = 1
             WHERE s.source_id IS NULL AND s.deleted_at IS NULL
             ORDER BY s.id ASC',
            $stores,
            $locations
        );
        $cacheKey = 'detail_url_sources_v1';
        $rows = wp_cache_get($cacheKey, 'cliq_store_locator');
        if (! is_array($rows)) {
            // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery -- Prepared custom-table query; result is cached immediately below.
            $rows = $wpdb->get_results($sql, ARRAY_A) ?: [];
            wp_cache_set($cacheKey, $rows, 'cliq_store_locator', 5 * MINUTE_IN_SECONDS);
        }

        foreach ($rows as $row) {
            $candidate = self::slug(
                [
                    'name' => $row['name'] ?? '',
                    'slug' => $row['slug'] ?? '',
                    'city' => $row['city'] ?? '',
                    'country' => $row['country'] ?? '',
                ],
                [
                    'city' => $row['location_city'] ?? '',
                    'state' => $row['state'] ?? '',
                    'postal_code' => $row['postal_code'] ?? '',
                    'country' => $row['location_country'] ?? '',
                ]
            );
            if ($candidate === $routeSlug) {
                return (int) ($row['id'] ?? 0) ?: null;
            }
        }

        return null;
    }
}
