<?php
/**
 * Shared helpers for form-plugin hosted checkout sessions.
 *
 * @package SHC4WC
 */

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

class SHC4WC_Hosted_Checkout_Flow {

	/**
	 * @param string $prefix Channel prefix (e.g. ninjaforms).
	 * @return string
	 */
	public static function create_ref( $prefix ) {
		return sanitize_key( $prefix ) . '_' . wp_generate_password( 16, false, false );
	}

	/**
	 * @param string $ref Reference id.
	 * @return string
	 */
	public static function create_key( $ref ) {
		return wp_hash( $ref . wp_salt( 'auth' ) );
	}

	/**
	 * @param string $ref Reference id.
	 * @param string $key Return key.
	 * @return bool
	 */
	public static function verify_key( $ref, $key ) {
		$ref = sanitize_text_field( (string) $ref );
		$key = sanitize_text_field( (string) $key );
		if ( '' === $ref || '' === $key ) {
			return false;
		}
		return hash_equals( self::create_key( $ref ), $key );
	}

	/**
	 * @param string $type Channel type.
	 * @param string $ref  Reference id.
	 * @return string
	 */
	public static function transient_name( $type, $ref ) {
		return 'shc4wc_' . sanitize_key( $type ) . '_' . sanitize_text_field( $ref );
	}

	/**
	 * @return string|null Error message or null when connected.
	 */
	public static function connection_error_message() {
		if ( ! SHC4WC_Plugin::is_connected() ) {
			return __( 'Square is not connected. Ask the site administrator to connect under Payments Square Connect.', 'payments-connect-square' );
		}

		$settings    = SHC4WC_Plugin::get_settings();
		$location_id = isset( $settings['location_id'] ) ? trim( (string) $settings['location_id'] ) : '';
		if ( '' === $location_id ) {
			return __( 'Square location is not configured.', 'payments-connect-square' );
		}

		return null;
	}

	/**
	 * @return string
	 */
	public static function default_currency() {
		if ( function_exists( 'get_woocommerce_currency' ) ) {
			return get_woocommerce_currency();
		}
		return 'USD';
	}

	/**
	 * @param array $response Square API response.
	 * @return string
	 */
	public static function extract_square_order_id( array $response ) {
		if ( ! empty( $response['related_resources']['orders'][0]['id'] ) ) {
			return sanitize_text_field( (string) $response['related_resources']['orders'][0]['id'] );
		}
		if ( ! empty( $response['payment_link']['order_id'] ) ) {
			return sanitize_text_field( (string) $response['payment_link']['order_id'] );
		}
		return '';
	}

	/**
	 * Start a one-time hosted checkout session.
	 *
	 * @param array $args {
	 *     @type string $type        Return router type.
	 *     @type float  $amount      Charge amount.
	 *     @type string $currency    ISO currency.
	 *     @type string $description Payment description.
	 *     @type string $line_name   Line item label.
	 *     @type array  $customer    Buyer prefill.
	 *     @type array  $payload     Data stored until return.
	 * }
	 * @return array{redirect:string,ref:string,key:string}|WP_Error
	 */
	public static function start_one_time_payment( array $args ) {
		$error = self::connection_error_message();
		if ( null !== $error ) {
			return new WP_Error( 'shc4wc_not_connected', $error );
		}

		$amount = isset( $args['amount'] ) ? (float) $args['amount'] : 0;
		if ( $amount <= 0 ) {
			return new WP_Error( 'shc4wc_invalid_amount', __( 'Enter a valid payment amount.', 'payments-connect-square' ) );
		}

		$type     = sanitize_key( (string) ( $args['type'] ?? '' ) );
		$currency = ! empty( $args['currency'] ) ? (string) $args['currency'] : self::default_currency();
		$ref      = self::create_ref( $type );
		$key      = self::create_key( $ref );
		$settings = SHC4WC_Plugin::get_settings();
		$api      = new SHC4WC_API( $settings );

		$response = $api->create_payment_link(
			$amount,
			$currency,
			$ref,
			array(
				'description' => (string) ( $args['description'] ?? '' ),
				'return_args' => array(
					'type' => $type,
					'ref'  => $ref,
					'key'  => $key,
				),
				'line_name'   => (string) ( $args['line_name'] ?? '' ),
				'customer'    => isset( $args['customer'] ) && is_array( $args['customer'] ) ? $args['customer'] : array(),
			)
		);

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

		$link = isset( $response['payment_link']['url'] ) ? esc_url_raw( $response['payment_link']['url'] ) : '';
		if ( '' === $link ) {
			return new WP_Error( 'shc4wc_invalid_response', __( 'Invalid response from Square.', 'payments-connect-square' ) );
		}

		$payload = isset( $args['payload'] ) && is_array( $args['payload'] ) ? $args['payload'] : array();
		$payload['ref']             = $ref;
		$payload['amount']          = $amount;
		$payload['currency']        = $currency;
		$payload['link_id']         = isset( $response['payment_link']['id'] ) ? (string) $response['payment_link']['id'] : '';
		$payload['square_order_id'] = self::extract_square_order_id( $response );

		set_transient( self::transient_name( $type, $ref ), $payload, DAY_IN_SECONDS );

		return array(
			'redirect' => $link,
			'ref'      => $ref,
			'key'      => $key,
		);
	}

	/**
	 * Start a subscription hosted checkout session (Square creates the subscription).
	 *
	 * @param array $args {
	 *     @type string $type              Return router type.
	 *     @type float  $amount            Initial checkout amount.
	 *     @type string $currency          ISO currency.
	 *     @type string $description       Payment description.
	 *     @type string $line_name         Line item label.
	 *     @type string $plan_variation_id Square subscription plan variation id.
	 *     @type array  $customer          Buyer prefill.
	 *     @type array  $payload           Data stored until return.
	 * }
	 * @return array{redirect:string,ref:string,key:string}|WP_Error
	 */
	public static function start_subscription_payment( array $args ) {
		$error = self::connection_error_message();
		if ( null !== $error ) {
			return new WP_Error( 'shc4wc_not_connected', $error );
		}

		$amount = isset( $args['amount'] ) ? (float) $args['amount'] : 0;
		if ( $amount <= 0 ) {
			return new WP_Error( 'shc4wc_invalid_amount', __( 'Enter a valid payment amount.', 'payments-connect-square' ) );
		}

		$plan_variation_id = ! empty( $args['plan_variation_id'] ) ? sanitize_text_field( (string) $args['plan_variation_id'] ) : '';
		if ( '' === $plan_variation_id ) {
			return new WP_Error( 'shc4wc_no_subscription_plan', __( 'Square subscription plan variation id missing.', 'payments-connect-square' ) );
		}

		$type     = sanitize_key( (string) ( $args['type'] ?? '' ) );
		$currency = ! empty( $args['currency'] ) ? (string) $args['currency'] : self::default_currency();
		$ref      = self::create_ref( $type );
		$key      = self::create_key( $ref );
		$settings = SHC4WC_Plugin::get_settings();
		$api      = new SHC4WC_API( $settings );

		$response = $api->create_subscription_payment_link(
			$amount,
			$currency,
			$ref,
			$plan_variation_id,
			array(
				'description' => (string) ( $args['description'] ?? '' ),
				'return_args' => array(
					'type' => $type,
					'ref'  => $ref,
					'key'  => $key,
				),
				'line_name'   => (string) ( $args['line_name'] ?? '' ),
				'customer'    => isset( $args['customer'] ) && is_array( $args['customer'] ) ? $args['customer'] : array(),
			)
		);

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

		$link = isset( $response['payment_link']['url'] ) ? esc_url_raw( $response['payment_link']['url'] ) : '';
		if ( '' === $link ) {
			return new WP_Error( 'shc4wc_invalid_response', __( 'Invalid response from Square.', 'payments-connect-square' ) );
		}

		$payload = isset( $args['payload'] ) && is_array( $args['payload'] ) ? $args['payload'] : array();
		$payload['ref']                  = $ref;
		$payload['amount']               = $amount;
		$payload['currency']             = $currency;
		$payload['link_id']              = isset( $response['payment_link']['id'] ) ? (string) $response['payment_link']['id'] : '';
		$payload['square_order_id']      = self::extract_square_order_id( $response );
		$payload['plan_variation_id']    = $plan_variation_id;
		$payload['is_recurring']         = true;

		set_transient( self::transient_name( $type, $ref ), $payload, DAY_IN_SECONDS );

		return array(
			'redirect' => $link,
			'ref'      => $ref,
			'key'      => $key,
		);
	}

	/**
	 * @param string $type Channel type.
	 * @param string $ref  Reference id.
	 * @param string $key  Return key.
	 * @return array|false
	 */
	public static function pull_pending( $type, $ref, $key ) {
		if ( ! self::verify_key( $ref, $key ) ) {
			return false;
		}

		$stored = get_transient( self::transient_name( $type, $ref ) );
		if ( ! is_array( $stored ) ) {
			return false;
		}

		delete_transient( self::transient_name( $type, $ref ) );
		return $stored;
	}

	/**
	 * @param string $url Form/page URL.
	 * @param string $arg Query arg without value.
	 * @return string
	 */
	public static function add_paid_query_arg( $url, $arg ) {
		return add_query_arg( sanitize_key( $arg ), '1', $url );
	}

	/**
	 * @param string $html Success message HTML.
	 * @return void
	 */
	public static function render_success_notice( $html ) {
		printf(
			'<div class="shc4wc-form-payment-success" role="status">%s</div>',
			wp_kses_post( $html )
		);
	}

	/**
	 * @return void
	 */
	public static function enqueue_success_styles() {
		$css = '.shc4wc-form-payment-success{display:block !important;margin:0 0 1.5em;padding:1em 1.25em;border:2px solid #46b450;background:#ecf7ed;color:#1e4620;border-radius:4px;}';
		wp_register_style( 'shc4wc-form-payment-success', false, array(), SHC4WC_VERSION );
		wp_enqueue_style( 'shc4wc-form-payment-success' );
		wp_add_inline_style( 'shc4wc-form-payment-success', $css );
	}
}
