<?php

namespace App\Services\Providers;

use App\Models\ProviderConnection;
use App\Services\Graph\GraphClientInterface;
use App\Services\Graph\GraphResponse;
use Illuminate\Support\Str;
use RuntimeException;

final class ProviderGateway
{
    public function __construct(
        private readonly GraphClientInterface $graph,
        private readonly ProviderIdentityResolver $identityResolver,
    ) {}

    public function getOrganization(ProviderConnection $connection): GraphResponse
    {
        return $this->graph->getOrganization($this->graphOptions($connection));
    }

    public function getPolicy(ProviderConnection $connection, string $policyType, string $policyId, array $options = []): GraphResponse
    {
        return $this->graph->getPolicy($policyType, $policyId, $this->graphOptions($connection, $options));
    }

    public function listPolicies(ProviderConnection $connection, string $policyType, array $options = []): GraphResponse
    {
        return $this->graph->listPolicies($policyType, $this->graphOptions($connection, $options));
    }

    public function applyPolicy(
        ProviderConnection $connection,
        string $policyType,
        string $policyId,
        array $payload,
        array $options = [],
    ): GraphResponse {
        return $this->graph->applyPolicy($policyType, $policyId, $payload, $this->graphOptions($connection, $options));
    }

    public function getServicePrincipalPermissions(ProviderConnection $connection, array $options = []): GraphResponse
    {
        return $this->graph->getServicePrincipalPermissions($this->graphOptions($connection, $options));
    }

    public function request(ProviderConnection $connection, string $method, string $path, array $options = []): GraphResponse
    {
        return $this->graph->request($method, $path, $this->graphOptions($connection, $options));
    }

    /**
     * @return array<string, mixed>
     */
    public function graphOptions(ProviderConnection $connection, array $overrides = []): array
    {
        $resolution = $this->identityResolver->resolve($connection);

        if (! $resolution->resolved || $resolution->effectiveClientId === null || $resolution->clientSecret === null) {
            throw new RuntimeException($resolution->message ?? 'Provider identity could not be resolved.');
        }

        return array_merge([
            'tenant' => $resolution->targetScopeIdentifier('organizations'),
            'client_id' => $resolution->effectiveClientId,
            'client_secret' => $resolution->clientSecret,
            'client_request_id' => (string) Str::uuid(),
        ], $overrides);
    }
}
