<?php
/**
 * SSLCommerz payment gateway (invoice-based).
 *
 * @package Lucrativeit_Subscription_Recurring_Billing
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * SSLCommerz gateway. Invoice-based: a payment link is emailed each cycle and
 * the customer must pay manually. Does not support automatic recurring.
 */
class LUCRSURE_SSLCommerz_Gateway extends LUCRSURE_Abstract_Gateway {

	/**
	 * Constructor.
	 */
	public function __construct() {
		$this->id                  = 'sslcommerz';
		$this->title               = __( 'SSLCommerz', 'lucrativeit-subscription-recurring-billing' );
		$this->automatic_recurring = false;
	}

	/**
	 * Initiate an SSLCommerz session for the invoice.
	 *
	 * @param array $invoice Invoice row.
	 * @return array
	 */
	public function create_payment( array $invoice ) {
		$config   = $this->config();
		$store_id = isset( $config['store_id'] ) ? $config['store_id'] : '';
		$store_pw = isset( $config['store_password'] ) ? $config['store_password'] : '';
		$sandbox  = ! empty( $config['sandbox'] );

		if ( empty( $store_id ) || empty( $store_pw ) ) {
			return array(
				'success'            => false,
				'payment_url'        => '',
				'gateway_payment_id' => '',
				'message'            => __( 'SSLCommerz store credentials are not configured.', 'lucrativeit-subscription-recurring-billing' ),
			);
		}

		$endpoint = $sandbox
			? 'https://sandbox.sslcommerz.com/gwprocess/v4/api.php'
			: 'https://securepay.sslcommerz.com/gwprocess/v4/api.php';

		$response = wp_remote_post(
			$endpoint,
			array(
				'timeout' => 30,
				'body'    => array(
					'store_id'         => sanitize_text_field( (string) $store_id ),
					'store_passwd'     => (string) $store_pw,
					'total_amount'     => number_format( (float) $invoice['amount'], 2, '.', '' ),
					'currency'         => sanitize_text_field( (string) $invoice['currency'] ),
					'tran_id'          => sanitize_text_field( (string) $invoice['invoice_number'] ),
					'success_url'      => home_url( '/?lucrsure_payment=success&invoice=' . rawurlencode( (string) $invoice['invoice_number'] ) . '&lucrsure_gateway=sslcommerz' ),
					'fail_url'         => home_url( '/?lucrsure_payment=fail&invoice=' . rawurlencode( (string) $invoice['invoice_number'] ) . '&lucrsure_gateway=sslcommerz' ),
					'cancel_url'       => home_url( '/?lucrsure_payment=cancel&invoice=' . rawurlencode( (string) $invoice['invoice_number'] ) . '&lucrsure_gateway=sslcommerz' ),
					'cus_name'         => sanitize_text_field( isset( $invoice['customer_name'] ) ? (string) $invoice['customer_name'] : 'Customer' ),
					'cus_email'        => sanitize_email( isset( $invoice['customer_email'] ) ? (string) $invoice['customer_email'] : '' ),
					'cus_add1'         => sanitize_text_field( isset( $invoice['billing_address_1'] ) ? (string) $invoice['billing_address_1'] : 'N/A' ),
					'cus_add2'         => sanitize_text_field( isset( $invoice['billing_address_2'] ) ? (string) $invoice['billing_address_2'] : '' ),
					'cus_city'         => sanitize_text_field( isset( $invoice['billing_city'] ) ? (string) $invoice['billing_city'] : 'N/A' ),
					'cus_state'        => sanitize_text_field( isset( $invoice['billing_state'] ) ? (string) $invoice['billing_state'] : 'N/A' ),
					'cus_postcode'     => sanitize_text_field( isset( $invoice['billing_postcode'] ) ? (string) $invoice['billing_postcode'] : 'N/A' ),
					'cus_country'      => sanitize_text_field( isset( $invoice['billing_country'] ) ? (string) $invoice['billing_country'] : 'Bangladesh' ),
					'product_name'     => sanitize_text_field( 'Invoice ' . $invoice['invoice_number'] ),
					'product_category' => 'subscription',
					'product_profile'  => 'general',
					'shipping_method'  => 'NO',
				),
			)
		);

		if ( is_wp_error( $response ) ) {
			return array(
				'success'            => false,
				'payment_url'        => '',
				'gateway_payment_id' => '',
				'message'            => $response->get_error_message(),
			);
		}

		$body = json_decode( wp_remote_retrieve_body( $response ), true );

		if ( empty( $body['GatewayPageURL'] ) ) {
			return array(
				'success'            => false,
				'payment_url'        => '',
				'gateway_payment_id' => '',
				'message'            => isset( $body['failedreason'] ) ? sanitize_text_field( (string) $body['failedreason'] ) : __( 'SSLCommerz session failed.', 'lucrativeit-subscription-recurring-billing' ),
			);
		}

		return array(
			'success'            => true,
			'payment_url'        => esc_url_raw( (string) $body['GatewayPageURL'] ),
			'gateway_payment_id' => isset( $body['sessionkey'] ) ? sanitize_text_field( (string) $body['sessionkey'] ) : '',
			'message'            => __( 'SSLCommerz payment link created.', 'lucrativeit-subscription-recurring-billing' ),
		);
	}

	/**
	 * Validate an SSLCommerz transaction via their validator API.
	 *
	 * @param string $val_id Validation id from SSLCommerz.
	 * @return bool
	 */
	public function validate_transaction( $val_id ) {
		$val_id   = sanitize_text_field( (string) $val_id );
		$config   = $this->config();
		$store_id = isset( $config['store_id'] ) ? sanitize_text_field( (string) $config['store_id'] ) : '';
		$store_pw = isset( $config['store_password'] ) ? (string) $config['store_password'] : '';
		$sandbox  = ! empty( $config['sandbox'] );

		if ( '' === $val_id || '' === $store_id || '' === $store_pw ) {
			return false;
		}

		$base = $sandbox
			? 'https://sandbox.sslcommerz.com/validator/api/validationserverAPI.php'
			: 'https://securepay.sslcommerz.com/validator/api/validationserverAPI.php';

		$url = add_query_arg(
			array(
				'val_id'       => $val_id,
				'store_id'     => $store_id,
				'store_passwd' => $store_pw,
				'format'       => 'json',
			),
			$base
		);

		$response = wp_remote_get( $url, array( 'timeout' => 30 ) );
		if ( is_wp_error( $response ) ) {
			return false;
		}

		$body = json_decode( wp_remote_retrieve_body( $response ), true );
		return isset( $body['status'] ) && in_array( $body['status'], array( 'VALID', 'VALIDATED' ), true );
	}

	/**
	 * Complete an SSLCommerz return/IPN-style confirmation.
	 *
	 * @param string $tran_id Merchant transaction id (our invoice number).
	 * @param string $val_id  SSLCommerz validation id.
	 * @return bool
	 */
	public function complete_return( $tran_id, $val_id ) {
		$tran_id = sanitize_text_field( (string) $tran_id );
		$val_id  = sanitize_text_field( (string) $val_id );

		if ( '' === $tran_id || '' === $val_id ) {
			return false;
		}

		if ( ! $this->validate_transaction( $val_id ) ) {
			return false;
		}

		if ( ! class_exists( 'LUCRSURE_Invoice_Repository' ) || ! class_exists( 'LUCRSURE_Billing_Engine' ) ) {
			return false;
		}

		$invoices = new LUCRSURE_Invoice_Repository();
		$invoice  = $invoices->find_by_number( $tran_id );
		if ( ! $invoice ) {
			return false;
		}

		$invoices->update(
			(int) $invoice['id'],
			array( 'gateway_payment_id' => $val_id )
		);

		LUCRSURE_Billing_Engine::instance()->mark_invoice_paid( (int) $invoice['id'] );

		return true;
	}
}
