<?php
defined( 'ABSPATH' ) || exit;

class WCP_Gateway_Razorpay implements WCP_Payment_Gateway_Interface {

	private function config(): array {
		$s = get_option( 'woocom_pay_settings', [] );
		return $s['gateways']['razorpay'] ?? [];
	}

	public function get_id(): string {
		return 'razorpay';
	}

	public function get_label(): string {
		return __( 'Razorpay (Cards · UPI · NetBanking · Wallets)', 'woocom-pay' );
	}

	public function is_enabled(): bool {
		return ! empty( $this->config()['enabled'] );
	}

	public function is_configured(): bool {
		$c = $this->config();
		return ! empty( $c['key_id'] ) && ! empty( $c['key_secret'] );
	}

	private function api_base(): string {
		return 'https://api.razorpay.com/v1';
	}

	private function auth_header(): string {
		$c = $this->config();
		return 'Basic ' . base64_encode( $c['key_id'] . ':' . $c['key_secret'] );
	}

	// -------------------------------------------------------------------------

	public function create_payment( WC_Order $order, float $amount, string $return_url ): string|WP_Error {
		$phone = preg_replace( '/[^0-9+]/', '', $order->get_billing_phone() );
		if ( strlen( $phone ) < 10 ) {
			$phone = '+919999999999';
		}

		$payload = [
			'amount'          => (int) round( $amount * 100 ),
			'currency'        => 'INR',
			'description'     => sprintf( __( 'Order #%s', 'woocom-pay' ), $order->get_order_number() ),
			'customer'        => [
				'name'    => trim( $order->get_billing_first_name() . ' ' . $order->get_billing_last_name() ),
				'email'   => $order->get_billing_email(),
				'contact' => $phone,
			],
			'callback_url'    => $return_url,
			'callback_method' => 'get',
			'notify'          => [ 'sms' => true, 'email' => true ],
			'notes'           => [
				'wc_order_id'     => (string) $order->get_id(),
				'wc_order_number' => $order->get_order_number(),
			],
		];

		$response = wp_remote_post(
			$this->api_base() . '/payment_links',
			[
				'headers' => [
					'Authorization' => $this->auth_header(),
					'Content-Type'  => 'application/json',
				],
				'body'    => wp_json_encode( $payload ),
				'timeout' => 30,
			]
		);

		if ( is_wp_error( $response ) ) {
			return $response;
		}

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

		if ( $code !== 200 || empty( $body['short_url'] ) ) {
			$msg = $body['error']['description'] ?? __( 'Razorpay: could not create payment link.', 'woocom-pay' );
			return new WP_Error( 'razorpay_error', $msg );
		}

		$order->update_meta_data( '_wcp_razorpay_link_id', $body['id'] );
		$order->save();

		return $body['short_url'];
	}

	// -------------------------------------------------------------------------
	// Return handler (WC API hook: woocommerce_api_woocom_pay_razorpay)
	// -------------------------------------------------------------------------

	public static function handle_return(): void {
		// phpcs:disable WordPress.Security.NonceVerification.Recommended
		$order_id   = (int) ( $_GET['order_id'] ?? 0 );
		$status     = sanitize_text_field( $_GET['razorpay_payment_link_status'] ?? '' );
		$payment_id = sanitize_text_field( $_GET['razorpay_payment_id'] ?? '' );
		$link_id    = sanitize_text_field( $_GET['razorpay_payment_link_id'] ?? '' );
		$ref_id     = sanitize_text_field( $_GET['razorpay_payment_link_reference_id'] ?? '' );
		$signature  = sanitize_text_field( $_GET['razorpay_signature'] ?? '' );
		$is_balance = ! empty( $_GET['balance'] );
		// phpcs:enable WordPress.Security.NonceVerification.Recommended

		$order = $order_id ? wc_get_order( $order_id ) : null;
		if ( ! $order ) {
			wp_die( esc_html__( 'Order not found.', 'woocom-pay' ) );
		}

		if ( $status !== 'paid' ) {
			wc_add_notice( __( 'Payment was not completed. Please try again.', 'woocom-pay' ), 'error' );
			wp_safe_redirect( wc_get_checkout_url() );
			exit;
		}

		// Verify Razorpay signature.
		$config     = ( new self() )->config();
		$key_secret = $config['key_secret'] ?? '';
		if ( $key_secret && $signature && $link_id ) {
			$expected = hash_hmac( 'sha256', "{$link_id}|{$ref_id}|{$status}|{$payment_id}", $key_secret );
			if ( ! hash_equals( $expected, $signature ) ) {
				wp_die( esc_html__( 'Payment signature verification failed.', 'woocom-pay' ) );
			}
		}

		self::complete_payment( $order, $payment_id, 'razorpay', $is_balance );

		wp_safe_redirect( $order->get_checkout_order_received_url() );
		exit;
	}

	// -------------------------------------------------------------------------
	// Webhook handler (WC API hook: woocommerce_api_woocom_pay_razorpay_webhook)
	// -------------------------------------------------------------------------

	public static function handle_webhook(): void {
		$raw_body = file_get_contents( 'php://input' );
		$payload  = json_decode( $raw_body, true );

		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
		$signature = $_SERVER['HTTP_X_RAZORPAY_SIGNATURE'] ?? '';

		$config         = get_option( 'woocom_pay_settings', [] );
		$webhook_secret = $config['gateways']['razorpay']['webhook_secret'] ?? '';

		if ( $webhook_secret && $signature ) {
			$expected = hash_hmac( 'sha256', $raw_body, $webhook_secret );
			if ( ! hash_equals( $expected, $signature ) ) {
				status_header( 400 );
				wp_die( 'Invalid signature.' );
			}
		}

		$event = $payload['event'] ?? '';

		if ( $event === 'payment_link.paid' ) {
			$notes      = $payload['payload']['payment_link']['entity']['notes'] ?? [];
			$order_id   = (int) ( $notes['wc_order_id'] ?? 0 );
			$payment_id = $payload['payload']['payment']['entity']['id'] ?? '';
			$order      = $order_id ? wc_get_order( $order_id ) : null;

			if ( $order ) {
				// Balance payment has '_wcp_balance_amount' > 0 and original status 'bal-pending'.
				$is_balance = ( $order->get_status() === 'wc-bal-pending' );
				self::complete_payment( $order, $payment_id, 'razorpay', $is_balance );
			}
		}

		status_header( 200 );
		echo 'OK';
		exit;
	}

	// -------------------------------------------------------------------------
	// Shared payment completion logic
	// -------------------------------------------------------------------------

	public static function complete_payment( WC_Order $order, string $payment_id, string $gateway_label, bool $is_balance ): void {
		// Idempotent: skip if order is already in a terminal payment state.
		$skip_statuses = [ 'wc-pay-verified', 'wc-bal-pending', 'wc-completed', 'wc-processing' ];
		if ( ! $is_balance && in_array( 'wc-' . $order->get_status(), $skip_statuses, true ) ) {
			return;
		}

		$settings = get_option( 'woocom_pay_settings', [] );
		$items    = $order->get_items();
		$first    = reset( $items );
		$product_id = $first ? (int) $first->get_product_id() : 0;

		if ( $is_balance ) {
			$balance = (float) $order->get_meta( '_wcp_balance_amount' );

			Woocom_Pay_DB::insert( [
				'order_id'            => $order->get_id(),
				'customer_id'         => (int) $order->get_customer_id(),
				'product_id'          => $product_id,
				'payment_type'        => 'balance',
				'product_price'       => (float) $order->get_meta( '_wcp_product_total' ),
				'paid_amount'         => $balance,
				'balance_amount'      => 0,
				'transaction_id'      => $payment_id,
				'screenshot_path'     => '',
				'remarks'             => 'Auto-verified via ' . $gateway_label,
				'verification_status' => 'approved',
			] );

			$order->update_meta_data( '_wcp_balance_amount', 0 );
			$order->update_status(
				'completed',
				sprintf( __( 'Balance payment of %1$s received via %2$s (ID: %3$s).', 'woocom-pay' ), wc_price( $balance ), $gateway_label, $payment_id )
			);
			$order->payment_complete( $payment_id );
			$order->save();
			Woocom_Pay_Emails::send_customer_payment_approved( $order );
			return;
		}

		$has_partial   = $order->get_meta( '_wcp_has_partial' );
		$paid_amount   = $has_partial ? (float) $order->get_meta( '_wcp_paid_amount' ) : (float) $order->get_total();
		$balance       = $has_partial ? (float) $order->get_meta( '_wcp_balance_amount' ) : 0.0;
		$product_total = $has_partial ? (float) $order->get_meta( '_wcp_product_total' ) : $paid_amount;
		$payment_type  = $has_partial ? 'partial' : 'full';

		Woocom_Pay_DB::insert( [
			'order_id'            => $order->get_id(),
			'customer_id'         => (int) $order->get_customer_id(),
			'product_id'          => $product_id,
			'payment_type'        => $payment_type,
			'product_price'       => $product_total,
			'paid_amount'         => $paid_amount,
			'balance_amount'      => $balance,
			'transaction_id'      => $payment_id,
			'screenshot_path'     => '',
			'remarks'             => 'Auto-verified via ' . $gateway_label,
			'verification_status' => 'approved',
		] );

		if ( $payment_type === 'partial' ) {
			$order->update_status(
				'bal-pending',
				sprintf( __( 'Advance of %1$s received via %2$s (ID: %3$s). Balance due.', 'woocom-pay' ), wc_price( $paid_amount ), $gateway_label, $payment_id )
			);
		} else {
			$order->update_status(
				'pay-verified',
				sprintf( __( 'Full payment of %1$s received via %2$s (ID: %3$s).', 'woocom-pay' ), wc_price( $paid_amount ), $gateway_label, $payment_id )
			);
			$order->payment_complete( $payment_id );
		}

		$order->save();
		Woocom_Pay_Emails::send_customer_payment_approved( $order );
	}
}
