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

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

/**
 * Razorpay gateway. Invoice-based: a payment link is emailed each cycle.
 */
class LUCRSURE_Razorpay_Gateway extends LUCRSURE_Abstract_Gateway {

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

	/**
	 * Create a Razorpay payment link for the invoice.
	 *
	 * @param array $invoice Invoice row.
	 * @return array
	 */
	public function create_payment( array $invoice ) {
		$config     = $this->config();
		$key_id     = isset( $config['key_id'] ) ? $config['key_id'] : '';
		$key_secret = isset( $config['key_secret'] ) ? $config['key_secret'] : '';

		if ( empty( $key_id ) || empty( $key_secret ) ) {
			return array(
				'success'            => false,
				'payment_url'        => '',
				'gateway_payment_id' => '',
				'message'            => __( 'Razorpay API keys are not configured.', 'lucrativeit-subscription-recurring-billing' ),
			);
		}

		$amount = (int) round( (float) $invoice['amount'] * 100 );
		$invoice_number = sanitize_text_field( (string) $invoice['invoice_number'] );

		$response = wp_remote_post(
			'https://api.razorpay.com/v1/payment_links',
			array(
				'timeout' => 30,
				'headers' => array(
					'Authorization' => 'Basic ' . base64_encode( $key_id . ':' . $key_secret ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
					'Content-Type'  => 'application/json',
				),
				'body'    => wp_json_encode(
					array(
						'amount'          => $amount,
						'currency'        => sanitize_text_field( (string) $invoice['currency'] ),
						'description'     => sanitize_text_field( 'Invoice ' . $invoice_number ),
						'reference_id'    => $invoice_number,
						'notes'           => array( 'lucrsure_invoice_number' => $invoice_number ),
						'callback_url'    => home_url( '/?lucrsure_payment=success&invoice=' . rawurlencode( $invoice_number ) . '&lucrsure_gateway=razorpay' ),
						'callback_method' => 'get',
					)
				),
			)
		);

		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['short_url'] ) ) {
			$message = isset( $body['error']['description'] ) ? sanitize_text_field( (string) $body['error']['description'] ) : __( 'Razorpay link could not be created.', 'lucrativeit-subscription-recurring-billing' );
			return array(
				'success'            => false,
				'payment_url'        => '',
				'gateway_payment_id' => '',
				'message'            => $message,
			);
		}

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

	/**
	 * Verify a Razorpay Payment Link callback signature.
	 *
	 * @param array $params {
	 *     @type string $payment_link_id
	 *     @type string $payment_link_reference_id
	 *     @type string $payment_link_status
	 *     @type string $razorpay_payment_id
	 *     @type string $razorpay_signature
	 * }
	 * @return bool
	 */
	public function verify_payment_link_signature( array $params ) {
		$config     = $this->config();
		$key_secret = isset( $config['key_secret'] ) ? (string) $config['key_secret'] : '';
		if ( '' === $key_secret ) {
			return false;
		}

		$payment_link_id         = isset( $params['payment_link_id'] ) ? (string) $params['payment_link_id'] : '';
		$payment_link_reference  = isset( $params['payment_link_reference_id'] ) ? (string) $params['payment_link_reference_id'] : '';
		$payment_link_status     = isset( $params['payment_link_status'] ) ? (string) $params['payment_link_status'] : '';
		$razorpay_payment_id     = isset( $params['razorpay_payment_id'] ) ? (string) $params['razorpay_payment_id'] : '';
		$razorpay_signature      = isset( $params['razorpay_signature'] ) ? (string) $params['razorpay_signature'] : '';

		if ( '' === $payment_link_id || '' === $razorpay_payment_id || '' === $razorpay_signature ) {
			return false;
		}

		$payload  = $payment_link_id . '|' . $payment_link_reference . '|' . $payment_link_status . '|' . $razorpay_payment_id;
		$expected = hash_hmac( 'sha256', $payload, $key_secret );

		return hash_equals( $expected, $razorpay_signature );
	}

	/**
	 * Complete a Razorpay Payment Link callback return.
	 *
	 * @param array $params Callback query params from Razorpay.
	 * @return bool
	 */
	public function complete_return( array $params ) {
		$payment_id     = isset( $params['razorpay_payment_id'] ) ? sanitize_text_field( (string) $params['razorpay_payment_id'] ) : '';
		$payment_link   = isset( $params['razorpay_payment_link_id'] ) ? sanitize_text_field( (string) $params['razorpay_payment_link_id'] ) : '';
		$reference_id   = isset( $params['razorpay_payment_link_reference_id'] ) ? sanitize_text_field( (string) $params['razorpay_payment_link_reference_id'] ) : '';
		$status         = isset( $params['razorpay_payment_link_status'] ) ? sanitize_key( (string) $params['razorpay_payment_link_status'] ) : '';
		$signature      = isset( $params['razorpay_signature'] ) ? sanitize_text_field( (string) $params['razorpay_signature'] ) : '';

		if ( '' === $payment_id || '' === $payment_link || '' === $signature ) {
			return false;
		}

		if ( ! in_array( $status, array( 'paid', 'partially_paid' ), true ) ) {
			return false;
		}

		$valid = $this->verify_payment_link_signature(
			array(
				'payment_link_id'            => $payment_link,
				'payment_link_reference_id'  => $reference_id,
				'payment_link_status'        => $status,
				'razorpay_payment_id'        => $payment_id,
				'razorpay_signature'         => $signature,
			)
		);

		if ( ! $valid ) {
			return false;
		}

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

		$invoices = new LUCRSURE_Invoice_Repository();
		$invoice  = '' !== $reference_id ? $invoices->find_by_number( $reference_id ) : null;

		if ( ! $invoice && ! empty( $params['invoice'] ) ) {
			$invoice = $invoices->find_by_number( sanitize_text_field( (string) $params['invoice'] ) );
		}

		if ( ! $invoice && $payment_link ) {
			$invoice = $invoices->find_by_gateway_payment( $payment_link );
		}

		if ( ! $invoice ) {
			return false;
		}

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

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

		return true;
	}
}
