<?php

namespace App\Services\Integrations;

use App\Models\ApiCredential;
use App\Services\DiscoveryTools\Jamf\JamfClient;
use Exception;
use GuzzleHttp\Client;
use Spatie\ArrayToXml\ArrayToXml;
use GuzzleHttp\Exception\BadResponseException;

class JamfIntegration
{
	public function __construct() {}

	/**
	 * Get the credential for the Jamf API.
	 *
	 * @return ApiCredential|null
	 */
	public function getCredential()
	{
		return ApiCredential::where('slug', 'jamf')->first();
	}

	/**
	 * Get the client for accessing the Jamf API.
	 *
	 * @return JamfClient
	 */
	public function getClient()
	{
		$credential = $this->getCredential();
		return new JamfClient(
			new Client([
				'base_uri' => optional($credential)->url
			]),
			[
				'client_id' => optional($credential)->user_name,
				'client_secret' => optional($credential)->password,
				'token' => $this->getToken(optional($credential)->data),
				'expiry' => $this->getExpiry(optional($credential)->data),
				'issuedAt' => $this->getIssuedAt(optional($credential)->data)
			]
		);
	}

	/** For Checking connection status
	 * @return bool
	 */
	public function checkConnection()
	{
		try {
			$credential = $this->getCredential();
			$client = $this->getClient();
			if (!$client->authorize($credential)) {
				return false;
			}
			return true;
		} catch (Exception $e) {
			return false;
		}
	}

	/**
	 * Get the token from the provided data.
	 *
	 * @param mixed $data The input data
	 * @return string The extracted token
	 */
	public function getToken($data)
	{
		if (empty($data)) {
			return '';
		}

		return json_decode($data)->token;
	}

	/**
	 * Get the expiry from the provided data.
	 *
	 * @param mixed $data The data to extract expiry from.
	 * @return mixed The extracted expiry value.
	 */
	public function getExpiry($data)
	{
		if (empty($data)) {
			return '';
		}

		return json_decode($data)->expiry;
	}

	/**
	 * Get the issuedAt property from the JSON data.
	 *
	 * @param mixed $data The input JSON data
	 * @return mixed The issuedAt property value
	 */
	public function getIssuedAt($data)
	{
		if (empty($data)) {
			return '';
		}

		return json_decode($data)->issuedAt;
	}

	/**
	 * Get the issuedAt property from the JSON data.
	 *
	 * @param mixed $data The input JSON data
	 * @return mixed The issuedAt property value
	 */
	public function getComputers($page = 0)
	{
		$credential = $this->getCredential();
		$client = $this->getClient();
		if (!$client->authorize($credential)) {
			return "Cannot Authorize";
		}

		$response = $client->getComputers($page);

		return json_decode($response->getBody()->getContents());
	}

	/**
	 * Retrieves hardware details using the given ID.
	 *
	 * @param datatype $id The ID of the hardware details to retrieve
	 * @throws Some_Exception_Class description of exception
	 * @return Some_Return_Value
	 */
	public function getHardwareDetails($id)
	{
		$credential = $this->getCredential();
		$client = $this->getClient();
		if (!$client->authorize($credential)) {
			return "Cannot Authorize";
		}

		$response = $client->getHardwareDetails($id);

		return json_decode($response->getBody()->getContents());
	}

	/**
	 * Retrieves a computer with the given name.
	 *
	 * @param string $name 
	 * @return mixed
	 */
	public function getComputerWithName(string $name)
	{
		$client = $this->getClient();
		$response = $client->getComputerWithName($name);

		return json_decode($response->getBody()->getContents());
	}

	/**
	 * A description of the entire PHP function.
	 *
	 * @param int $id description
	 * @param array $updateData description
	 * @throws BadResponseException description of exception
	 */
	public function updateUserDetailsForComputer(int $id, array $updateData)
	{
		$data = [
			'general' => $updateData
		];

		$result = ArrayToXml::convert($data, 'computer');

		try {
			$client = $this->getClient();
			$client->updateUserDetailsForComputer($id, $result);
		} catch (BadResponseException $e) {
			// dd($e->getResponse()->getBody()->getContents(), true);
		}
	}

	/**
	 * Authenticates the Jamf API client with the given API credentials.
	 * 
	 * @return boolean
	 */
	public function oauth()
	{
		try {
			$credential = $this->getCredential();
			$client = $this->getClient();
			if (!$client->authorize($credential)) {
				return false;
			}
			return true;
		} catch (Exception $e) {
			// dd($e->getMessage(), $e->getFile(), $e->getLine());
			return false;
		}

		return true;
	}

	/**Get some additional info about device using id
	 * @param mixed $id
	 * 
	 * @return [type]
	 */
	public function getDeviceDetailsById($id)
	{
		$credential = $this->getCredential();
		$client = $this->getClient();
		if (!$client->authorize($credential)) {
			return "Cannot Authorize";
		}
		$response = $client->getDeviceDetailsById($id);

		return json_decode($response->getBody()->getContents());
	}

	/**
	 * Retrieves the mobile devices from the API.
	 *
	 * @return mixed Returns the decoded JSON response containing the mobile devices.
	 */
	public function getMobileDevices()
	{
		$credential = $this->getCredential();
		$client = $this->getClient();
		if (!$client->authorize($credential)) {
			return "Cannot Authorize";
		}

		$response = $client->getMobileDevices();

		return json_decode($response->getBody()->getContents());
	}

	/**Get Mobile Device Details
	 * @param mixed $id
	 * 
	 * @return [type]
	 */
	public function getMobileDetailsById($id)
	{
		$credential = $this->getCredential();
		$client = $this->getClient();
		if (!$client->authorize($credential)) {
			return "Cannot Authorize";
		}

		$response = $client->getMobileDetailsById($id);

		return json_decode($response->getBody()->getContents());
	}


	/**Get the Computer Prestages
	 * 
	 * @return [type]
	 */
	public function getComputerPrestages($page = 0)
	{
		$credential = $this->getCredential();
		$client = $this->getClient();
		if (!$client->authorize($credential)) {
			return "Cannot Authorize";
		}

		$response = $client->getComputerPreStages($page);

		return json_decode($response->getBody()->getContents());
	}

	/**
	 * Get the devices from the computer prestates
	 */
	public function getComputerPreStagesDevices($preStage)
	{
		$credential = $this->getCredential();
		$client = $this->getClient();
		if (!$client->authorize($credential)) {
			return "Cannot Authorize";
		}

		$response = $client->getComputerPreStagesDevices($preStage);

		return json_decode($response->getBody()->getContents());
	}

	/**
	 * Get computer details by serial no
	 */
	public function getComputerDetailsBySerialNo($serialNo)
	{
		$credential = $this->getCredential();
		$client = $this->getClient();
		if (!$client->authorize($credential)) {
			return "Cannot Authorize";
		}
		$response = $client->getComputerDetailsBySerialNo($serialNo);

		return json_decode($response->getBody()->getContents());
	}


	/**Get recovery lock password details using id
	 * @param mixed $id
	 * 
	 * @return [type]
	 */
	public function getRecoveryLockPasswordById($id)
	{
		$credential = $this->getCredential();
		$client = $this->getClient();
		if (!$client->authorize($credential)) {
			return "Cannot Authorize";
		}

		$response = $client->getRecoveryLockPasswordById($id);

		return json_decode($response->getBody()->getContents());
	}

	/**Get File Vault info by using device id
	 * @param mixed $id
	 * 
	 * @return [type]
	 */
	public function getFileVaultInfoById($id)
	{
		$credential = $this->getCredential();
		$client = $this->getClient();
		if (!$client->authorize($credential)) {
			return "Cannot Authorize";
		}

		$response = $client->getFileVaultInfoById($id);

		return json_decode($response->getBody()->getContents());
	}

	/**
	 * gets jamf computer inventory from PRO API
	 * @param int $page
	 * 
	 * @return [type]
	 */
	public function getJamfProComputers($page = 0, $pageSize = 100)
	{
		$credential = $this->getCredential();
		$client = $this->getClient();
		if (!$client->authorize($credential)) {
			return "Cannot Authorize";
		}

		$response = $client->getJamfProComputers($page, $pageSize);

		return json_decode($response->getBody()->getContents());
	}

	/**Get some additional info about device using id
	 * @param mixed $id
	 * 
	 * @return [type]
	 */
	public function getProDeviceDetailsById($id)
	{
		$credential = $this->getCredential();
		$client = $this->getClient();
		if (!$client->authorize($credential)) {
			return "Cannot Authorize";
		}
		$response = $client->getJamfProDeviceDetailsById($id);

		return json_decode($response->getBody()->getContents());
	}
}
