<?php
use Give\Framework\PaymentGateways\Commands\RedirectOffsite;
use Give\Framework\PaymentGateways\Exceptions\PaymentGatewayException;
use Give\Donations\Models\Donation;
use Webimpian\BayarcashSdk\Bayarcash as BayarcashSdk;

trait BayarcashPaymentTrait {
	private static bool $script_loaded = false;
	private BayarcashSdk $bayarcashSdk;

	public function getLegacyFormFieldMarkup($formId, $args): string {
		return "<div class=''>
            <p>You will be redirected to " . $this->getName() . "</p>
        </div>";
	}

	public function enqueueScript(int $formId) {
		BayarcashScriptLoader::enqueueScript();
	}


	public function createPayment(Donation $donation, $gatewayData): RedirectOffsite {
		$form_id = $donation->formId;
		$tokens = $this->getEndpointTokens($form_id);
		$gatewayId = $gatewayData['gatewayId'] ?? $donation->gatewayId ?? null;

		if (empty($gatewayId)) {
			throw new PaymentGatewayException(__('Gateway ID is required.', 'bayarcash-for-givewp'));
		}

		try {
			$payment_mode = $this->mapGatewayIdToPaymentMode($gatewayId);
		} catch (\Exception $e) {
			throw new PaymentGatewayException(__('Invalid payment gateway selected.', 'bayarcash-for-givewp'));
		}

		if (!isset($tokens->$payment_mode)) {
			throw new PaymentGatewayException(__('Invalid payment mode selected.', 'bayarcash-for-givewp'));
		}

		$channel_tokens = $tokens->$payment_mode;
		$this->bayarcashSdk = new BayarcashSdk($channel_tokens['portal_token']);

		if (give_is_test_mode()) {
			$this->bayarcashSdk->useSandbox();
		}

		$args = [
			'portal_key' => $channel_tokens['portal_key'],
			'order_number' => $donation->id,
			'amount' => $donation->amount->getAmount() / 100,
			'payer_name' => $donation->firstName . ' ' . $donation->lastName,
			'payer_email' => $donation->email,
			'payer_telephone_number' => $gatewayData['phone'] ?? '',
			'return_url' => site_url('/give-api/bayarcash_gateway/?bc-givewp-return=' . $this->createReturnToken($donation->id)),
			'payment_channel' => $channel_tokens['payment_channel'],
		];

		$args['checksum'] = $this->bayarcashSdk->createPaymentIntenChecksumValue($channel_tokens['secret_key'], $args);

		try {
			$response = $this->bayarcashSdk->createPaymentIntent($args);

			if (empty($response->url)) {
				throw new PaymentGatewayException(__('Failed to create payment intent with Bayarcash SDK', 'bayarcash-for-givewp'));
			}

			if (give_is_test_mode()) {
				give_insert_payment_note($donation->id, __('This is test environment where payment status is simulated.', 'bayarcash-for-givewp'));
			}
			give_insert_payment_note($donation->id, sprintf(__('URL: %s', 'bayarcash-for-givewp'), $response->url));

			return new RedirectOffsite($response->url);

		} catch (\Exception $e) {
			throw new PaymentGatewayException(
				defined('WP_DEBUG') && WP_DEBUG ?
					$e->getMessage() :
					__('Something went wrong, please contact the merchant', 'bayarcash-for-givewp')
			);
		}
	}

	private function getEndpointTokens($form_id): object {
		$channels = [
			'bayarcash' => ['key' => 'bayarcash', 'payment_channel' => 1],
			'bayarcash_duitnow' => ['key' => 'bc-duitnow', 'payment_channel' => 5],
			'bayarcash_linecredit' => ['key' => 'bc-linecredit', 'payment_channel' => 4],
			'bayarcash_duitnowqr' => ['key' => 'bc-duitnowqr', 'payment_channel' => 6],
			'bayarcash_duitnowshopee' => ['key' => 'bc-duitnowshopee', 'payment_channel' => 7],
			'bayarcash_duitnowboost' => ['key' => 'bc-duitnowboost', 'payment_channel' => 8],
			'bayarcash_duitnowqris' => ['key' => 'bc-duitnowqris', 'payment_channel' => 9],
			'bayarcash_duitnowqriswallet' => ['key' => 'bc-duitnowqriswallet', 'payment_channel' => 10],
		];

		$tokens = [];
		foreach ($channels as $payment_mode => $channel) {
			$setting_key = $channel['key'];
			$customize_donations = give_get_meta($form_id, "{$setting_key}_givewp_customize_donations", true) === 'enabled';

			if ($customize_donations) {
				$portal_token = give_get_meta($form_id, "{$setting_key}_portal_token", true);
				$portal_key = give_get_meta($form_id, "{$setting_key}_portal_key", true);
				$secret_key = give_get_meta($form_id, "{$setting_key}_secret_key", true);
			} else {
				$portal_token = give_get_option("{$setting_key}_portal_token");
				$portal_key = give_get_option("{$setting_key}_portal_key");
				$secret_key = give_get_option("{$setting_key}_secret_key");
			}

			$tokens[$payment_mode] = [
				'portal_token' => $portal_token,
				'portal_key' => $portal_key,
				'secret_key' => $secret_key,
				'payment_channel' => $channel['payment_channel'],
			];
		}

		$endpoint = give_is_test_mode() ? 'https://sandbox.bayar.cash/api' : 'https://bayar.cash/api';

		return (object) array_merge(
			$tokens,
			[
				'directdebit_request_url' => $endpoint.'/mandates/enrollment/confirmation',
				'directdebit_cancel_url'  => $endpoint.'/mandates/termination',
			]
		);
	}

	/**
	 * @throws Exception
	 */
	private function mapGatewayIdToPaymentMode(string $gatewayId): string {
		$gatewayMap = [
			'bayarcash_block' => 'bayarcash',
			'bayarcash_duitnow_block' => 'bayarcash_duitnow',
			'bayarcash_linecredit_block' => 'bayarcash_linecredit',
			'bayarcash_duitnowqr_block' => 'bayarcash_duitnowqr',
			'bayarcash_duitnowshopee_block' => 'bayarcash_duitnowshopee',
			'bayarcash_duitnowboost_block' => 'bayarcash_duitnowboost',
			'bayarcash_duitnowqris_block' => 'bayarcash_duitnowqris',
			'bayarcash_duitnowqriswallet_block' => 'bayarcash_duitnowqriswallet'
		];

		if (!isset($gatewayMap[$gatewayId])) {
			throw new \Exception(sprintf('Unsupported gateway ID: %s', $gatewayId));
		}

		return $gatewayMap[$gatewayId];
	}

	private function createReturnToken(string $payment_id): string {
		return wp_create_nonce('bc-givewp-return-' . $payment_id);
	}
}

class BayarcashScriptLoader {
	private static bool $script_loaded = false;

	public static function enqueueScript() {
		if (self::$script_loaded) {
			return;
		}

		self::$script_loaded = true;

		wp_enqueue_script(
			'bayarcash-gateway',  // Use a common handle for all gateways
			plugin_dir_url(__FILE__) . '../js/bayarcash-gateway.js',
			['react', 'wp-element'],
			'1.0.0',
			true
		);
	}
}