<?php

namespace KnitPayUPI\Gateways\UpiQR\BharatPe;

use KnitPayUPI\Gateways\UpiQR\KnitPayUPIIntegration;
use Exception;
use KnitPay\Utils as KnitPayUtils;
use Pronamic\WordPress\Html\Element;
use Zxing\QrReader;

/**
 * Title: BharatPe Integration
 * Copyright: 2020-2026 Knit Pay
 *
 * @author  Knit Pay
 * @version 1.6.1.0
 * @since   1.3.0.0
 */
class Integration extends KnitPayUPIIntegration {
	/**
	 * Construct BharatPe integration.
	 *
	 * @param array $args Arguments.
	 */
	public function __construct( $args = [] ) {
		$args = wp_parse_args(
			$args,
			[
				'id'                 => 'bharat-pe',
				'name'               => 'UPI/QR - BharatPe for Business',
				'product_url'        => 'http://go.thearrangers.xyz/bharatpe?utm_source=knit-pay&utm_medium=ecommerce-module&utm_campaign=module-admin&utm_content=product-url',
				'provider'           => 'bharat-pe',
				'gateway_name'       => 'BharatPe for Business',
				'short_id'           => 'bharatpe',
				'refresh_connection' => true,
			]
		);

		parent::__construct( $args );
	}
	
	/**
	 * Get config.
	 *
	 * @param int $post_id Config ID.
	 * @return Config
	 */
	public function get_config( $post_id ) {
		$config = new Config();
		$config->copy_properties( parent::get_config( $post_id ) );
		
		// Common Config.
		$config->integration_mode    = $this->get_meta( $post_id, 'upi_qr_bharatpe_integration_mode' );
		$config->merchant_id         = $this->get_meta( $post_id, 'upi_qr_bharatpe_merchant_id' );
		$config->token               = $this->get_meta( $post_id, 'upi_qr_bharatpe_token' );
		$config->payment_status_mode = $this->get_meta( $post_id, 'upi_qr_bharatpe_payment_status_mode' );
		$config->connection_data     = $this->get_meta( $post_id, 'upi_qr_bharatpe_connection_data' );

		// Auto Integration Mode Config.
		$config->phone_number     = $this->get_meta( $post_id, 'upi_qr_bharatpe_phone_number' );
		$config->csrf_token       = $this->get_meta( $post_id, 'upi_qr_bharatpe_csrf_token' );
		$config->bharatpe_session = $this->get_meta( $post_id, 'upi_qr_bharatpe_bharatpe_session' );
		$config->uuid             = $this->get_meta( $post_id, 'upi_qr_bharatpe_uuid' );

		$config->hide_mobile_qr       = false;
		$config->hide_pay_button      = true;
		$config->transaction_id_field = self::SHOW_REQUIRED_FIELD;

		if ( empty( $config->integration_mode ) ) {
			$config->integration_mode = 'auto';
		}

		return $config;
	}

	public function get_setup_settings_fields( $fields ) {
		$fields = $this->get_login_logout_fields( $fields );

		// Payment Status Mode.
		$fields[] = [
			'section'     => 'general',
			'meta_key'    => '_pronamic_gateway_upi_qr_bharatpe_payment_status_mode',
			'title'       => __( 'Payment Status Mode', 'knit-pay-upi' ),
			'type'        => 'select',
			'options'     => [
				'auto'         => 'Fully Automatic',
				'partial_auto' => 'Partially Automatic',
			],
			'default'     => 'auto',
			'description' => 'Fully Automatic - the payment status will be updated automatically. The amount collected might be slightly different than the actual. We will try to keep the collected amount as close to the actual amount as possible.<br>' .
			'Partially Automatic - the buyer will have to enter the UTR number to get the payment status.',
		];
		
		// WP Cron URL.
		$fields[] = [
			'section'  => 'general',
			'title'    => \__( 'WP Cron URL', 'knit-pay-upi' ),
			'type'     => 'text',
			'classes'  => [ 'large-text', 'code' ],
			'value'    => site_url( 'wp-cron.php' ),
			'readonly' => true,
			'callback' => function () {
				echo 'We recommend setting up WP-Cron to run at least twice per hour (every 30 minutes) to help prevent session timeouts. For reliable scheduling, configure your system task scheduler to call your site\'s <code>wp-cron.php</code>. See the documentation for details.<br>' .
				'<a target="_blank" rel="noopener noreferrer" href="https://developer.wordpress.org/plugins/cron/hooking-wp-cron-into-the-system-task-scheduler/">https://developer.wordpress.org/plugins/cron/hooking-wp-cron-into-the-system-task-scheduler/</a>';
			},
		];

		unset( $fields['transaction_id_field'] );
		unset( $fields['merchant_category_code'] );

		return $fields;
	}

	private function get_login_logout_fields( $fields ) {
		// Connection Status.
		$config_id = KnitPayUtils::get_gateway_config_id();
		if ( ! empty( $config_id ) ) {
			$config = $this->get_config( $config_id );
		}
		if ( isset( $config ) && '' !== $config->token ) {
			try {
				$api_client = new Client( $config );
				$api_client->get_transaction_details( $this->get_meta( $config_id, 'upi_qr_bharatpe_connection_data' ) );

				$fields[] = [
					'section'  => 'general',
					'type'     => 'custom',
					'title'    => 'Connected',
					'callback' => function () {
						echo '<span class="dashicons dashicons-yes"></span>';
					},
				];
			} catch ( Exception $e ) {
				$fields[] = [
					'section'  => 'general',
					'type'     => 'custom',
					'title'    => 'Connected',
					'callback' => function () {
						echo '<span class="dashicons dashicons-no"></span>';
					},
				];
				
				$message = '<strong>Knit Pay</strong> - The connection to BharatPe could not be established. Please ensure that the provided merchant ID and token are accurate.';
				wp_admin_notice( $message, [ 'type' => 'error' ] );
				return $fields;
			}
			
			$fields = parent::get_setup_settings_fields( $fields );

			return $fields;
		}

		if ( 'auto' === $config->integration_mode ) {
			// Registered Phone.
			$fields[] = [
				'section'  => 'general',
				'title'    => __( 'Phone Number', 'knit-pay-upi' ),
				'type'     => 'description',
				'callback' => [ $this, 'field_send_phone_otp' ],
				'tooltip'  => __( 'Phone number of BharatPe account.', 'knit-pay-upi' ),
			];
		
			// Submit OTP.
			$fields[] = [
				'section'  => 'general',
				'title'    => __( 'OTP', 'knit-pay-upi' ),
				'type'     => 'description',
				'callback' => [ $this, 'field_submit_otp' ],
			];

			// Load admin.js Javascript
			$fields[] = [
				'section'  => 'general',
				'type'     => 'custom',
				'callback' => function () {
					echo '<script src="' . plugins_url( '', __FILE__ ) . '/js/admin.js"></script>';
				},
			];
		} else {
			// Steps to Integrate.
			$fields[] = [
				'section'  => 'general',
				'type'     => 'custom',
				'title'    => 'Steps to Integrate BharatPe',
				'callback' => function () {
					echo '<ol><li>Token and Merchant ID can be found in the Local Storage, after login at <a target="_blank" href="https://enterprise.bharatpe.in/">https://enterprise.bharatpe.in/</a></li>
                    <ul>
                        <li><a target="_blank" href="https://firefox-source-docs.mozilla.org/devtools-user/storage_inspector/local_storage_session_storage/index.html">Firefox Local Storage</a></li>
                        <li><a target="_blank" href="https://developer.chrome.com/docs/devtools/storage/localstorage">Chrome Local Storage</a></li>
                    </ul>
                    <br><li>Feel free to <a target="_blank" href="https://www.knitpay.org/contact-us/">contact us</a> if you need help in generating retrieving Merchant ID and Token</li>
                  </ol>';
				},
			];

			// Merchant ID.
			// JSON.parse(window.localStorage.getItem("USER_INFO")).merchant_id
			$fields[] = [
				'section'  => 'general',
				'meta_key' => '_pronamic_gateway_upi_qr_bharatpe_merchant_id',
				'title'    => __( 'Merchant ID', 'knit-pay-upi' ),
				'type'     => 'text',
				'classes'  => [ 'regular-text', 'code' ],
				'required' => true,
			];

			// Token.
			// window.localStorage.getItem("TOKEN")
			$fields[] = [
				'section'  => 'general',
				'meta_key' => '_pronamic_gateway_upi_qr_bharatpe_token',
				'title'    => __( 'Token', 'knit-pay-upi' ),
				'type'     => 'text',
				'classes'  => [ 'regular-text', 'code' ],
				'required' => true,
			];
		}
		
		return $fields;
	}
	
	/**
	 * Save post.
	 *
	 * @param int $post_id Post ID.
	 * @return void
	 */
	public function save_post( $config_id ) {
		if ( '' !== $this->get_meta( $config_id, 'upi_qr_bharatpe_connection_data' ) ) {
			return;
		}

		$config = $this->get_config( $config_id );

		// Don't do anything if manual mode is activated.
		if ( 'manual' === $config->integration_mode ) {
			$this->get_vpa( $config_id );
			$this->get_bharatpe_connection_data( $config_id );
			return;
		}

		if ( '' === $config->bharatpe_session ) {
			$api_client = new Client( $config );
			try {
				$api_client->init_session();
			} catch ( Exception $e ) {
				$this->knit_pay_post_save_notice( $e->getMessage() );
				return;
			}
		}

		//phpcs:ignore WordPress.Security.NonceVerification.Missing
		$new_phone_number = isset( $_POST['_pronamic_gateway_upi_qr_bharatpe_phone_number'] ) ? sanitize_text_field( $_POST['_pronamic_gateway_upi_qr_bharatpe_phone_number'] ) : '';
		if ( $new_phone_number !== $config->phone_number && '' !== $new_phone_number ) {
			update_post_meta( $config_id, '_pronamic_gateway_upi_qr_bharatpe_phone_number', $new_phone_number );
		}

		//phpcs:ignore WordPress.Security.NonceVerification.Missing
		$otp = isset( $_POST['_pronamic_gateway_upi_qr_bharatpe_otp'] ) ? sanitize_text_field( $_POST['_pronamic_gateway_upi_qr_bharatpe_otp'] ) : '';
		if ( '' !== $otp ) {
			try {
				$api = new Client( $config );
				$api->verify_otp( $otp );
			} catch ( Exception $e ) {
				$this->knit_pay_post_save_notice( $e->getMessage() );
				return;
			}

			$this->get_user_info( $config_id );
			$this->get_bharatpe_connection_data( $config_id );
			return;
		}

		if ( '' === $config->token ) {
			$config = $this->get_config( $config_id );
			try {
				$api                = new Client( $config );
				$request_otp_result = $api->request_otp();
			} catch ( Exception $e ) {
				$this->knit_pay_post_save_notice( $e->getMessage() );
				return;
			}
			if ( $request_otp_result->success ) {
				update_post_meta( $config_id, '_pronamic_gateway_upi_qr_bharatpe_uuid', $request_otp_result->data->uuid );
			}
			return;
		}
	}

	// Get Merchant ID, Business Name and VPA.
	private function get_user_info( $config_id ) {
		$config = $this->get_config( $config_id );

		try {
			$api       = new Client( $config );
			$user_info = $api->get_user_info();
		} catch ( Exception $e ) {
			$this->knit_pay_post_save_notice( $e->getMessage() );
			return;
		}

		update_post_meta( $config_id, '_pronamic_gateway_upi_qr_bharatpe_merchant_id', $user_info->data->merchant_id );
		update_post_meta( $config_id, '_pronamic_gateway_upi_qr_bharatpe_token', $user_info->data->accessToken );
		update_post_meta( $config_id, '_pronamic_gateway_upi_qr_payee_name', $user_info->data->businessName );
		update_post_meta( $config_id, '_pronamic_gateway_upi_qr_payment_template', '0' );

		delete_post_meta( $config_id, '_pronamic_gateway_upi_qr_bharatpe_otp' );
		delete_post_meta( $config_id, '_pronamic_gateway_upi_qr_bharatpe_uuid' );
		delete_post_meta( $config_id, '_pronamic_gateway_upi_qr_bharatpe_bharatpe_session' );
		delete_post_meta( $config_id, '_pronamic_gateway_upi_qr_bharatpe_csrf_token' );

		$this->get_vpa( $config_id );
	}

	private function get_bharatpe_connection_data( $config_id ) {
		$config = $this->get_config( $config_id );

		try {
			$api_client               = new Client( $config );
			$bharatpe_connection_data = $api_client->get_bharatpe_connection_data();
		} catch ( Exception $e ) {
			$this->knit_pay_post_save_notice( $e->getMessage() );
			return;
		}
		
		update_post_meta( $config_id, '_pronamic_gateway_upi_qr_bharatpe_connection_data', $bharatpe_connection_data );

		wp_schedule_event(
			time(),
			'hourly',
			'knit_pay_upi_bharatpe_refresh_connection',
			[ 'config_id' => $config_id ]
		);
	}

	private function get_vpa( $config_id ) {
		// Below code can run only for php version 8.1 and above.
		if ( version_compare( PHP_VERSION, '8.1', '<' ) ) {
			return;
		}

		try {
			$config      = $this->get_config( $config_id );
			$api_client  = new Client( $config );
			$qr_code_url = $api_client->get_qr_code( $this->get_meta( $config_id, 'upi_qr_bharatpe_connection_data' ) );
			$qr_code     = new QrReader( $qr_code_url, QrReader::SOURCE_TYPE_FILE, false );
			$qr_text     = $qr_code->text();

			// Parse the UPI string to get pa parameter
			parse_str( wp_parse_url( $qr_text, PHP_URL_QUERY ), $qr_params );

			update_post_meta( $config_id, '_pronamic_gateway_upi_qr_vpa', $qr_params['pa'] );
			if ( empty( $config->payee_name ) ) {
				update_post_meta( $config_id, '_pronamic_gateway_upi_qr_payee_name', $qr_params['pn'] );
			}
		} catch ( Exception $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
			// It's okay if we don't not get the vpa, admin will enter manually, don't do anything.
		}
	}
	
	public function refresh_connection( $config_id ) {
		try {
			$config     = $this->get_config( $config_id );
			$api_client = new Client( $config );
			$api_client->get_transaction_details( $this->get_meta( $config_id, 'upi_qr_bharatpe_connection_data' ) );
		} catch ( Exception $e ) {// phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
			// Don't show error, because this might be temporary issue and it might not cause any later issue.
		}
	}
	
	public static function clear_config( $config_id ) {
		delete_post_meta( $config_id, '_pronamic_gateway_upi_qr_bharatpe_connection_data' );
		delete_post_meta( $config_id, '_pronamic_gateway_upi_qr_bharatpe_token' );
		
		wp_unschedule_hook( 'knit_pay_upi_bharatpe_refresh_connection' );
	}

	/**
	 * Field Enabled Payment Methods.
	 *
	 * @param array<string, mixed> $field Field.
	 * @return void
	 */
	public function field_send_phone_otp( $field ) {
		$config_id = KnitPayUtils::get_gateway_config_id();

		$input_phone_number = new Element(
			'input',
			[
				'id'        => '_pronamic_gateway_upi_qr_bharatpe_phone_number',
				'name'      => '_pronamic_gateway_upi_qr_bharatpe_phone_number',
				'type'      => 'text',
				'value'     => $this->get_meta( $config_id, 'upi_qr_bharatpe_phone_number' ),
				'inputmode' => 'numeric',
				'pattern'   => '\d*',
			]
		);
		$input_phone_number->output();
		
		$button_send_otp           = new Element(
			'a',
			[
				'id'    => 'bharatpe-send-phone-otp',
				'class' => 'button button-primary button-large',
				'role'  => 'button',
			]
		);
		$button_send_otp->children = [ 'Click to Send OTP' ];
		$button_send_otp->output();

		printf( '<br>Enter the 10-digit Phone number registered at BharatPe Business.' );
	}
	
	/**
	 * Field Enabled Payment Methods.
	 *
	 * @param array<string, mixed> $field Field.
	 * @return void
	 */
	public function field_submit_otp( $field ) {
		$input_otp = new Element(
			'input',
			[
				'id'        => '_pronamic_gateway_upi_qr_bharatpe_otp',
				'name'      => '_pronamic_gateway_upi_qr_bharatpe_otp',
				'type'      => 'text',
				'inputmode' => 'numeric',
				'pattern'   => '\d*',
			]
		);
		$input_otp->output();
		
		$button_submit_otp           = new Element(
			'a',
			[
				'id'    => 'bharatpe-submit-otp',
				'class' => 'button button-primary button-large',
				'role'  => 'button',
			]
		);
		$button_submit_otp->children = [ 'Submit OTP' ];
		$button_submit_otp->output();
		
		printf( '<br>Enter OTP received on phone number' );
	}
}
