<?php

use App\Models\Setting;
use Carbon\Carbon;
use Illuminate\Database\QueryException;

function formatDate( $date ): string {
	return Carbon::parse( $date )->format( getOption( 'ui', 'dateFormat', 'F j, Y' ) );
}

function formatTime( $date ): string {
	return Carbon::parse( $date )->format( getOption( 'ui', 'timeFormat', 'H:i' ) );
}

function formatDatetime( $date ): string {
	return Carbon::parse( $date )->format( getOption( 'ui', 'dateFormat', 'F j, Y' ) . ' ' . getOption( 'ui', 'timeFormat', 'H:i' ) );
}

function getOption( $group, $name, $default = '' ): string {
	try {
		$option = Setting::select( 'value' )->where( [
			'group' => $group,
			'name'  => $name
		] )->first();

		if ( $option ) {
			return $option->value;
		}
	} catch ( QueryException $e ) {
		return $default;
	}

	return $default;
}

function getLangDirection( $language ): string {
	return in_array( $language, [ 'ar' ] ) ? 'rtl' : 'ltr';

}

function generateLicenseKey( $characters, $chunksNumber, $chunkLength ): string {
	$characters_length = strlen( $characters );
	$license_chunks    = array();

	for ( $i = 0; $i < $chunksNumber; $i ++ ) {
		$chunk = '';

		for ( $j = 0; $j < $chunkLength; $j ++ ) {
			$chunk .= $characters[ rand( 0, $characters_length - 1 ) ];
		}

		$license_chunks[] = $chunk;
	}

	return implode( '-', $license_chunks );
}

function isEnvatoPurchaseCode( $purchase_code ): bool {
	if ( ! preg_match( "/^([a-f0-9]{8})-(([a-f0-9]{4})-){3}([a-f0-9]{12})$/i", $purchase_code ) ) {
		return false;
	}

	return true;
}

function getEnvatoPurchase( $purchase_code, $personalToken = '' ): array {
	return json_decode(
		Http::withToken( $personalToken != '' ? $personalToken : getOption( 'envato', 'personalToken' ) )
		    ->get( "https://api.envato.com/v3/market/author/sale?code=" . trim( $purchase_code ) )
		    ->body(),
		true
	);
}

function can( $capability ): bool {
	return in_array( $capability, Auth::user()->getCapabilities() );
}


/**
 * @param array $requestData
 * @param mixed $private_key
 * @param mixed $passphrase
 * @param mixed $algorithm
 *
 * @return array
 */
function sign( array $requestData, mixed $private_key, mixed $passphrase, mixed $algorithm ): array {
	$requestData['timestamp'] = time();
	$response                 = base64_encode( json_encode( $requestData ) );
	$binary_signature         = '';

	if ( extension_loaded( 'openssl' ) ) {
		if ( $private_key == '' ) {
			$signature = __( 'Private key not set' );
		} else {
			try {
				$pk_id     = openssl_pkey_get_private( $private_key, $passphrase );
				$is_signed = openssl_sign( $response, $binary_signature, $pk_id, (int) $algorithm );
				if ( $is_signed ) {
					$signature = base64_encode( $binary_signature );
				} else {
					$signature = openssl_error_string();
				}
			} catch ( Exception ) {
				$signature = __( 'Supplied key param cannot be coerced into a private key' );
			}
		}
	} else {
		$signature = __( 'Openssl is not installed on your server' );
	}

	return array( $requestData, $response, $signature );
}

/**
 * @param array $requestData
 * @param mixed $private_key
 * @param mixed $passphrase
 * @param mixed $algorithm
 *
 * @return string
 */
function encryptData( array $requestData, mixed $private_key, mixed $passphrase, mixed $algorithm ): string {
	$requestData['timestamp'] = time();
	$response                 = base64_encode( json_encode( $requestData ) );

	if ( extension_loaded( 'openssl' ) ) {
		if ( $private_key == '' ) {
			$encryptedData = __( 'API response authentication method set to encrypt but no private key was set' );
		} else {
			try {
				$is_encrypted = openssl_private_encrypt( $response, $encryptedData, openssl_pkey_get_private( $private_key, $passphrase ) );

				if ( $is_encrypted ) {
					$encryptedData = base64_encode( $encryptedData );
				} else {
					$encryptedData = openssl_error_string();
				}
			} catch ( Exception ) {
				$encryptedData = __( 'Supplied key param cannot be coerced into a private key' );
			}
		}
	} else {
		$encryptedData = __( 'Openssl is not installed on your server' );
	}

	return $encryptedData;
}

function strToColor( $str ): string {
	return '#' . substr( md5( $str ), 0, 6 );
}

function getKeevaultProductInfo(): array {
	return [
		'appVersion' => [
			'displayName' => __( 'Keevault Version' ),
			'value'       => '1.1.5'
		],
	];
}

function autoMigrate(): void {
	if ( file_exists( storage_path( 'installed' ) ) && ! file_exists( storage_path( 'version_101_update_installed' ) ) ) {
		Artisan::call( 'migrate', array( '--path' => 'database/migrations/2024_03_14_194454_add_endpoint_permission_to_api_keys_table.php', '--force' => true ) );

		file_put_contents( storage_path( 'version_101_update_installed' ), '' );
	}

	if ( file_exists( storage_path( 'version_101_update_installed' ) ) && ! file_exists( storage_path( 'version_111_update_installed' ) ) ) {
		Artisan::call( 'migrate', array( '--path' => 'database/migrations/2024_11_05_233117_create_contracts_table.php', '--force' => true ) );
		Artisan::call( 'migrate', array( '--path' => 'database/migrations/2024_11_06_000552_add_contract_id_to_license_keys_table.php', '--force' => true ) );

		file_put_contents( storage_path( 'version_111_update_installed' ), '' );
	}

	if ( file_exists( storage_path( 'version_111_update_installed' ) ) && ! file_exists( storage_path( 'version_112_update_installed' ) ) ) {
		Artisan::call( 'migrate', array( '--path' => 'database/migrations/2024_11_10_014603_add_endpoint_permissions_to_api_keys_table.php', '--force' => true ) );

		file_put_contents( storage_path( 'version_112_update_installed' ), '' );
	}

	if ( file_exists( storage_path( 'version_112_update_installed' ) ) && ! file_exists( storage_path( 'version_113_update_installed' ) ) ) {
		Artisan::call( 'migrate', array( '--path' => 'database/migrations/2024_11_11_043805_drop_unique_from_api_key_description_column.php', '--force' => true ) );

		file_put_contents( storage_path( 'version_113_update_installed' ), '' );
	}

	if ( file_exists( storage_path( 'version_113_update_installed' ) ) && ! file_exists( storage_path( 'version_114_update_installed' ) ) ) {
		Artisan::call( 'migrate', array( '--path' => 'database/migrations/2024_11_23_121141_add_endpoint_permission_to_api_keys_table.php', '--force' => true ) );

		file_put_contents( storage_path( 'version_114_update_installed' ), '' );
	}

	if ( file_exists( storage_path( 'version_114_update_installed' ) ) && ! file_exists( storage_path( 'version_115_update_installed' ) ) ) {
		Artisan::call( 'migrate', array( '--path' => 'database/migrations/2024_11_24_001809_create_jobs_table.php', '--force' => true ) );

		file_put_contents( storage_path( 'version_115_update_installed' ), '' );
	}
}

function printArray( $array, $depth = 0 ): void {
	foreach ( $array as $key => $value ) {
		// Create a style for the span to connect to the vertical border
		$spanStyle      = 'padding-left: 5px; margin-left: 0;';
		$containerStyle = 'position: relative; margin-left: 20px;'; // Add margin for indentation
		if ( $depth == 0 ) {
			$containerStyle = 'position: relative;'; // Add margin for indentation
		}

		// Print the container div for the horizontal line (only if depth > 0)
		echo '<div style="' . $containerStyle . '" class="border-left">';

		if ( $depth > 0 ) {
			echo '<div style="position: absolute; top: 14px; left: -20px; width: 20px; height: 2px; border-bottom: 2px dotted #c4c4c4;"></div>'; // Horizontal line for nested levels
		}

		// Check if the value is an array
		if ( is_array( $value ) || is_object( $value ) ) {
			// Print the key wrapped in the specified span with a border
			echo '<span class="badge bg-success font-weight-bolder text-xs my-1 py-1 px-1" style="' . $spanStyle . '">' . htmlspecialchars( $key ) . '</span>';

			// If the value is an object, convert it to an array and call the function recursively
			echo '<div >';
			printArray( (array) $value, $depth + 1 ); // Convert object to array and recursively print
			echo '</div>';
		} else {
			// Print the key wrapped in the specified span with a border
			echo '<span class="badge bg-success font-weight-bolder text-xs my-1 py-1 px-1" style="' . $spanStyle . '">' . htmlspecialchars( $key ) . '</span> = ';

			// Print the actual value followed by a line break
			echo htmlspecialchars( $value ) . '<br>';
		}
		echo '</div>'; // Close the container div
	}
}


