<?php

namespace App\Services\Integrations;

use Illuminate\Http\Client\RequestException;
use Illuminate\Support\Facades\Http;
use App\Models\ApiCredential;
use Illuminate\Support\Facades\Log;

/**
 * Service Class for JumpCloud API
 */
class JumpCloudIntegration
{
    /**
     * Returns the JumpCloud credentials
     */
    public function getJumpcloudCredentials()
    {
        return ApiCredential::where('slug', 'jumpcloud')->first();
    }

    /**
     * Check API Connection status
     */
    public function checkApiConnection()
    {
        return $this->makeGetRequest('api/systems', ['limit' => '1']);
    }

    /**
     * Make a GET request to the JumpCloud API
     * 
     * @param string $url The url for the GET request
     * @param array $params The parameters to pass in the GET request
     * 
     * @throws \Illuminate\Http\Client\RequestException
     * 
     * @return \Illuminate\Http\Client\Response
     */
    public function makeGetRequest($url, $params = [])
    {
        $credentials = $this->getJumpcloudCredentials();
        $baseUrl = config('services.jumpcloud.base_url');
        try {
            $response = Http::withHeaders([
                'Content-Type' => 'application/json',
                'Accept' => 'application/json',
                'x-api-key' => $credentials->key,
            ])
                ->retry(3, 3000)
                ->get($baseUrl . $url, $params)
                ->throw();

            if ($response->successful()) {
                return $response->json();
            }

            Log::channel('daily')->error('Failed to get JumpCloud API data for url: ' . $url . '. Error: ' . $response->json()['error']);
        } catch (RequestException $e) {
            Log::channel('daily')->error('Failed to get JumpCloud API data for url: ' . $url . '. Error: ' . $response->json()['error']);
        }

        return false;
    }

    /**
     * Call the API and return the reponse
     *
     * @param int $limit
     * @param int $offset
     */
    public function getAllDevicesData($page = 0)
    {
        $limit  = 100;
        $offset = $page * $limit;

        $response = $this->makeGetRequest('api/systems', ['skip' => $offset, 'limit' => $limit]);

        return $response;
    }

    /**
     * Call the API and return the reponse
     *
     * @param int $deviceId  device id
     * @return Array
     */
    public function getSingleDeviceData($deviceId)
    {
        if (!$deviceId) {
            return false;
        }

        return $this->makeGetRequest("api/systems/$deviceId");
    }

    /**
     * Call the API to get hardware details of device by id and return the reponse
     *
     * @param int $deviceId  device id
     */
    public function getHardwareDetails($deviceId)
    {
        if (!$deviceId) {
            return false;
        }

        return $this->makeGetRequest('api/v2/systeminsights/system_info', ['filter' => 'system_id:eq:' . $deviceId]);
    }

    /**
     * Call the API to get disk details of device and return the reponse
     *
     * @param int $deviceId  device id
     */
    public function getDiskDetails($deviceId)
    {
        if (!$deviceId) {
            return false;
        }

        return $this->makeGetRequest('api/v2/systeminsights/disk_info', ['filter' => 'system_id:eq:' . $deviceId]);
    }

    /**
     * Call the API to get user details and return the reponse
     *
     * @param int $userId user id
     */
    public function getUserById($userId)
    {
        if (!$userId) {
            return false;
        }

        return $this->makeGetRequest('api/systemusers/' . $userId);
    }

    /**
     * Call the API and return the reponse
     *
     * @param int $deviceId  device id
     */
    public function getSystemUsers($deviceId)
    {
        if (!$deviceId) {
            return false;
        }

        return $this->makeGetRequest('api/v2/systems/' . $deviceId . '/users');
    }
}
