<?php

namespace App\Support\Providers\TargetScope;

use App\Models\ProviderConnection;
use App\Support\Badges\BadgeDomain;
use App\Support\Badges\BadgeRenderer;
use App\Support\Providers\ProviderConsentStatus;
use App\Support\Providers\ProviderVerificationStatus;

final class ProviderConnectionSurfaceSummary
{
    /**
     * @param  list<ProviderIdentityContextMetadata>  $contextualIdentityDetails
     */
    public function __construct(
        public readonly string $provider,
        public readonly ProviderConnectionTargetScopeDescriptor $targetScope,
        public readonly string $consentState,
        public readonly string $verificationState,
        public readonly string $readinessSummary,
        public readonly array $contextualIdentityDetails = [],
    ) {}

    public static function forConnection(ProviderConnection $connection): self
    {
        /** @var ProviderConnectionTargetScopeNormalizer $normalizer */
        $normalizer = app(ProviderConnectionTargetScopeNormalizer::class);
        $targetScope = $normalizer->descriptorForConnection($connection);
        $consentState = self::stateValue($connection->consent_status);
        $verificationState = self::stateValue($connection->verification_status);

        return new self(
            provider: trim((string) $connection->provider),
            targetScope: $targetScope,
            consentState: $consentState,
            verificationState: $verificationState,
            readinessSummary: self::readinessSummary(
                isEnabled: (bool) $connection->is_enabled,
                consentState: $consentState,
                verificationState: $verificationState,
            ),
            contextualIdentityDetails: $normalizer->contextualIdentityDetailsForConnection($connection),
        );
    }

    public function targetScopeSummary(): string
    {
        return $this->targetScope->summary();
    }

    public function contextualIdentityLine(): ?string
    {
        if ($this->contextualIdentityDetails === []) {
            return null;
        }

        return collect($this->contextualIdentityDetails)
            ->map(fn (ProviderIdentityContextMetadata $detail): string => sprintf('%s: %s', $detail->detailLabel, $detail->detailValue))
            ->implode("\n");
    }

    /**
     * @return array{
     *     provider: string,
     *     target_scope: array<string, string>,
     *     consent_state: string,
     *     verification_state: string,
     *     readiness_summary: string,
     *     contextual_identity_details: list<array<string, string>>
     * }
     */
    public function toArray(): array
    {
        return [
            'provider' => $this->provider,
            'target_scope' => $this->targetScope->toArray(),
            'consent_state' => $this->consentState,
            'verification_state' => $this->verificationState,
            'readiness_summary' => $this->readinessSummary,
            'contextual_identity_details' => array_map(
                static fn (ProviderIdentityContextMetadata $detail): array => $detail->toArray(),
                $this->contextualIdentityDetails,
            ),
        ];
    }

    private static function stateValue(mixed $state): string
    {
        if ($state instanceof ProviderConsentStatus || $state instanceof ProviderVerificationStatus) {
            return $state->value;
        }

        return trim((string) $state);
    }

    private static function readinessSummary(bool $isEnabled, string $consentState, string $verificationState): string
    {
        if (! $isEnabled) {
            return 'Disabled';
        }

        if ($consentState !== ProviderConsentStatus::Granted->value) {
            return sprintf(
                'Consent %s',
                strtolower(BadgeRenderer::spec(BadgeDomain::ProviderConsentStatus, $consentState)->label),
            );
        }

        return match ($verificationState) {
            ProviderVerificationStatus::Healthy->value => 'Ready',
            ProviderVerificationStatus::Degraded->value => 'Ready with warnings',
            ProviderVerificationStatus::Blocked->value => 'Verification blocked',
            ProviderVerificationStatus::Error->value => 'Verification failed',
            ProviderVerificationStatus::Pending->value => 'Verification pending',
            default => 'Verification not run',
        };
    }
}
