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

/**
 * Generic redirect payment gateway.
 *
 * Admin configures:
 *  - name            : Label shown to customers.
 *  - payment_url     : URL template. Supports {amount}, {order_id}, {order_number},
 *                      {currency}, {return_url}, {webhook_url}.
 *  - api_key_header  : HTTP header name to pass api_key_value in (optional).
 *  - api_key_value   : Value for the above header (optional).
 *  - webhook_secret  : Shared secret for webhook verification (optional).
 *  - success_param   : GET param name the gateway appends on success, e.g. "status".
 *  - success_value   : Expected value for that param, e.g. "success".
 */
class WCP_Gateway_Custom implements WCP_Payment_Gateway_Interface {

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

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

	public function get_label(): string {
		$c = $this->config();
		return ! empty( $c['name'] ) ? $c['name'] : __( 'Custom Payment Gateway', 'woocom-pay' );
	}

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

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

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

	public function create_payment( WC_Order $order, float $amount, string $return_url ): string|WP_Error {
		$c = $this->config();

		$replacements = [
			'{amount}'      => number_format( $amount, 2, '.', '' ),
			'{order_id}'    => (string) $order->get_id(),
			'{order_number}' => $order->get_order_number(),
			'{currency}'    => 'INR',
			'{return_url}'  => rawurlencode( $return_url ),
			'{webhook_url}' => rawurlencode( home_url( '/?wc-api=woocom_pay_custom_webhook' ) ),
		];

		$url = strtr( $c['payment_url'], $replacements );

		// Optionally call the URL with an API key header first (e.g. to create a transaction).
		// If the gateway only needs a redirect with params in the URL, nothing extra is needed.

		return esc_url_raw( $url );
	}

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

	public static function handle_return(): void {
		// phpcs:disable WordPress.Security.NonceVerification.Recommended
		$order_id   = (int) ( $_GET['order_id'] ?? 0 );
		$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' ) );
		}

		$config        = ( new self() )->config();
		$success_param = $config['success_param'] ?? 'status';
		$success_value = strtolower( $config['success_value'] ?? 'success' );

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$returned_value = strtolower( sanitize_text_field( $_GET[ $success_param ] ?? '' ) );

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

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$payment_id = sanitize_text_field( $_GET['transaction_id'] ?? $_GET['txn_id'] ?? uniqid( 'custom_' ) );

		$gw_name = ( new self() )->get_label();
		WCP_Gateway_Razorpay::complete_payment( $order, $payment_id, $gw_name, $is_balance );

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

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

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

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

		if ( $webhook_secret ) {
			// Accept secret in body as 'secret' or in Authorization header.
			$body_secret   = $payload['secret'] ?? '';
			// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
			$header_secret = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
			$header_secret = str_replace( 'Bearer ', '', $header_secret );

			$provided = $body_secret ?: $header_secret;
			if ( ! hash_equals( $webhook_secret, $provided ) ) {
				status_header( 400 );
				wp_die( 'Invalid secret.' );
			}
		}

		$config        = get_option( 'woocom_pay_settings', [] );
		$success_value = strtolower( $config['gateways']['custom']['success_value'] ?? 'success' );
		$success_param = $config['gateways']['custom']['success_param'] ?? 'status';

		$returned_status = strtolower( $payload[ $success_param ] ?? '' );
		if ( $returned_status !== $success_value ) {
			status_header( 200 );
			echo 'IGNORED';
			exit;
		}

		$order_id   = (int) ( $payload['order_id'] ?? 0 );
		$payment_id = sanitize_text_field( $payload['transaction_id'] ?? $payload['txn_id'] ?? '' );
		$order      = $order_id ? wc_get_order( $order_id ) : null;

		if ( $order ) {
			$is_balance = ( $order->get_status() === 'wc-bal-pending' );
			$gw_name    = ( new self() )->get_label();
			WCP_Gateway_Razorpay::complete_payment( $order, $payment_id, $gw_name, $is_balance );
		}

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