<?php
/**
 * Normalizes Bricks setting values for governance comparisons.
 *
 * @package LolaCoreForBricks
 */

declare(strict_types=1);

namespace LolaCoreForBricks\Governance;

/**
 * Makes equivalent Bricks values compare equal during duplicate detection.
 */
final class ValueNormalizer
{
    public static function normalize(mixed $value): string
    {
        if (is_bool($value)) {
            return $value ? 'true' : 'false';
        }

        if (is_int($value) || is_float($value)) {
            return self::normalizeScalar((string) $value);
        }

        if (!is_string($value)) {
            return wp_json_encode($value) ?: '';
        }

        return self::normalizeScalar($value);
    }

    private static function normalizeScalar(string $value): string
    {
        $value = trim($value);

        if ($value === '') {
            return '';
        }

        if (self::isZeroUnit($value)) {
            return '0';
        }

        if (preg_match('/^var\(\s*--\s*([a-zA-Z0-9_-]+)\s*\)$/i', $value, $matches) === 1) {
            return 'var(--' . $matches[1] . ')';
        }

        if (preg_match('/^#([0-9a-f]{3}|[0-9a-f]{6})$/i', $value, $matches) === 1) {
            return self::expandHexColor($matches[1]);
        }

        if (preg_match('/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i', $value, $matches) === 1) {
            return sprintf(
                '#%02x%02x%02x',
                (int) $matches[1],
                (int) $matches[2],
                (int) $matches[3]
            );
        }

        return $value;
    }

    private static function isZeroUnit(string $value): bool
    {
        return preg_match('/^0+(\.0+)?(px|em|rem|%|vh|vw|vmin|vmax|ch|ex)?$/i', $value) === 1;
    }

    private static function expandHexColor(string $hex): string
    {
        $hex = strtolower($hex);
        if (strlen($hex) === 3) {
            $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
        }

        return '#' . $hex;
    }
}
