<?php

declare(strict_types=1);

namespace App\Support\Ui\OperatorExplanation;

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

final readonly class OperatorExplanationPattern
{
    /**
     * @param  array<int, CountDescriptor>  $countDescriptors
     */
    public function __construct(
        public ExplanationFamily $family,
        public string $headline,
        public string $executionOutcome,
        public string $executionOutcomeLabel,
        public string $evaluationResult,
        public TrustworthinessLevel $trustworthinessLevel,
        public string $reliabilityStatement,
        public ?string $coverageStatement,
        public ?string $dominantCauseCode,
        public ?string $dominantCauseLabel,
        public ?string $dominantCauseExplanation,
        public string $nextActionCategory,
        public string $nextActionText,
        public array $countDescriptors = [],
        public bool $diagnosticsAvailable = false,
        public ?string $diagnosticsSummary = null,
    ) {
        if (trim($this->headline) === '') {
            throw new InvalidArgumentException('Operator explanation patterns require a headline.');
        }

        if (trim($this->executionOutcome) === '' || trim($this->executionOutcomeLabel) === '') {
            throw new InvalidArgumentException('Operator explanation patterns require an execution outcome and label.');
        }

        if (trim($this->evaluationResult) === '') {
            throw new InvalidArgumentException('Operator explanation patterns require an evaluation result state.');
        }

        if (trim($this->reliabilityStatement) === '') {
            throw new InvalidArgumentException('Operator explanation patterns require a reliability statement.');
        }

        if (trim($this->nextActionCategory) === '' || trim($this->nextActionText) === '') {
            throw new InvalidArgumentException('Operator explanation patterns require a next action category and text.');
        }

        foreach ($this->countDescriptors as $descriptor) {
            if (! $descriptor instanceof CountDescriptor) {
                throw new InvalidArgumentException('Operator explanation count descriptors must contain CountDescriptor instances.');
            }
        }
    }

    public function evaluationResultLabel(): string
    {
        return BadgeCatalog::spec(BadgeDomain::OperatorExplanationEvaluationResult, $this->evaluationResult)->label;
    }

    public function trustworthinessLabel(): string
    {
        return BadgeCatalog::spec(BadgeDomain::OperatorExplanationTrustworthiness, $this->trustworthinessLevel)->label;
    }

    /**
     * @return array{
     *     family: string,
     *     headline: string,
     *     executionOutcome: string,
     *     executionOutcomeLabel: string,
     *     evaluationResult: string,
     *     evaluationResultLabel: string,
     *     trustworthinessLevel: string,
     *     reliabilityLevel: string,
     *     trustworthinessLabel: string,
     *     reliabilityStatement: string,
     *     coverageStatement: ?string,
     *     dominantCause: array{
     *         code: ?string,
     *         label: ?string,
     *         explanation: ?string
     *     },
     *     nextAction: array{
     *         category: string,
     *         text: string
     *     },
     *     countDescriptors: array<int, array{
     *         label: string,
     *         value: int,
     *         role: string,
     *         qualifier: ?string,
     *         visibilityTier: string
     *     }>,
     *     diagnosticsAvailable: bool,
     *     diagnosticsSummary: ?string
     * }
     */
    public function toArray(): array
    {
        return [
            'family' => $this->family->value,
            'headline' => $this->headline,
            'executionOutcome' => $this->executionOutcome,
            'executionOutcomeLabel' => $this->executionOutcomeLabel,
            'evaluationResult' => $this->evaluationResult,
            'evaluationResultLabel' => $this->evaluationResultLabel(),
            'trustworthinessLevel' => $this->trustworthinessLevel->value,
            'reliabilityLevel' => $this->trustworthinessLevel->value,
            'trustworthinessLabel' => $this->trustworthinessLabel(),
            'reliabilityStatement' => $this->reliabilityStatement,
            'coverageStatement' => $this->coverageStatement,
            'dominantCause' => [
                'code' => $this->dominantCauseCode,
                'label' => $this->dominantCauseLabel,
                'explanation' => $this->dominantCauseExplanation,
            ],
            'nextAction' => [
                'category' => $this->nextActionCategory,
                'text' => $this->nextActionText,
            ],
            'countDescriptors' => array_map(
                static fn (CountDescriptor $descriptor): array => $descriptor->toArray(),
                $this->countDescriptors,
            ),
            'diagnosticsAvailable' => $this->diagnosticsAvailable,
            'diagnosticsSummary' => $this->diagnosticsSummary,
        ];
    }
}
