<?php

use App\Models\ProviderConnection;
use App\Models\ProviderCredential;
use App\Models\ManagedEnvironment;
use App\Services\Providers\MicrosoftGraphOptionsResolver;
use App\Services\Providers\ProviderConfigurationRequiredException;
use App\Support\Providers\ProviderReasonCodes;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

it('throws when no default provider connection exists', function (): void {
    $tenant = ManagedEnvironment::factory()->create();

    $resolver = app(MicrosoftGraphOptionsResolver::class);

    $call = fn (): array => $resolver->resolveForTenant($tenant);

    expect($call)->toThrow(ProviderConfigurationRequiredException::class);

    try {
        $call();
    } catch (ProviderConfigurationRequiredException $exception) {
        expect($exception->reasonCode)->toBe(ProviderReasonCodes::ProviderConnectionMissing);
        expect($exception->provider)->toBe('microsoft');
        expect($exception->tenantId)->toBe((int) $tenant->getKey());
    }
});

it('throws when default provider connection needs consent', function (): void {
    $tenant = ManagedEnvironment::factory()->create();

    ProviderConnection::factory()->create([
        'managed_environment_id' => $tenant->getKey(),
        'workspace_id' => $tenant->workspace_id,
        'provider' => 'microsoft',
        'is_default' => true,
        'consent_status' => 'required',
    ]);

    $resolver = app(MicrosoftGraphOptionsResolver::class);

    $call = fn (): array => $resolver->resolveForTenant($tenant);

    expect($call)->toThrow(ProviderConfigurationRequiredException::class);

    try {
        $call();
    } catch (ProviderConfigurationRequiredException $exception) {
        expect($exception->reasonCode)->toBe(ProviderReasonCodes::ProviderConsentMissing);
    }
});

it('builds graph options from default provider connection credentials', function (): void {
    $tenant = ManagedEnvironment::factory()->create();

    $connection = ProviderConnection::factory()->dedicated()->consentGranted()->create([
        'managed_environment_id' => $tenant->getKey(),
        'workspace_id' => $tenant->workspace_id,
        'provider' => 'microsoft',
        'entra_tenant_id' => 'entra-tenant-id',
        'is_default' => true,
    ]);

    ProviderCredential::factory()->create([
        'provider_connection_id' => $connection->getKey(),
        'type' => 'client_secret',
        'payload' => [
            'client_id' => 'client-id',
            'client_secret' => 'client-secret',
        ],
    ]);

    $resolver = app(MicrosoftGraphOptionsResolver::class);

    $options = $resolver->resolveForTenant($tenant, ['query' => ['a' => 'b']]);

    expect($options['tenant'])->toBe('entra-tenant-id');
    expect($options['client_id'])->toBe('client-id');
    expect($options['client_secret'])->toBe('client-secret');
    expect($options['client_request_id'])->toBeString()->not->toBeEmpty();
    expect($options['query'])->toBe(['a' => 'b']);
});
