<?php
/**
 * Standalone Square payment link shortcode and block.
 *
 * @package SHC4WC
 */

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

class SHC4WC_Payment_Link {
	const SHORTCODE = 'square_payment_link';
	const BLOCK     = 'shc4wc/payment-link';

	/** @var self|null */
	private static $instance = null;

	public static function instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	private function __construct() {
		add_shortcode( self::SHORTCODE, array( $this, 'render_shortcode' ) );
		add_shortcode( 'square_pay_link', array( $this, 'render_shortcode' ) );
		add_action( 'init', array( $this, 'register_block' ) );
		add_action( 'template_redirect', array( $this, 'maybe_start_payment' ), 5 );
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_styles' ) );
		add_filter( 'the_content', array( $this, 'maybe_prepend_success_notice' ), 5 );
	}

	/**
	 * @param array|string $atts Shortcode attributes.
	 * @return string
	 */
	public function render_shortcode( $atts ) {
		$atts = shortcode_atts(
			array(
				'amount'      => '',
				'label'       => __( 'Pay Now', 'payments-connect-square' ),
				'description' => '',
				'class'       => '',
				'currency'    => '',
			),
			$atts,
			self::SHORTCODE
		);

		return $this->render_button( $atts );
	}

	/**
	 * @param array<string, string> $atts Button attributes.
	 * @return string
	 */
	public function render_button( array $atts ) {
		/**
		 * Filter payment link button attributes before render.
		 *
		 * @param array<string, string> $atts Button attributes.
		 */
		$atts = apply_filters( 'shc4wc_payment_link_button_atts', $atts );

		$amount = $this->parse_amount( $atts['amount'] ?? '' );
		if ( $amount <= 0 ) {
			return '<p class="shc4wc-payment-link-notice">' . esc_html__( 'Square payment link: enter a valid amount.', 'payments-connect-square' ) . '</p>';
		}

		if ( ! SHC4WC_Plugin::is_connected() ) {
			return '<p class="shc4wc-payment-link-notice">' . esc_html__( 'Square payments are not configured yet.', 'payments-connect-square' ) . '</p>';
		}

		$label       = sanitize_text_field( (string) ( $atts['label'] ?? __( 'Pay Now', 'payments-connect-square' ) ) );
		$description = sanitize_text_field( (string) ( $atts['description'] ?? '' ) );
		$class       = sanitize_html_class( (string) ( $atts['class'] ?? '' ) );
		$currency    = $this->resolve_currency( $atts['currency'] ?? '' );
		$return_url  = $this->get_current_page_url();

		$url = add_query_arg(
			array(
				'shc4wc_pay'         => '1',
				'shc4wc_pay_amount'  => rawurlencode( (string) $amount ),
				'shc4wc_pay_desc'    => rawurlencode( $description ),
				'shc4wc_pay_currency'=> rawurlencode( $currency ),
				'shc4wc_pay_return'  => rawurlencode( $return_url ),
				'shc4wc_pay_nonce'   => wp_create_nonce( 'shc4wc_pay_' . $amount ),
			),
			$return_url
		);

		$classes = trim( 'shc4wc-payment-link-button button ' . $class );

		return sprintf(
			'<p class="shc4wc-payment-link-wrap"><a class="%1$s" href="%2$s">%3$s</a></p>',
			esc_attr( $classes ),
			esc_url( $url ),
			esc_html( $label )
		);
	}

	public function register_block() {
		if ( ! function_exists( 'register_block_type' ) ) {
			return;
		}

		wp_register_script(
			'shc4wc-payment-link-editor',
			SHC4WC_PLUGIN_URL . 'assets/js/payment-link-block.js',
			array( 'wp-blocks', 'wp-element', 'wp-block-editor', 'wp-components', 'wp-i18n' ),
			SHC4WC_VERSION,
			true
		);

		register_block_type(
			self::BLOCK,
			array(
				'api_version'     => 2,
				'title'           => __( 'Square Payment Link', 'payments-connect-square' ),
				'description'     => __( 'Button that sends visitors to Square Hosted Checkout to pay a fixed amount.', 'payments-connect-square' ),
				'category'        => 'widgets',
				'icon'            => 'money-alt',
				'keywords'        => array( 'square', 'payment', 'pay', 'checkout' ),
				'editor_script'   => 'shc4wc-payment-link-editor',
				'render_callback' => array( $this, 'render_block' ),
				'attributes'      => array(
					'amount'      => array(
						'type'    => 'string',
						'default' => '25.00',
					),
					'label'       => array(
						'type'    => 'string',
						'default' => __( 'Pay Now', 'payments-connect-square' ),
					),
					'description' => array(
						'type'    => 'string',
						'default' => '',
					),
					'className'   => array(
						'type' => 'string',
					),
					'currency'    => array(
						'type'    => 'string',
						'default' => '',
					),
				),
			)
		);
	}

	/**
	 * @param array<string, mixed> $attributes Block attributes.
	 * @return string
	 */
	public function render_block( $attributes ) {
		$attributes = is_array( $attributes ) ? $attributes : array();

		return $this->render_button(
			array(
				'amount'      => isset( $attributes['amount'] ) ? (string) $attributes['amount'] : '',
				'label'       => isset( $attributes['label'] ) ? (string) $attributes['label'] : '',
				'description' => isset( $attributes['description'] ) ? (string) $attributes['description'] : '',
				'class'       => ! empty( $attributes['className'] ) ? (string) $attributes['className'] : '',
				'currency'    => isset( $attributes['currency'] ) ? (string) $attributes['currency'] : '',
			)
		);
	}

	public function maybe_start_payment() {
		if ( empty( $_GET['shc4wc_pay'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			return;
		}

		$amount = isset( $_GET['shc4wc_pay_amount'] ) ? $this->parse_amount( wp_unslash( $_GET['shc4wc_pay_amount'] ) ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( $amount <= 0 ) {
			wp_die( esc_html__( 'Invalid payment amount.', 'payments-connect-square' ), 400 );
		}

		$nonce = isset( $_GET['shc4wc_pay_nonce'] ) ? sanitize_text_field( wp_unslash( $_GET['shc4wc_pay_nonce'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( ! wp_verify_nonce( $nonce, 'shc4wc_pay_' . $amount ) ) {
			wp_die( esc_html__( 'Invalid payment request.', 'payments-connect-square' ), 403 );
		}

		if ( ! SHC4WC_Plugin::is_connected() ) {
			wp_die( esc_html__( 'Square is not connected.', 'payments-connect-square' ), 503 );
		}

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

		$description = isset( $_GET['shc4wc_pay_desc'] ) ? sanitize_text_field( wp_unslash( $_GET['shc4wc_pay_desc'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$currency    = isset( $_GET['shc4wc_pay_currency'] ) ? sanitize_text_field( wp_unslash( $_GET['shc4wc_pay_currency'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$currency    = $this->resolve_currency( $currency );
		$return_url  = isset( $_GET['shc4wc_pay_return'] ) ? esc_url_raw( wp_unslash( $_GET['shc4wc_pay_return'] ) ) : $this->get_current_page_url(); // phpcs:ignore WordPress.Security.NonceVerification.Recommended

		if ( '' === $description ) {
			$description = sprintf(
				/* translators: %s: formatted amount with currency. */
				__( 'Payment %1$s %2$s', 'payments-connect-square' ),
				number_format( $amount, 2 ),
				$currency
			);
		}

		$ref = 'paylink_' . wp_generate_password( 16, false, false );
		$key = wp_hash( $ref . wp_salt( 'auth' ) );
		$api = new SHC4WC_API( $settings );

		$customer = array(
			'email'       => '',
			'given_name'  => '',
			'family_name' => '',
			'phone'       => '',
			'wp_user_id'  => get_current_user_id(),
		);
		if ( is_user_logged_in() ) {
			$user = wp_get_current_user();
			if ( $user && is_email( $user->user_email ) ) {
				$customer['email'] = sanitize_email( $user->user_email );
				if ( $user->first_name ) {
					$customer['given_name'] = sanitize_text_field( (string) $user->first_name );
				}
				if ( $user->last_name ) {
					$customer['family_name'] = sanitize_text_field( (string) $user->last_name );
				}
			}
		}

		$response = $api->create_payment_link(
			$amount,
			$currency,
			$ref,
			array(
				'location_id' => $location_id,
				'description' => $description,
				'line_name'   => $description,
				'return_args' => array(
					'type' => 'paylink',
					'ref'  => $ref,
					'key'  => $key,
				),
				'customer'    => $customer,
			)
		);

		if ( is_wp_error( $response ) ) {
			$api->log( 'Payment link shortcode create failed', array( 'error' => $response->get_error_data() ), 'error' );
			wp_die( esc_html__( 'Could not start Square payment. Please try again.', 'payments-connect-square' ), 500 );
		}

		$link = isset( $response['payment_link']['url'] ) ? esc_url_raw( $response['payment_link']['url'] ) : '';
		if ( '' === $link ) {
			wp_die( esc_html__( 'Invalid response from Square.', 'payments-connect-square' ), 500 );
		}

		set_transient(
			'shc4wc_paylink_' . $ref,
			array(
				'amount'   => $amount,
				'currency' => $currency,
				'return_url' => $return_url,
			),
			DAY_IN_SECONDS
		);

		wp_redirect( esc_url_raw( $link ) ); // phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect -- Square Hosted Checkout.
		exit;
	}

	/**
	 * @param string $ref Reference id.
	 * @param string $key Verification key.
	 */
	public static function handle_return( $ref, $key ) {
		$ref = sanitize_text_field( (string) $ref );
		$key = sanitize_text_field( (string) $key );

		if ( '' === $ref || '' === $key || ! hash_equals( wp_hash( $ref . wp_salt( 'auth' ) ), $key ) ) {
			wp_safe_redirect( home_url( '/' ) );
			exit;
		}

		$stored = get_transient( 'shc4wc_paylink_' . $ref );
		delete_transient( 'shc4wc_paylink_' . $ref );

		$url = ( is_array( $stored ) && ! empty( $stored['return_url'] ) )
			? (string) $stored['return_url']
			: home_url( '/' );

		$url = add_query_arg( 'shc4wc_paylink_paid', '1', remove_query_arg( array( 'shc4wc_pay', 'shc4wc_pay_amount', 'shc4wc_pay_desc', 'shc4wc_pay_currency', 'shc4wc_pay_return', 'shc4wc_pay_nonce' ), $url ) );

		wp_safe_redirect( $url );
		exit;
	}

	/**
	 * @param string $content Post content.
	 * @return string
	 */
	public function maybe_prepend_success_notice( $content ) {
		if ( ! is_singular() || empty( $_GET['shc4wc_paylink_paid'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			return $content;
		}

		$notice = '<div class="shc4wc-payment-link-success" role="status">' . esc_html__( 'Thank you — your Square payment was received.', 'payments-connect-square' ) . '</div>';

		return $notice . $content;
	}

	public function enqueue_styles() {
		if ( empty( $_GET['shc4wc_paylink_paid'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			return;
		}

		$css = '.shc4wc-payment-link-success,.shc4wc-payment-link-notice{display:block;margin:0 0 1.5em;padding:1em 1.25em;border-radius:4px;}.shc4wc-payment-link-success{border:2px solid #46b450;background:#ecf7ed;color:#1e4620;}.shc4wc-payment-link-notice{border:2px solid #dba617;background:#fff8e5;color:#614200;}.shc4wc-payment-link-button{display:inline-block;text-decoration:none;}';
		wp_register_style( 'shc4wc-payment-link', false, array(), SHC4WC_VERSION );
		wp_enqueue_style( 'shc4wc-payment-link' );
		wp_add_inline_style( 'shc4wc-payment-link', $css );
	}

	private function parse_amount( $raw ) {
		$raw = is_string( $raw ) ? trim( $raw ) : '';
		if ( '' === $raw ) {
			return 0.0;
		}
		$raw = preg_replace( '/[^0-9.]/', '', $raw );
		return (float) $raw;
	}

	private function resolve_currency( $currency ) {
		$currency = strtoupper( sanitize_text_field( (string) $currency ) );
		if ( '' !== $currency && 3 === strlen( $currency ) ) {
			return $currency;
		}

		if ( function_exists( 'get_woocommerce_currency' ) ) {
			return get_woocommerce_currency();
		}

		return 'USD';
	}

	private function get_current_page_url() {
		if ( is_singular() ) {
			return get_permalink();
		}

		$scheme = is_ssl() ? 'https' : 'http';
		$host   = isset( $_SERVER['HTTP_HOST'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
		$uri    = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '/'; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized

		if ( '' === $host ) {
			return home_url( '/' );
		}

		return esc_url_raw( $scheme . '://' . $host . $uri );
	}
}
