<?php

namespace KnitPayUPI\Gateways\UpiQR\PhonePe;

use KnitPayUPI\Gateways\UpiQR\KnitPayUPIIntegration;
use Pronamic\WordPress\Html\Element;
use Pronamic\WordPress\Pay\Admin\AdminGatewayPostType;
use Exception;
use KnitPay\Utils as KnitPayUtils;

/**
 * Title: PhonePe Business Integration
 * Copyright: 2020-2026 Knit Pay
 *
 * @author  Knit Pay
 * @version 1.2.0.0
 * @since   1.2.0.0
 */
class Integration extends KnitPayUPIIntegration {
	private $config;

	/**
	 * Construct UPI QR integration.
	 *
	 * @param array $args Arguments.
	 */
	public function __construct( $args = [] ) {
		$args = wp_parse_args(
			$args,
			[
				'id'           => 'phonepe-business',
				'name'         => 'UPI/QR - PhonePe Business',
				'product_url'  => 'https://play.google.com/store/apps/details?id=com.phonepe.app.business',
				'provider'     => 'phonepe-business',
				'gateway_name' => 'PhonePe Business',
			]
		);
		
		parent::__construct( $args );
	}
	
	/**
	 * Get about settings fields.
	 *
	 * @return array
	 */
	public function get_about_settings_fields( $fields ) {
		$fields = parent::get_about_settings_fields( $fields );

		// Integration Steps.
		$fields[] = [
			'section'  => 'general',
			'type'     => 'custom',
			'title'    => 'Steps to create Supervisor Account',
			'callback' => function () {
				echo '
                <style>
                /* Container and row styling */
                .knitpay-phonepe-admin-card {
                    padding: 20px;
                    background-color: #ffffff;
                    border: 1px solid #e0e0e0;
                    border-radius: 4px;
                }

                .knitpay-phonepe-admin-row {
                    display: flex;
                    flex-wrap: wrap;
                    justify-content: space-around;
                    margin-bottom: 20px;
                }

                /* Column styling */
                .knitpay-phonepe-admin-col {
                    flex: 1 1 200px;
                    max-width: 250px;
                    margin: 10px;
                    text-align: center;
                }

                /* Image styling */
                .knitpay-phonepe-admin-col img {
                    max-width: 100%;
                    height: auto;
                    border-radius: 4px;
                }

                /* Text styling */
                .knitpay-phonepe-admin-text {
                    margin-top: 15px;
                    color: #6c757d;
                    font-size: 14px;
                }

                .knitpay-phonepe-admin-text a {
                    font-weight: 500;
                    color: #007bff;
                    text-decoration: none;
                }

                .knitpay-phonepe-admin-text a:hover {
                    text-decoration: underline;
                }

                /* Alert box styling */
                .knitpay-phonepe-admin-alert {
                    display: flex;
                    align-items: center;
                    padding: 15px;
                    background-color: #d4edda;
                    border-color: #c3e6cb;
                    border-radius: 4px;
                    color: #155724;
                    margin-top: 20px;
                }

                .knitpay-phonepe-admin-alert svg {
                    margin-right: 10px;
                }
                </style>
                ';

				$steps = [
					[
						'image'       => 'PhonePe/images/step-0.jpg',
						'description' => 'Download <a href="https://play.google.com/store/apps/details?id=com.phonepe.app.business" target="_blank">PhonePe Business App</a> on Play Store. Login or create an account in PhonePe Business App.',
					],
					[
						'image'       => 'PhonePe/images/step-1.jpg',
						'description' => 'Select the "Manage Staff" option.',
					],
					[
						'image'       => 'PhonePe/images/step-2.jpg',
						'description' => 'Now click on the "+" button.',
					],
					[
						'image'       => 'PhonePe/images/step-3.jpg',
						'description' => 'Select or enter the phone number which is not registered in the PhonePe Business App.',
					],
					[
						'image'       => 'PhonePe/images/step-4.jpg',
						'description' => 'Enter the phone number and select "Supervisor" as the user role. Now click on the "ADD USER" button.',
					],
					[
						'image'       => 'PhonePe/images/step-5.jpg',
						'description' => 'Logout from PhonePe Business App. Now enter the supervisor phone number and log in to the app.',
					],
					[
						'image'       => 'PhonePe/images/step-6.jpg',
						'description' => 'Accept as a supervisor role.',
					],
					[
						'image'       => 'PhonePe/images/step-7.jpg',
						'description' => 'Supervisor account created successfully. Now logout the supervisor account from the app.',
					],
				];

				echo '<div class="knitpay-phonepe-admin-card">
                    <div class="knitpay-phonepe-admin-row">';

				foreach ( $steps as $key => $value ) {
					echo '<div class="knitpay-phonepe-admin-col">
                            <img src="' . KNIT_PAY_UPI_URL . '/gateways/UpiQR/' . $value['image'] . '" alt="">
                            <p class="knitpay-phonepe-admin-text">' . $key + 1 . '. ' . $value['description'] . '</p>
                        </div>';
				}

				echo '</div>
                    <div class="knitpay-phonepe-admin-alert">
                        <span class="dashicons dashicons-admin-users" style="margin-right: 8px;"></span>
                        <p>Use this PhonePe Business supervisor account to accept payments at Knit Pay. Please don\'t use this account on your phone else it will get logout from Knit Pay.</p>
                    </div>
                </div>';
			},
		];

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

		if ( isset( $this->config ) && '' !== $this->config->refresh_token ) {
			$fields = parent::get_setup_settings_fields( $fields );

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

		// We don't want to save TID automatically, we want to handle it later in save_post function.
		if ( doing_action( 'save_post_' . AdminGatewayPostType::POST_TYPE ) ) {
			unset( $fields['phonepe_group_value'] );
		}
		
		return $fields;
	}
	
	private function get_login_logout_fields( $fields ) {      
		// Callback URL.
		$config_id = KnitPayUtils::get_gateway_config_id();
		if ( ! empty( $config_id ) ) {
			$this->config = $this->get_config( $config_id );
		}
		
		if ( ! isset( $this->config ) || '' !== $this->config->refresh_token ) {
			try {
				$api             = new API( $this->config );
				$group_info_list = $api->get_group_info_list();
				$account_array   = [];
				foreach ( $group_info_list as $key => $value ) {
					$account_array[ $value->userGroupNamespace->groupValue ] = $value->merchantName . " ({$value->userGroupNamespace->groupValue})";
				}
				$fields['phonepe_group_value'] = [
					'section'  => 'general',
					'meta_key' => '_pronamic_gateway_upi_qr_phonepe_group_value',
					'title'    => __( 'Group Value', 'knit-pay-upi' ),
					'type'     => 'select',
					'options'  => $account_array,
				];
			} catch ( Exception $e ) {

			}

			// TODO Show logout button
			return $fields;
		}
		
		// Registered Phone.
		$fields[] = [
			'section'  => 'general',
			'title'    => __( 'Supervisor Phone Number', 'knit-pay-upi' ),
			'type'     => 'description',
			'callback' => [ $this, 'field_send_phone_otp' ],
			'tooltip'  => __( 'Phone number of PhonePe Business Supervisor', '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>';
			},
		];
		
		return $fields;
	}
	
	/**
	 * 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 ) );

		$config->refresh_token      = $this->get_meta( $post_id, 'upi_qr_phonepe_refresh_token' );
		$config->token              = $this->get_meta( $post_id, 'upi_qr_phonepe_token' );
		$config->expires_at         = $this->get_meta( $post_id, 'upi_qr_phonepe_expires_at' );
		$config->device_fingerprint = $this->get_meta( $post_id, 'upi_qr_phonepe_device_fingerprint' );
		$config->fingerprint        = $this->get_meta( $post_id, 'upi_qr_phonepe_fingerprint' );
		$config->phone_number       = $this->get_meta( $post_id, 'upi_qr_phonepe_phone_number' );
		$config->user_group_id      = $this->get_meta( $post_id, 'upi_qr_phonepe_user_group_id' );
		$config->group_value        = $this->get_meta( $post_id, 'upi_qr_phonepe_group_value' );

		return $config;
	}
	
	/**
	 * Save post.
	 *
	 * @param int $post_id Post ID.
	 * @return void
	 */
	public function save_post( $config_id ) {
		parent::save_post( $config_id );
		
		$config = $this->get_config( $config_id );
		
		if ( '' === $config->device_fingerprint ) {
			$s1 = substr( hash( 'sha256', self::generate_random_number( 13 ) ), 0, 32 );
			$s2 = substr( hash( 'sha256', self::generate_random_number( 19 ) ), 0, 32 );
			
			$device_fingerprint = self::generate_random_string( 16 ) . 'c2RtNjM2-cWNvbQ-';
			$fingerprint        = "$s1.$s2.Xiaomi" . self::generate_random_string( 64 );
			
			update_post_meta( $config_id, '_pronamic_gateway_upi_qr_phonepe_device_fingerprint', $device_fingerprint );
			update_post_meta( $config_id, '_pronamic_gateway_upi_qr_phonepe_fingerprint', $fingerprint );
		}

		$new_phone_number = isset( $_POST['_pronamic_gateway_upi_qr_phonepe_phone_number'] ) ? sanitize_text_field( $_POST['_pronamic_gateway_upi_qr_phonepe_phone_number'] ) : '';
		if ( $new_phone_number !== $config->phone_number && '' !== $new_phone_number ) {
			update_post_meta( $config_id, '_pronamic_gateway_upi_qr_phonepe_phone_number', $new_phone_number );
		}
		
		$otp = isset( $_POST['_pronamic_gateway_upi_qr_phonepe_otp'] ) ? sanitize_text_field( $_POST['_pronamic_gateway_upi_qr_phonepe_otp'] ) : '';
		if ( '' !== $otp ) {
			try {
				$api        = new API( $config );
				$token_data = $api->login( $otp );
			} catch ( Exception $e ) {
				echo $e->getMessage();
				exit;
			}
			
			update_post_meta( $config_id, '_pronamic_gateway_upi_qr_phonepe_refresh_token', $token_data->refreshToken );
			update_post_meta( $config_id, '_pronamic_gateway_upi_qr_phonepe_token', $token_data->token );
			update_post_meta( $config_id, '_pronamic_gateway_upi_qr_phonepe_expires_at', $token_data->expiresAt - 900 );
			delete_post_meta( $config_id, '_pronamic_gateway_upi_qr_phonepe_otp' );

			// Setup First Group/Account during login.
			$this->update_group( $config_id );
			return;
		}
		
		if ( '' === $config->refresh_token ) {
			$config = $this->get_config( $config_id );
			try {
				$api             = new API( $config );
				$send_otp_result = $api->send_otp();
			} catch ( Exception $e ) {
				echo $e->getMessage();
				exit;
			}
			if ( $send_otp_result->success ) {
				update_post_meta( $config_id, '_pronamic_gateway_upi_qr_phonepe_token', $send_otp_result->data->token );
			}
			return;
		}

		// Update Group/Account if changed by admin.
		$this->update_group( $config_id );
	}

	// Update PhonePe Group/Account
	private function update_group( $config_id ) {
		$config = $this->get_config( $config_id );

		$new_group_value = isset( $_POST['_pronamic_gateway_upi_qr_phonepe_group_value'] ) ? sanitize_text_field( $_POST['_pronamic_gateway_upi_qr_phonepe_group_value'] ) : '';
		if ( '' !== $config->group_value && $new_group_value === $config->group_value ) {
			return;
		}

		try {
			$api             = new API( $config );
			$group_info_list = $api->get_group_info_list();
		} catch ( Exception $e ) {
			echo $e->getMessage();
			exit;
		}
		foreach ( $group_info_list as $value ) {
			if ( '' === $config->group_value || $value->userGroupNamespace->groupValue === $new_group_value ) {
				if ( isset( $value->userGroupNamespace->userRole->userGroupId ) ) {
					update_post_meta( $config_id, '_pronamic_gateway_upi_qr_phonepe_user_group_id', $value->userGroupNamespace->userRole->userGroupId );
				}
				update_post_meta( $config_id, '_pronamic_gateway_upi_qr_phonepe_group_value', $value->userGroupNamespace->groupValue );
				update_post_meta( $config_id, '_pronamic_gateway_upi_qr_payee_name', $value->merchantName );

				// Update session if group is changed.
				$this->update_session( $config_id );
			}
		}
	}

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

		try {
			$new_api            = new API( $config );
			$session_token_data = $new_api->update_session();
		} catch ( Exception $e ) {
			echo $e->getMessage();
			exit;
		}

		update_post_meta( $config_id, '_pronamic_gateway_upi_qr_phonepe_refresh_token', $session_token_data->refreshToken );
		update_post_meta( $config_id, '_pronamic_gateway_upi_qr_phonepe_token', $session_token_data->token );
		update_post_meta( $config_id, '_pronamic_gateway_upi_qr_phonepe_expires_at', $session_token_data->expiresAt - 900 );
		return;
	}

	/**
	 * 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_phonepe_phone_number',
				'name'      => '_pronamic_gateway_upi_qr_phonepe_phone_number',
				'type'      => 'text',
				'value'     => $this->get_meta( $config_id, 'upi_qr_phonepe_phone_number' ),
				'inputmode' => 'numeric',
				'pattern'   => '\d*',
			]
		);
		$input_phone_number->output();
		
		$button_send_otp           = new Element(
			'a',
			[
				'id'    => 'phonepe-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 Supervisor Phone number registered at PhonePe Business. Read the steps above to know how to create a supervisor account.' );
	}
	
	/**
	 * 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_phonepe_otp',
				'name'      => '_pronamic_gateway_upi_qr_phonepe_otp',
				'type'      => 'text',
				'inputmode' => 'numeric',
				'pattern'   => '\d*',
			]
		);
		$input_otp->output();
		
		$button_submit_otp           = new Element(
			'a',
			[
				'id'    => 'phonepe-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 supervisor phone number' );
	}
	
	private static function generate_random_string( $length = 16 ) {
		$characters    = '0123456789abcdef';
		$random_string = '';
		
		for ( $i = 0; $i < $length; $i++ ) {
			$random_string .= $characters[ rand( 0, strlen( $characters ) - 1 ) ];
		}
		
		return $random_string;
	}
	
	private static function generate_random_number( $length ) {
		$str = '';
		for ( $i = 0; $i < $length; $i++ ) {
			$str .= mt_rand( 0, 9 );
		}
		return $str;
	}
}
