<?php

namespace App\Services\Drift\Normalizers;

class ScopeTagsNormalizer
{
    /**
     * @return array<int, string>
     */
    public function normalizeIds(mixed $scopeTags): array
    {
        return $this->normalizeIdsForHash($scopeTags) ?? [];
    }

    /**
     * For drift hashing/comparison we need stable, reliable IDs.
     *
     * Legacy policy versions may have only `names` without `ids`. In that case we:
     * - infer `Default` as id `0`
     * - otherwise return null (unknown/unreliable; should not create drift)
     *
     * @return array<int, string>|null
     */
    public function normalizeIdsForHash(mixed $scopeTags): ?array
    {
        if (! is_array($scopeTags)) {
            return [];
        }

        $ids = $scopeTags['ids'] ?? null;
        if (is_array($ids)) {
            $normalized = [];

            foreach ($ids as $id) {
                if (! is_string($id)) {
                    continue;
                }

                $id = trim($id);

                if ($id === '') {
                    continue;
                }

                $normalized[] = $id;
            }

            $normalized = array_values(array_unique($normalized));
            sort($normalized);

            return $normalized;
        }

        $names = $scopeTags['names'] ?? null;
        if (! is_array($names) || $names === []) {
            return [];
        }

        $normalizedNames = [];

        foreach ($names as $name) {
            if (! is_string($name)) {
                continue;
            }

            $name = trim($name);

            if ($name === '') {
                continue;
            }

            $normalizedNames[] = strtolower($name);
        }

        $normalizedNames = array_values(array_unique($normalizedNames));
        sort($normalizedNames);

        if ($normalizedNames === ['default']) {
            return ['0'];
        }

        return null;
    }

    /**
     * @return array<string, string>
     */
    public function labelsById(mixed $scopeTags): array
    {
        if (! is_array($scopeTags)) {
            return [];
        }

        $ids = is_array($scopeTags['ids'] ?? null) ? $scopeTags['ids'] : null;
        $names = is_array($scopeTags['names'] ?? null) ? $scopeTags['names'] : [];

        if (! is_array($ids)) {
            $inferred = $this->normalizeIdsForHash($scopeTags);

            if ($inferred === ['0'] && $names !== []) {
                return ['0' => 'Default'];
            }

            return [];
        }

        $labels = [];

        foreach ($ids as $index => $id) {
            if (! is_string($id)) {
                continue;
            }

            $id = trim($id);

            if ($id === '') {
                continue;
            }

            $name = $names[$index] ?? '';
            $name = is_string($name) ? trim($name) : '';

            if ($name === '') {
                $name = $id === '0' ? 'Default' : $id;
            }

            if (! array_key_exists($id, $labels) || $labels[$id] === $id) {
                $labels[$id] = $name;
            }
        }

        ksort($labels);

        return $labels;
    }
}
