<?php

namespace App\Services\Providers;

use App\Models\ProviderConnection;
use App\Models\ProviderCredential;
use App\Models\ManagedEnvironment;
use App\Support\Providers\ProviderConnectionType;

final class ProviderConnectionClassifier
{
    public function classify(
        ProviderConnection $connection,
        string $source = 'migration_scan',
    ): ProviderConnectionClassificationResult {
        $connection->loadMissing(['credential', 'tenant']);

        $tenant = $connection->tenant;
        $credential = $connection->credential;
        $legacyIdentity = $tenant instanceof ManagedEnvironment ? $tenant->legacyProviderIdentity() : ['client_id' => null, 'has_secret' => false];
        $tenantClientId = trim((string) ($legacyIdentity['client_id'] ?? ''));
        $credentialClientId = $this->credentialClientId($credential);
        $currentConnectionType = $connection->connection_type instanceof ProviderConnectionType
            ? $connection->connection_type->value
            : (is_string($connection->connection_type) ? $connection->connection_type : null);
        $hasLegacyTenantIdentity = $tenantClientId !== '' || (bool) ($legacyIdentity['has_secret'] ?? false);
        $hasDedicatedCredential = $credential instanceof ProviderCredential;

        $suggestedConnectionType = ProviderConnectionType::Platform;
        $reviewRequired = false;

        if ($hasDedicatedCredential && ! $hasLegacyTenantIdentity) {
            $suggestedConnectionType = ProviderConnectionType::Dedicated;
        } elseif ($hasDedicatedCredential && $hasLegacyTenantIdentity) {
            $suggestedConnectionType = ProviderConnectionType::Dedicated;
            $reviewRequired = $tenantClientId === '' || $credentialClientId === '' || $tenantClientId !== $credentialClientId;
        } elseif (! $hasDedicatedCredential && $hasLegacyTenantIdentity) {
            $suggestedConnectionType = ProviderConnectionType::Platform;
            $reviewRequired = true;
        }

        return new ProviderConnectionClassificationResult(
            providerConnectionId: (int) $connection->getKey(),
            suggestedConnectionType: $suggestedConnectionType,
            reviewRequired: $reviewRequired,
            signals: [
                'has_dedicated_credential' => $hasDedicatedCredential,
                'credential_client_id' => $credentialClientId !== '' ? $credentialClientId : null,
                'has_legacy_tenant_identity' => $hasLegacyTenantIdentity,
                'tenant_client_id' => $tenantClientId !== '' ? $tenantClientId : null,
                'tenant_has_secret' => (bool) ($legacyIdentity['has_secret'] ?? false),
                'current_connection_type' => $currentConnectionType,
                'is_enabled' => (bool) $connection->is_enabled,
                'consent_status' => $this->enumValue($connection->consent_status),
                'verification_status' => $this->enumValue($connection->verification_status),
                'last_error_reason_code' => is_string($connection->last_error_reason_code) ? $connection->last_error_reason_code : null,
            ],
            effectiveApp: $this->effectiveAppMetadata(
                suggestedConnectionType: $suggestedConnectionType,
                reviewRequired: $reviewRequired,
                credentialClientId: $credentialClientId,
            ),
            source: $source,
        );
    }

    private function credentialClientId(?ProviderCredential $credential): string
    {
        if (! $credential instanceof ProviderCredential || ! is_array($credential->payload)) {
            return '';
        }

        return trim((string) ($credential->payload['client_id'] ?? ''));
    }

    /**
     * @return array{app_id: ?string, source: string}
     */
    private function effectiveAppMetadata(
        ProviderConnectionType $suggestedConnectionType,
        bool $reviewRequired,
        string $credentialClientId,
    ): array {
        if ($reviewRequired) {
            return [
                'app_id' => null,
                'source' => 'review_required',
            ];
        }

        if ($suggestedConnectionType === ProviderConnectionType::Dedicated) {
            return [
                'app_id' => $credentialClientId !== '' ? $credentialClientId : null,
                'source' => 'dedicated_credential',
            ];
        }

        $platformClientId = trim((string) config('graph.client_id'));

        return [
            'app_id' => $platformClientId !== '' ? $platformClientId : null,
            'source' => 'platform_config',
        ];
    }

    private function enumValue(mixed $value): ?string
    {
        if ($value instanceof \BackedEnum) {
            return $value->value;
        }

        if (is_string($value) && trim($value) !== '') {
            return trim($value);
        }

        return null;
    }
}
