<?php

namespace App\Services\Integrations;

use League\OAuth2\Client\Provider\GenericProvider;
use App\Models\ApiCredential;
use Microsoft\Graph\Graph;
use Microsoft\Graph\Model;
use GuzzleHttp\Exception\BadResponseException;
use Exception;

class IntuneIntegration
{
	protected $credential;
	protected $client;

	public function __construct()
	{
		$this->credential = ApiCredential::where('slug', 'intune')->first();

		$this->client = new GenericProvider([
			'clientId'                => optional($this->credential)->user_name,
			'clientSecret'            => optional($this->credential)->password,
			'redirectUri'             => url('intune-callback'),
			'urlAuthorize'            => config('services.intune.base_url') . '/' . optional($this->credential)->url . 'oauth2/v2.0/authorize',
			'urlAccessToken'          => config('services.intune.base_url') . '/' . optional($this->credential)->url . 'oauth2/v2.0/token',
			'urlResourceOwnerDetails' => '',
			'scopes'                  => config('services.intune.scopes')
		]);
	}

	public function getAuthUrl()
	{
		$authUrl = $this->client->getAuthorizationUrl();

		session(['oauthState' => $this->client->getState()]);

		return $authUrl;
	}

	public function getAccessToken($authCode)
	{
		return $this->client->getAccessToken('authorization_code', [
			'code' => $authCode
		]);
	}

	public function storeTokens($accessToken)
	{
		$this->credential->update([
			'data' => json_encode([
				'accessToken' => $accessToken->getToken(),
				'refreshToken' => $accessToken->getRefreshToken(),
				'tokenExpires' => $accessToken->getExpires(),
			])
		]);
	}

	public function clearTokens()
	{
		$this->credential->update(['data' => '']);
	}

	public function getCurrentAccessToken()
	{
		if (empty($this->credential->data)) {
			return '';
		}

		$tokens = json_decode($this->credential->data);
		// Check if tokens exist
		if (
			empty($tokens->accessToken) ||
			empty($tokens->refreshToken) ||
			empty($tokens->tokenExpires)
		) {
			return '';
		}

		$now = time() + 300;
		if ($tokens->tokenExpires <= $now) {

			try {
				$newToken = $this->client->getAccessToken('refresh_token', [
					'refresh_token' => $tokens->refreshToken
				]);

				$this->storeTokens($newToken);

				return $newToken->getToken();
			} catch (League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
				return '';
			} catch (Exception $e) {
				return '';
			}
		}

		return $tokens->accessToken;
	}

	public function getWindowsManagedDevices($nextPageLink = '')
	{
		$accessToken = $this->getCurrentAccessToken();
		if (empty($accessToken)) {
			return ['token_error' => "Invalid Token!. Please reconnect"];
		}
		$graph = new Graph();
		$graph->setAccessToken($accessToken);

		//For the first page execution we will use ths default link, then we will get the next page Link
		if (empty($nextPageLink)) {
			$nextPageLink = '/deviceManagement/managedDevices';
		}

		try {
			$devices = $graph->createRequest('GET', $nextPageLink)->execute();
		} catch (BadResponseException $e) {
			return ['error' => json_decode($e->getResponse()->getBody()->getContents(), true)];
		}
		return ['devices' => $devices->getBody()];
	}
}
