<?php

namespace App\Services\Intune;

use App\Models\ManagedEnvironment;
use App\Services\Graph\GraphClientInterface;
use App\Services\Graph\GraphErrorMapper;
use App\Services\Providers\MicrosoftGraphOptionsResolver;
use App\Services\Providers\ProviderConfigurationRequiredException;
use App\Support\Providers\ProviderReasonCodes;
use Throwable;

class TenantConfigService
{
    public function __construct(
        private readonly GraphClientInterface $graphClient,
        private readonly MicrosoftGraphOptionsResolver $graphOptionsResolver,
    ) {}

    /**
     * @return array{success:bool,error_message:?string,requires_consent:bool}
     */
    public function testConnectivity(ManagedEnvironment $tenant): array
    {
        try {
            $options = $this->graphOptions($tenant);
        } catch (ProviderConfigurationRequiredException $exception) {
            return [
                'success' => false,
                'error_message' => $exception->getMessage(),
                'requires_consent' => $exception->reasonCode === ProviderReasonCodes::ProviderConsentMissing,
            ];
        }

        if ($options['tenant'] === null) {
            return [
                'success' => false,
                'error_message' => 'ManagedEnvironment ID is missing',
                'requires_consent' => false,
            ];
        }

        try {
            $response = $this->graphClient->getOrganization($options);
        } catch (Throwable $throwable) {
            $mapped = GraphErrorMapper::fromThrowable($throwable, ['tenant' => $options['tenant']]);

            return [
                'success' => false,
                'error_message' => $mapped->getMessage(),
                'requires_consent' => $this->requiresConsent($mapped->getMessage()),
            ];
        }

        if ($response->failed()) {
            $message = $response->errors[0]['message'] ?? $response->errors[0] ?? 'Graph connectivity failed';

            return [
                'success' => false,
                'error_message' => is_string($message) ? $message : json_encode($message),
                'requires_consent' => $this->requiresConsent((string) $message),
            ];
        }

        return ['success' => true, 'error_message' => null, 'requires_consent' => false];
    }

    /**
     * @return array<string, mixed>
     */
    public function graphOptions(ManagedEnvironment $tenant): array
    {
        return $this->graphOptionsResolver->resolveForTenant($tenant);
    }

    private function requiresConsent(string $message): bool
    {
        return str_contains(strtolower($message), 'consent');
    }
}
