<?php

namespace classes;

require_once WD . '/modules/entra/entra_c.php';

use entra\entra_c;


class entra
{
    /**
     * Configuration of the Entra module
     * @var entra_c
     */
    public entra_c $config;

    public function __construct()
    {
        $this->config = new entra_c();
    }

    public function get_users(bool $array = false): array
    {
        $accessToken = $this->requestAccessToken();
        $usersResponse = $this->requestJson(
            'https://graph.microsoft.com/v1.0/users?$select=id,displayName,mail,userPrincipalName',
            ['Authorization: Bearer ' . $accessToken]
        );
        $users = is_array($usersResponse['value'] ?? null) ? $usersResponse['value'] : [];
        if (!$array) {
            return $users;
        }

        $result = [];
        foreach ($users as $user) {
            if (!is_array($user)) {
                continue;
            }
            $result[] = [
                'id' => $user['id'] ?? null,
                'displayName' => $user['displayName'] ?? null,
                'mail' => $user['mail'] ?? null,
                'userPrincipalName' => $user['userPrincipalName'] ?? null,
            ];
        }
        return $result;
    }

    private function requestAccessToken(): string
    {
        $tenantId = trim((string)$this->config->tenant_id->getVariableValue());
        $response = $this->requestJson(
            'https://login.microsoftonline.com/' . rawurlencode($tenantId) . '/oauth2/v2.0/token',
            ['Content-Type: application/x-www-form-urlencoded'],
            http_build_query([
                'client_id' => (string)$this->config->client_id->getVariableValue(),
                'client_secret' => (string)$this->config->client_secret->getVariableValue(),
                'scope' => 'https://graph.microsoft.com/.default',
                'grant_type' => 'client_credentials',
            ])
        );

        $token = trim((string)($response['access_token'] ?? ''));
        if ($token === '') {
            throw new \RuntimeException('Microsoft Entra token response did not contain an access token.');
        }

        return $token;
    }

    /**
     * @param list<string> $headers
     * @return array<string,mixed>
     */
    private function requestJson(string $url, array $headers, ?string $postFields = null): array
    {
        $curl = curl_init($url);
        if ($curl === false) {
            throw new \RuntimeException('Unable to initialize Microsoft Entra request.');
        }

        curl_setopt_array($curl, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_CONNECTTIMEOUT => 5,
            CURLOPT_TIMEOUT => 20,
            CURLOPT_HTTPHEADER => $headers,
        ]);
        if ($postFields !== null) {
            curl_setopt($curl, CURLOPT_POST, true);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $postFields);
        }

        try {
            $body = curl_exec($curl);
            $status = (int)curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
            if ($body === false) {
                throw new \RuntimeException('Microsoft Entra request failed: ' . curl_error($curl));
            }
        } finally {
            curl_close($curl);
        }

        $decoded = json_decode((string)$body, true);
        if ($status < 200 || $status >= 300 || !is_array($decoded)) {
            $message = is_array($decoded)
                ? (string)($decoded['error_description'] ?? $decoded['error']['message'] ?? 'Unexpected response')
                : 'Invalid JSON response';
            throw new \RuntimeException('Microsoft Entra request failed with HTTP ' . $status . ': ' . $message);
        }

        return $decoded;
    }
}
