<?php

declare(strict_types=1);

namespace App\Support\Ui\GovernanceArtifactTruth;

use App\Support\Badges\BadgeCatalog;
use App\Support\Badges\BadgeSpec;
use InvalidArgumentException;

final readonly class CompressedGovernanceOutcome
{
    /**
     * @param  list<array{
     *     label: string,
     *     value: string,
     *     badge: ?BadgeSpec
     * }>  $secondaryFacts
     */
    public function __construct(
        public string $surfaceFamily,
        public string $decisionDirection,
        public string $primaryLabel,
        public string $primaryReason,
        public string $nextActionText,
        public BadgeSpec $primaryBadge,
        public array $secondaryFacts = [],
        public bool $diagnosticsAvailable = false,
        public ?string $diagnosticsSummary = null,
    ) {
        if (trim($this->surfaceFamily) === '') {
            throw new InvalidArgumentException('Compressed governance outcomes require a surface family.');
        }

        if (! in_array($this->decisionDirection, [
            'usable',
            'publishable',
            'internal_only',
            'stale',
            'blocked',
            'follow_up_needed',
            'historical_only',
        ], true)) {
            throw new InvalidArgumentException(sprintf('Unsupported compressed governance decision direction [%s].', $this->decisionDirection));
        }

        if (trim($this->primaryLabel) === '') {
            throw new InvalidArgumentException('Compressed governance outcomes require a primary label.');
        }

        if (trim($this->primaryReason) === '') {
            throw new InvalidArgumentException('Compressed governance outcomes require a primary reason.');
        }

        if (trim($this->nextActionText) === '') {
            throw new InvalidArgumentException('Compressed governance outcomes require a next action.');
        }
    }

    /**
     * @return array{
     *     surfaceFamily: string,
     *     decisionDirection: string,
     *     primaryLabel: string,
     *     primaryReason: string,
     *     nextActionText: string,
     *     primaryBadge: array{label: string, color: ?string, icon: ?string, iconColor: ?string},
     *     secondaryFacts: list<array{
     *         label: string,
     *         value: string,
     *         badge: ?array{label: string, color: ?string, icon: ?string, iconColor: ?string}
     *     }>,
     *     diagnosticsAvailable: bool,
     *     diagnosticsSummary: ?string
     * }
     */
    public function toArray(): array
    {
        return [
            'surfaceFamily' => $this->surfaceFamily,
            'decisionDirection' => $this->decisionDirection,
            'primaryLabel' => $this->primaryLabel,
            'primaryReason' => $this->primaryReason,
            'nextActionText' => $this->nextActionText,
            'primaryBadge' => BadgeCatalog::summaryData($this->primaryBadge),
            'secondaryFacts' => array_values(array_map(
                static fn (array $fact): array => [
                    'label' => $fact['label'],
                    'value' => $fact['value'],
                    'badge' => $fact['badge'] instanceof BadgeSpec
                        ? BadgeCatalog::summaryData($fact['badge'])
                        : null,
                ],
                $this->secondaryFacts,
            )),
            'diagnosticsAvailable' => $this->diagnosticsAvailable,
            'diagnosticsSummary' => $this->diagnosticsSummary,
        ];
    }
}
