<?php

namespace App\Services\Providers;

use App\Models\ProviderConnection;
use App\Support\Providers\ProviderReasonCodes;
use App\Support\Providers\TargetScope\ProviderConnectionTargetScopeDescriptor;
use App\Support\Providers\TargetScope\ProviderConnectionTargetScopeNormalizer;
use App\Support\Providers\TargetScope\ProviderIdentityContextMetadata;

final class ProviderConnectionResolution
{
    /**
     * @param  list<ProviderIdentityContextMetadata>  $contextualIdentityDetails
     */
    private function __construct(
        public readonly bool $resolved,
        public readonly ?ProviderConnection $connection,
        public readonly ?string $reasonCode,
        public readonly ?string $extensionReasonCode,
        public readonly ?string $message,
        public readonly ?ProviderConnectionTargetScopeDescriptor $targetScope,
        public readonly array $contextualIdentityDetails,
    ) {}

    public static function resolved(ProviderConnection $connection): self
    {
        /** @var ProviderConnectionTargetScopeNormalizer $normalizer */
        $normalizer = app(ProviderConnectionTargetScopeNormalizer::class);

        return new self(
            resolved: true,
            connection: $connection,
            reasonCode: null,
            extensionReasonCode: null,
            message: null,
            targetScope: $normalizer->descriptorForConnection($connection),
            contextualIdentityDetails: $normalizer->contextualIdentityDetailsForConnection($connection),
        );
    }

    public static function blocked(
        string $reasonCode,
        ?string $message = null,
        ?string $extensionReasonCode = null,
        ?ProviderConnection $connection = null,
    ): self {
        /** @var ProviderConnectionTargetScopeNormalizer $normalizer */
        $normalizer = app(ProviderConnectionTargetScopeNormalizer::class);
        $targetScope = null;
        $contextualIdentityDetails = [];

        if ($connection instanceof ProviderConnection) {
            $normalization = $normalizer->normalizeConnection($connection);
            $descriptor = $normalization['target_scope'] ?? null;

            if ($descriptor instanceof ProviderConnectionTargetScopeDescriptor) {
                $targetScope = $descriptor;
                $contextualIdentityDetails = $normalizer->contextualIdentityDetailsForConnection($connection);
            }
        }

        return new self(
            resolved: false,
            connection: $connection,
            reasonCode: ProviderReasonCodes::isKnown($reasonCode) ? $reasonCode : ProviderReasonCodes::UnknownError,
            extensionReasonCode: $extensionReasonCode,
            message: $message,
            targetScope: $targetScope,
            contextualIdentityDetails: $contextualIdentityDetails,
        );
    }

    public function effectiveReasonCode(): string
    {
        return $this->reasonCode ?? ProviderReasonCodes::UnknownError;
    }
}
