<?php

declare(strict_types=1);

namespace App\Support\Governance\Controls;

final readonly class CanonicalControlResolutionResult
{
    /**
     * @param  list<string>  $candidateControlKeys
     */
    private function __construct(
        public string $status,
        public ?CanonicalControlDefinition $control,
        public ?string $reasonCode,
        public array $bindingContext,
        public array $candidateControlKeys = [],
    ) {}

    public static function resolved(CanonicalControlDefinition $definition): self
    {
        return new self(
            status: 'resolved',
            control: $definition,
            reasonCode: null,
            bindingContext: [],
        );
    }

    public static function unresolved(string $reasonCode, CanonicalControlResolutionRequest $request): self
    {
        return new self(
            status: 'unresolved',
            control: null,
            reasonCode: $reasonCode,
            bindingContext: $request->bindingContext(),
        );
    }

    /**
     * @param  list<string>  $candidateControlKeys
     */
    public static function ambiguous(array $candidateControlKeys, CanonicalControlResolutionRequest $request): self
    {
        sort($candidateControlKeys, SORT_STRING);

        return new self(
            status: 'ambiguous',
            control: null,
            reasonCode: 'ambiguous_binding',
            bindingContext: $request->bindingContext(),
            candidateControlKeys: array_values(array_unique($candidateControlKeys)),
        );
    }

    public function isResolved(): bool
    {
        return $this->status === 'resolved' && $this->control instanceof CanonicalControlDefinition;
    }

    /**
     * @return array<string, mixed>
     */
    public function toArray(): array
    {
        if ($this->isResolved()) {
            return [
                'status' => 'resolved',
                'control' => $this->control?->toArray(),
            ];
        }

        if ($this->status === 'ambiguous') {
            return [
                'status' => 'ambiguous',
                'reason_code' => $this->reasonCode,
                'candidate_control_keys' => $this->candidateControlKeys,
                'binding_context' => $this->bindingContext,
            ];
        }

        return [
            'status' => 'unresolved',
            'reason_code' => $this->reasonCode,
            'binding_context' => $this->bindingContext,
        ];
    }
}
