<?php

namespace Planaday\Platform\WordpressConfig;

use Planaday\Config\Booking\BookingSettings;
use Planaday\Config\Course\CourseSettings;
use Planaday\Config\FeatureToggles\FeatureToggleSettings;
use Planaday\Config\General\GeneralSettings;
use Planaday\Config\Internal\InternalSettings;
use Planaday\Config\Payment\PaymentSettings;
use Planaday\Entities\PostEntities;
use Planaday\Platform\PlatformAbstraction\DataHandler;
use Planaday\Utility\Debug\Log\Logging;
use Planaday\Utility\PluginData;

class WPDataHandler implements DataHandler {
	use Logging;

	public function __construct(
		protected PluginData $pluginData
	) {}

	public function setOption( string $optionName, $value ): void {
		$this->logDebug("Setting option '$optionName' to (data)", $value);
		$optionName = $this->pluginData->getFullPrefix() . $optionName;
		update_option($optionName, $value);
	}

	/**
	 * @param string $optionName
	 *
	 * @return false|mixed|mixed[]|null
	 */
	public function getOption( string $optionName ): mixed {
		$this->logDebug("Getting option '$optionName'");

		$optionName = $this->pluginData->getFullPrefix() . $optionName;

		$option = get_option($optionName);
		$this->logDebug("Got option '$optionName' with value: (data)", $option);
		return $option;
	}

	public function getPostField(string $fieldName): mixed {
		if (PostEntities::is($fieldName)){
			$fieldName = $this->pluginData->getFullPrefix() . $fieldName;
		}

		if (isset($_POST[$fieldName])){
			return $this->cleanPostData($_POST[$fieldName]);
		}

		return null;
	}

	public function getPostData(): array {
		return $this->cleanPostData($_POST);
	}

	private function cleanPostData(mixed $postData): mixed{
		if (is_string($postData)){
			if ($postData === ''){
				return null;
			}

			return preg_replace("@\\\\(.)@", "$1", $postData);
		}

		if (is_array($postData)){
			return array_map( function ( $value ) {
				return $this->cleanPostData( $value );
			}, $postData );
		}

		if (
			is_int($postData) ||
			is_float($postData) ||
			is_bool($postData)
		){
			return $postData;
		}

		return null;
	}

	public function isPostDataSet():bool {
		return isset($_POST);
	}

	public function escapeSql(array|string $input): array|string {
		return esc_sql($input);
	}

	public function getServer(): string {
		$httpHost = $_SERVER['HTTP_HOST'];

		if (is_string($httpHost)){
			return preg_replace("@\\\\(.)@", "$1", $httpHost);
		}

		return '';
	}

	public function getSupportObject(): array{
		return [
			'internal' => $this->getOption(InternalSettings::getIndex()),
			'course' => $this->getOption(CourseSettings::getIndex()),
			'booking' => $this->getOption(BookingSettings::getIndex()),
			'payment' => $this->getOption(PaymentSettings::getIndex()),
			'general' => $this->getOption(GeneralSettings::getIndex()),
			'feature' => $this->getOption(FeatureToggleSettings::getIndex()),
			'pad-version' => $this->getOption('-version'),
			'wp-version' => get_bloginfo('version'),
			'php-version' => phpversion(),
			'db-version' => $GLOBALS['wpdb']?->db_version(),
		];
	}

	public function getSupportString(): string{
		return json_encode($this->getSupportObject());
	}

	public function sanitizeTextareaField(string $input): string {
		return sanitize_textarea_field($input);
	}

	public function generateNonceKey( string $nonceName, bool $clean = false ): string {
		return wp_create_nonce( ($clean ? "" : $this->pluginData->getShortPrefix()) . $nonceName );
	}

	public function verifyNonce( string $nonceName, ?string $key = null ): bool {
		return (wp_verify_nonce( $key ?? $this->getPostData()['_wpnonce'] ?? '', $this->pluginData->getShortPrefix() . $nonceName ) !== false);
	}

	public function verifyAdminNonce( string $nonceName ): void {
		check_admin_referer($this->pluginData->getShortPrefix() . $nonceName );
	}

	public function getRestNonceHeader(): array{
		return [
			'X-WP-Nonce' => $this->generateNonceKey('wp_rest', true)
		];
	}

	public function getPlatformVersion(): string {
		return wp_get_wp_version();
	}

	public function saveBackofficeKey( string $key ): void {
		$salt = $this->getOption('backoffice-key-salt');

		if (empty($salt) || !is_string($salt)){
			$salt = hash('sha256', uniqid(rand(), true));
			$this->setOption('backoffice-key-salt', $salt);
		}

		$this->setOption('backoffice-key', hash('sha256',$key . $salt));
	}

	public function checkBackofficeKey( string $key ): bool {
		$salt = $this->getOption('backoffice-key-salt');
		if (empty($salt) || !is_string($salt)){
			return false;
		}

		$expectedHash = $this->getOption('backoffice-key');
		if (empty($expectedHash) || !is_string($expectedHash)){
			return false;
		}

		$hash = hash('sha256',$key . $salt);

		return $hash === $expectedHash;
	}
}