<?php
declare(strict_types=1);

/** Workflow tags for tickets (must include exactly one meta tag: ticket or issue). */
final class TicketTagCatalog {
    public const META_ID = 'ticket';

    /** @var list<string> */
    public const META_IDS = ['ticket', 'issue'];

    /** @var array<string, array{label:string,bg:string}> */
    private const META = [
        'ticket' => ['label' => 'ticket', 'bg' => '#6366f1'],
        'issue' => ['label' => 'issue', 'bg' => '#0d9488'],
    ];

    /** @var array<string, array{label:string,bg:string}> */
    private const STATUS = [
        'open' => ['label' => 'open', 'bg' => '#22c55e'],
        'in-progress' => ['label' => 'in progress', 'bg' => '#3b82f6'],
        'blocked' => ['label' => 'blocked', 'bg' => '#b45309'],
        'wont-fix' => ['label' => "won't fix", 'bg' => '#6b7280'],
        'closed' => ['label' => 'closed', 'bg' => '#6b7280'],
        'rejected' => ['label' => 'rejected', 'bg' => '#b91c1c'],
        'confirmed' => ['label' => 'confirmed', 'bg' => '#047857'],
        'postponed' => ['label' => 'postponed', 'bg' => '#a16207'],
        'urgent' => ['label' => 'urgent', 'bg' => '#dc2626'],
    ];

    /** @return list<string> */
    public static function statusIds(): array {
        return array_keys(self::STATUS);
    }

    /** @return list<array{id:string,label:string,bg:string}> */
    public static function presets(): array {
        $out = [];
        foreach (self::META as $id => $def) {
            $out[] = ['id' => $id, 'label' => $def['label'], 'bg' => $def['bg']];
        }
        foreach (self::STATUS as $id => $def) {
            $out[] = ['id' => $id, 'label' => $def['label'], 'bg' => $def['bg']];
        }
        return $out;
    }

    public static function isMetaId(string $id): bool {
        return isset(self::META[$id]);
    }

    /**
     * @param list<mixed> $tags
     * @return list<array{id:string,label:string,bg:string}>
     */
    public static function normalize(array $tags): array {
        $normalized = normalize_report_tags($tags);
        $metaId = null;
        $hasStatus = false;
        $rest = [];
        foreach ($normalized as $t) {
            if (self::isMetaId($t['id'])) {
                $metaId = $t['id'];
                continue;
            }
            if (isset(self::STATUS[$t['id']])) {
                $hasStatus = true;
            }
            $rest[] = $t;
        }
        if ($metaId === null) {
            $metaId = self::META_ID;
        }
        $meta = self::META[$metaId];
        $out = [
            ['id' => $metaId, 'label' => $meta['label'], 'bg' => $meta['bg']],
        ];
        foreach ($rest as $t) {
            $out[] = $t;
        }
        if (!$hasStatus) {
            $out[] = ['id' => 'open', 'label' => 'open', 'bg' => '#22c55e'];
        }
        return $out;
    }

    public static function validate(array $tags): ?string {
        $normalized = normalize_report_tags($tags);
        $metaCount = 0;
        $hasStatus = false;
        foreach ($normalized as $t) {
            if (self::isMetaId($t['id'])) {
                $metaCount++;
            }
            if (isset(self::STATUS[$t['id']])) {
                $hasStatus = true;
            }
        }
        if ($metaCount === 0) {
            return 'tags must include a type tag (ticket or issue)';
        }
        if ($metaCount > 1) {
            return 'only one type tag allowed: ticket or issue';
        }
        if (!$hasStatus) {
            return 'tags must include a status tag (open, in-progress, closed, …)';
        }
        return null;
    }
}
