<?php

namespace App\Services\Providers;

use App\Models\ProviderConnection;
use App\Models\ProviderCredential;
use App\Models\Tenant;
use App\Support\Providers\ProviderReasonCodes;

final class ProviderConnectionResolver
{
    public function resolveDefault(Tenant $tenant, string $provider): ProviderConnectionResolution
    {
        $defaults = ProviderConnection::query()
            ->where('tenant_id', (int) $tenant->getKey())
            ->where('provider', $provider)
            ->where('is_default', true)
            ->orderBy('id')
            ->get();

        if ($defaults->count() === 0) {
            return ProviderConnectionResolution::blocked(
                ProviderReasonCodes::ProviderConnectionMissing,
                'No default provider connection is configured for this tenant/provider.',
            );
        }

        if ($defaults->count() > 1) {
            return ProviderConnectionResolution::blocked(
                ProviderReasonCodes::ProviderConnectionInvalid,
                'Multiple default provider connections were detected.',
                'ext.multiple_defaults_detected',
            );
        }

        /** @var ProviderConnection $connection */
        $connection = $defaults->first();

        return $this->validateConnection($tenant, $provider, $connection);
    }

    public function validateConnection(Tenant $tenant, string $provider, ProviderConnection $connection): ProviderConnectionResolution
    {
        if ((int) $connection->tenant_id !== (int) $tenant->getKey() || (string) $connection->provider !== $provider) {
            return ProviderConnectionResolution::blocked(
                ProviderReasonCodes::ProviderConnectionInvalid,
                'Provider connection does not match tenant/provider scope.',
                'ext.connection_scope_mismatch',
                $connection,
            );
        }

        if ((string) $connection->status === 'disabled') {
            return ProviderConnectionResolution::blocked(
                ProviderReasonCodes::ProviderConnectionInvalid,
                'Provider connection is disabled.',
                'ext.connection_disabled',
                $connection,
            );
        }

        if ((string) $connection->status === 'needs_consent') {
            return ProviderConnectionResolution::blocked(
                ProviderReasonCodes::ProviderConsentMissing,
                'Provider connection requires admin consent before use.',
                'ext.connection_needs_consent',
                $connection,
            );
        }

        if ($connection->entra_tenant_id === null || trim((string) $connection->entra_tenant_id) === '') {
            return ProviderConnectionResolution::blocked(
                ProviderReasonCodes::ProviderConnectionInvalid,
                'Provider connection is missing target tenant scope.',
                'ext.connection_tenant_missing',
                $connection,
            );
        }

        $credential = $connection->credential()->first();

        if (! $credential instanceof ProviderCredential) {
            return ProviderConnectionResolution::blocked(
                ProviderReasonCodes::ProviderCredentialMissing,
                'Provider connection is missing credentials.',
                connection: $connection,
            );
        }

        if ($credential->type !== 'client_secret') {
            return ProviderConnectionResolution::blocked(
                ProviderReasonCodes::ProviderCredentialInvalid,
                'Provider credential type is invalid.',
                'ext.invalid_credential_type',
                $connection,
            );
        }

        $payload = $credential->payload;

        if (! is_array($payload)) {
            return ProviderConnectionResolution::blocked(
                ProviderReasonCodes::ProviderCredentialInvalid,
                'Provider credential payload is invalid.',
                'ext.invalid_credential_payload',
                $connection,
            );
        }

        $clientId = trim((string) ($payload['client_id'] ?? ''));
        $clientSecret = trim((string) ($payload['client_secret'] ?? ''));

        if ($clientId === '' || $clientSecret === '') {
            return ProviderConnectionResolution::blocked(
                ProviderReasonCodes::ProviderCredentialInvalid,
                'Provider credential payload is missing required fields.',
                'ext.missing_credential_fields',
                $connection,
            );
        }

        return ProviderConnectionResolution::resolved($connection);
    }
}
