<?php

declare(strict_types=1);

namespace App\Support\Ui\GovernanceArtifactTruth;

use App\Support\Badges\BadgeSpec;
use App\Support\Ui\OperatorExplanation\OperatorExplanationPattern;

final readonly class ArtifactTruthEnvelope
{
    /**
     * @param  array<int, ArtifactTruthDimension>  $dimensions
     */
    public function __construct(
        public string $artifactFamily,
        public string $artifactKey,
        public int $workspaceId,
        public ?int $tenantId,
        public ?string $executionOutcome,
        public string $artifactExistence,
        public string $contentState,
        public string $freshnessState,
        public ?string $publicationReadiness,
        public string $supportState,
        public string $actionability,
        public string $primaryLabel,
        public ?string $primaryExplanation,
        public ?string $diagnosticLabel,
        public ?string $nextActionLabel,
        public ?string $nextActionUrl,
        public ?int $relatedRunId,
        public ?string $relatedArtifactUrl,
        public array $dimensions = [],
        public ?ArtifactTruthCause $reason = null,
        public ?OperatorExplanationPattern $operatorExplanation = null,
        public ?string $displayReference = null,
        public ?string $integrityAnchor = null,
        public ?string $lifecycleState = null,
        public ?string $retentionState = null,
    ) {}

    public function primaryDimension(): ?ArtifactTruthDimension
    {
        foreach ($this->dimensions as $dimension) {
            if ($dimension instanceof ArtifactTruthDimension && $dimension->isPrimary()) {
                return $dimension;
            }
        }

        return null;
    }

    public function primaryBadgeSpec(): BadgeSpec
    {
        $dimension = $this->primaryDimension();

        return $dimension?->badgeSpec() ?? \App\Support\Badges\BadgeSpec::unknown();
    }

    public function nextStepText(): string
    {
        if (is_string($this->nextActionLabel) && trim($this->nextActionLabel) !== '') {
            return $this->nextActionLabel;
        }

        return match ($this->actionability) {
            'none' => 'No action needed',
            'optional' => 'Review recommended',
            default => 'Action required',
        };
    }

    /**
     * @return array{
     *     artifactFamily: string,
     *     artifactKey: string,
     *     workspaceId: int,
     *     tenantId: ?int,
     *     executionOutcome: ?string,
     *     artifactExistence: string,
     *     contentState: string,
     *     freshnessState: string,
     *     publicationReadiness: ?string,
     *     supportState: string,
     *     actionability: string,
     *     primaryLabel: string,
     *     primaryExplanation: ?string,
     *     diagnosticLabel: ?string,
     *     nextActionLabel: ?string,
     *     nextActionUrl: ?string,
     *     relatedRunId: ?int,
     *     relatedArtifactUrl: ?string,
    *     displayReference: ?string,
    *     integrityAnchor: ?string,
    *     lifecycleState: ?string,
    *     retentionState: ?string,
     *     dimensions: array<int, array{
     *         axis: string,
     *         state: string,
     *         label: string,
     *         classification: string,
     *         badgeDomain: ?string,
     *         badgeState: ?string
     *     }>,
     *     reason: ?array{
     *         reasonCode: ?string,
     *         translationArtifact: ?string,
     *         operatorLabel: ?string,
     *         shortExplanation: ?string,
     *         diagnosticCode: ?string,
     *         trustImpact: string,
     *         absencePattern: ?string,
     *         nextSteps: array<int, string>
     *     },
     *     operatorExplanation: ?array<string, mixed>,
     *     compressedOutcome: ?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(?CompressedGovernanceOutcome $compressedOutcome = null): array
    {
        return [
            'artifactFamily' => $this->artifactFamily,
            'artifactKey' => $this->artifactKey,
            'workspaceId' => $this->workspaceId,
            'tenantId' => $this->tenantId,
            'executionOutcome' => $this->executionOutcome,
            'artifactExistence' => $this->artifactExistence,
            'contentState' => $this->contentState,
            'freshnessState' => $this->freshnessState,
            'publicationReadiness' => $this->publicationReadiness,
            'supportState' => $this->supportState,
            'actionability' => $this->actionability,
            'primaryLabel' => $this->primaryLabel,
            'primaryExplanation' => $this->primaryExplanation,
            'diagnosticLabel' => $this->diagnosticLabel,
            'nextActionLabel' => $this->nextActionLabel,
            'nextActionUrl' => $this->nextActionUrl,
            'relatedRunId' => $this->relatedRunId,
            'relatedArtifactUrl' => $this->relatedArtifactUrl,
            'displayReference' => $this->displayReference,
            'integrityAnchor' => $this->integrityAnchor,
            'lifecycleState' => $this->lifecycleState,
            'retentionState' => $this->retentionState,
            'dimensions' => array_values(array_map(
                static fn (ArtifactTruthDimension $dimension): array => $dimension->toArray(),
                array_filter(
                    $this->dimensions,
                    static fn (mixed $dimension): bool => $dimension instanceof ArtifactTruthDimension,
                ),
            )),
            'reason' => $this->reason?->toArray(),
            'operatorExplanation' => $this->operatorExplanation?->toArray(),
            'compressedOutcome' => $compressedOutcome?->toArray(),
        ];
    }
}
