<?php

namespace Mtc\Plugins\BlockManager\Services;

/**
 * Read-only parser for sites/default/css/variables.less.
 *
 * Returns each `@name: value;` declaration tagged with a `type`
 * (color / length / reference / other) so the Designer view's property
 * panels can present typed token pickers without re-parsing client-side.
 *
 * Per scope §"Designer / Tokens are read-only" — this service NEVER writes.
 */
class DesignTokenService
{
    private string $variablesPath;

    /** @var array<int, array{name: string, type: string, value: string}>|null */
    private ?array $cache = null;

    public function __construct(?string $variablesPath = null)
    {
        $this->variablesPath = $variablesPath
            ?? base_path('sites/default/css/variables.less');
    }

    /**
     * @return array<int, array{name: string, type: string, value: string}>
     */
    public function list(): array
    {
        if ($this->cache !== null) {
            return $this->cache;
        }
        if (!is_file($this->variablesPath)) {
            return $this->cache = [];
        }

        $raw = (string) file_get_contents($this->variablesPath);

        // Strip block comments first (multi-line aware), then line comments.
        $stripped = preg_replace('#/\*.*?\*/#s', '', $raw) ?? '';
        $stripped = preg_replace('#//[^\n]*#', '', $stripped) ?? '';

        $taken = []; // name => entry; last-write-wins for re-declarations
        preg_match_all(
            '/(@[a-zA-Z_][\w-]*)\s*:\s*([^;]+);/',
            $stripped,
            $matches,
            PREG_SET_ORDER
        );
        foreach ($matches as $m) {
            $name = trim($m[1]);
            $value = trim($m[2]);
            $taken[$name] = [
                'name'  => $name,
                'type'  => $this->classify($value),
                'value' => $value,
            ];
        }

        return $this->cache = array_values($taken);
    }

    /**
     * @return array{name: string, type: string, value: string}|null
     */
    public function get(string $name): ?array
    {
        foreach ($this->list() as $token) {
            if ($token['name'] === $name) {
                return $token;
            }
        }
        return null;
    }

    private function classify(string $value): string
    {
        if (preg_match('/^#[0-9a-fA-F]{3,8}$/', $value)) {
            return 'color';
        }
        if (preg_match('/^(rgb|rgba|hsl|hsla|hsv|color-mix|color|oklch|oklab|lab|lch)\s*\(/i', $value)) {
            return 'color';
        }
        if (preg_match('/^-?\d+(\.\d+)?(px|em|rem|%|vh|vw|vmin|vmax|ch|ex|fr|pt|pc|cm|mm|in)$/i', $value)) {
            return 'length';
        }
        if (preg_match('/^-?\d+(\.\d+)?$/', $value)) {
            return 'length';
        }
        if (preg_match('/^@[a-zA-Z_][\w-]*$/', $value)) {
            return 'reference';
        }
        return 'other';
    }
}
