<?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\Runtime;

defined('ABSPATH') || exit;

class RuntimeFontMapper
{
    public function buildRuntimeConfig(array $fonts) : array
    {
        $runtime = [
            'system' => [],
            'google' => [],
            'custom' => [],
        ];

        foreach ($fonts as $font) {
            if (! is_array($font)) {
                continue;
            }

            $family = sanitize_text_field((string) ($font['family'] ?? $font['label'] ?? $font['name'] ?? ''));
            if ($family === '') {
                continue;
            }

            $source = sanitize_key((string) ($font['source'] ?? 'system'));
            if (! in_array($source, ['system', 'google', 'custom'], true)) {
                $source = 'system';
            }

            $id = sanitize_key((string) ($font['id'] ?? ''));
            if ($id === '') {
                $id = sanitize_title($family);
            }

            $base = [
                'id' => $id,
                'family' => $family,
            ];

            if ($source === 'google') {
                $item = $base;
                $cssUrl = esc_url_raw((string) ($font['cssUrl'] ?? ''));
                if ($cssUrl !== '') {
                    $item['cssUrl'] = $cssUrl;
                }
                $weights = $this->normalizeStringList($font['weights'] ?? []);
                if ($weights !== []) {
                    $item['weights'] = $weights;
                }
                $styles = array_values(array_filter($this->normalizeStringList($font['styles'] ?? []), static fn($style) => in_array($style, ['normal', 'italic'], true)));
                if ($styles !== []) {
                    $item['styles'] = $styles;
                }
                $runtime['google'][] = $item;
                continue;
            }

            if ($source === 'custom') {
                $item = $base;
                $url = esc_url_raw((string) ($font['url'] ?? $font['fileUrl'] ?? ''));
                $cssUrl = esc_url_raw((string) ($font['cssUrl'] ?? ''));
                if ($url !== '') {
                    $item['url'] = $url;
                    $format = sanitize_key((string) ($font['format'] ?? pathinfo((string) wp_parse_url($url, PHP_URL_PATH), PATHINFO_EXTENSION)));
                    if (in_array($format, ['woff2', 'woff', 'ttf', 'otf'], true)) {
                        $item['format'] = $format;
                    }
                }
                if ($cssUrl !== '') {
                    $item['cssUrl'] = $cssUrl;
                }
                if (isset($font['weight']) && $font['weight'] !== '') {
                    $item['weight'] = is_numeric($font['weight']) ? (int) $font['weight'] : sanitize_text_field((string) $font['weight']);
                }
                $style = sanitize_key((string) ($font['style'] ?? ''));
                if (in_array($style, ['normal', 'italic'], true)) {
                    $item['style'] = $style;
                }
                if ($url !== '' || $cssUrl !== '') {
                    $runtime['custom'][] = $item;
                } else {
                    $runtime['system'][] = $base;
                }
                continue;
            }

            $runtime['system'][] = $base;
        }

        return [
            'system' => $this->dedupeRuntimeItems($runtime['system']),
            'google' => $this->dedupeRuntimeItems($runtime['google']),
            'custom' => $this->dedupeRuntimeItems($runtime['custom']),
        ];
    }

    private function normalizeStringList(mixed $value) : array
    {
        if (is_string($value)) {
            $value = preg_split('/[\s,]+/', trim($value));
        }
        if (! is_array($value)) {
            return [];
        }

        $items = [];
        foreach ($value as $item) {
            $item = sanitize_text_field((string) $item);
            if ($item !== '') {
                $items[] = $item;
            }
        }

        return array_values(array_unique($items));
    }

    private function dedupeRuntimeItems(array $items) : array
    {
        $indexed = [];
        foreach ($items as $item) {
            if (! is_array($item)) {
                continue;
            }
            $id = sanitize_key((string) ($item['id'] ?? ''));
            if ($id === '') {
                $indexed[] = $item;
                continue;
            }
            $indexed[$id] = isset($indexed[$id]) && is_array($indexed[$id]) ? array_replace($indexed[$id], $item) : $item;
        }

        return array_values($indexed);
    }
}
