<?php

namespace App\Support\Providers\TargetScope;

use App\Models\ProviderConnection;
use InvalidArgumentException;

final class ProviderConnectionTargetScopeDescriptor
{
    public const string SCOPE_KIND_TENANT = 'tenant';

    public function __construct(
        public readonly string $provider,
        public readonly string $scopeKind,
        public readonly string $scopeIdentifier,
        public readonly string $scopeDisplayName,
        public readonly string $sharedLabel = 'Target scope',
        public readonly string $sharedHelpText = 'The platform scope this provider connection represents.',
    ) {
        $this->validate();
    }

    public static function fromConnection(ProviderConnection $connection): self
    {
        $tenantName = is_string($connection->tenant?->name) && trim($connection->tenant->name) !== ''
            ? trim($connection->tenant->name)
            : trim((string) $connection->display_name);
        $scopeIdentifier = trim((string) $connection->entra_tenant_id);

        if ($scopeIdentifier === '') {
            $scopeIdentifier = trim((string) $connection->tenant?->providerTenantContext());
        }

        return new self(
            provider: trim((string) $connection->provider),
            scopeKind: self::SCOPE_KIND_TENANT,
            scopeIdentifier: $scopeIdentifier,
            scopeDisplayName: $tenantName !== '' ? $tenantName : $scopeIdentifier,
        );
    }

    public static function fromInput(
        string $provider,
        string $scopeKind,
        string $scopeIdentifier,
        ?string $scopeDisplayName = null,
    ): self {
        $scopeIdentifier = trim($scopeIdentifier);
        $displayName = trim((string) $scopeDisplayName);

        return new self(
            provider: trim($provider),
            scopeKind: trim($scopeKind),
            scopeIdentifier: $scopeIdentifier,
            scopeDisplayName: $displayName !== '' ? $displayName : $scopeIdentifier,
        );
    }

    public function summary(): string
    {
        if ($this->scopeDisplayName !== '' && $this->scopeDisplayName !== $this->scopeIdentifier) {
            return sprintf('%s (%s)', $this->scopeDisplayName, $this->scopeIdentifier);
        }

        return $this->scopeIdentifier;
    }

    /**
     * @return array{
     *     provider: string,
     *     scope_kind: string,
     *     scope_identifier: string,
     *     scope_display_name: string,
     *     shared_label: string,
     *     shared_help_text: string
     * }
     */
    public function toArray(): array
    {
        return [
            'provider' => $this->provider,
            'scope_kind' => $this->scopeKind,
            'scope_identifier' => $this->scopeIdentifier,
            'scope_display_name' => $this->scopeDisplayName,
            'shared_label' => $this->sharedLabel,
            'shared_help_text' => $this->sharedHelpText,
        ];
    }

    private function validate(): void
    {
        if ($this->provider === '') {
            throw new InvalidArgumentException('Provider is required for target-scope descriptors.');
        }

        if ($this->scopeKind !== self::SCOPE_KIND_TENANT) {
            throw new InvalidArgumentException('Unsupported provider connection target-scope kind.');
        }

        if ($this->scopeIdentifier === '') {
            throw new InvalidArgumentException('Target scope identifier is required.');
        }

        if ($this->scopeDisplayName === '') {
            throw new InvalidArgumentException('Target scope display name is required.');
        }
    }
}
