<?php
/**
 * WooCommerce Pay for Order / invoice payment link (Square Hosted Checkout).
 *
 * @package SHC4WC
 */

// phpcs:disable Squiz.Commenting
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class SHC4WC_Pay_For_Order {
	private static $instance = null;

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

	private function __construct() {
		if ( ! class_exists( 'WooCommerce' ) ) {
			return;
		}

		add_filter( 'woocommerce_available_payment_gateways', array( $this, 'ensure_gateway_on_order_pay' ), 20 );
		add_action( 'woocommerce_admin_order_data_after_billing_address', array( $this, 'render_admin_order_panel' ) );
		add_filter( 'woocommerce_order_actions', array( $this, 'register_order_actions' ), 10, 2 );
		add_action( 'woocommerce_order_action_shc4wc_email_payment_link', array( $this, 'handle_email_payment_link_action' ) );
		add_action( 'wp_ajax_shc4wc_send_payment_link_email', array( $this, 'ajax_send_payment_link_email' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
	}

	/**
	 * Customer-facing WooCommerce order-pay URL (invoice link).
	 *
	 * @param WC_Order $order WooCommerce order.
	 * @return string
	 */
	public static function get_customer_payment_url( WC_Order $order ) {
		return $order->get_checkout_payment_url();
	}

	/**
	 * Keep Square gateway available on the order-pay endpoint for unpaid orders.
	 *
	 * @param array<string, WC_Payment_Gateway> $gateways Available gateways.
	 * @return array<string, WC_Payment_Gateway>
	 */
	public function ensure_gateway_on_order_pay( $gateways ) {
		if ( ! is_wc_endpoint_url( 'order-pay' ) ) {
			return $gateways;
		}

		$order_id = absint( get_query_var( 'order-pay' ) );
		if ( ! $order_id ) {
			return $gateways;
		}

		$order = wc_get_order( $order_id );
		if ( ! $order || ! $order->needs_payment() ) {
			return $gateways;
		}

		if ( isset( $gateways['shc4wc'] ) ) {
			return $gateways;
		}

		$all_gateways = WC()->payment_gateways()->payment_gateways();
		if ( ! isset( $all_gateways['shc4wc'] ) || ! $all_gateways['shc4wc']->is_available() ) {
			return $gateways;
		}

		$gateways['shc4wc'] = $all_gateways['shc4wc'];
		return $gateways;
	}

	/**
	 * @param WC_Order $order WooCommerce order.
	 */
	public function render_admin_order_panel( $order ) {
		if ( ! $order instanceof WC_Order ) {
			return;
		}

		if ( ! current_user_can( 'edit_shop_orders' ) && ! current_user_can( 'manage_woocommerce' ) ) {
			return;
		}

		if ( ! $order->needs_payment() ) {
			return;
		}

		if ( ! SHC4WC_Plugin::is_connected() ) {
			echo '<p class="form-field form-field-wide shc4wc-pay-for-order-panel">';
			echo '<strong>' . esc_html__( 'Square payment link', 'payments-connect-square' ) . '</strong><br />';
			echo esc_html__( 'Connect Square under Payments Square Connect to send hosted checkout payment links for this order.', 'payments-connect-square' );
			echo '</p>';
			return;
		}

		$gateway_settings = get_option( 'woocommerce_shc4wc_settings', array() );
		$gateway_enabled  = isset( $gateway_settings['enabled'] ) && 'yes' === $gateway_settings['enabled'];
		if ( ! $gateway_enabled ) {
			echo '<p class="form-field form-field-wide shc4wc-pay-for-order-panel">';
			echo '<strong>' . esc_html__( 'Square payment link', 'payments-connect-square' ) . '</strong><br />';
			echo esc_html__( 'Enable Payments Square Connect under WooCommerce → Settings → Payments to use pay-for-order links.', 'payments-connect-square' );
			echo '</p>';
			return;
		}

		if ( 'shc4wc' !== $order->get_payment_method() ) {
			echo '<p class="description">';
			esc_html_e( 'Tip: choose Payments Square Connect as the payment method on this order so the customer sees Square when they open the link.', 'payments-connect-square' );
			echo '</p>';
		}

		$pay_url        = self::get_customer_payment_url( $order );
		$billing_email  = trim( (string) $order->get_billing_email() );
		$can_send_email = '' !== $billing_email;
		?>
		<div class="form-field form-field-wide shc4wc-pay-for-order-panel" data-order-id="<?php echo esc_attr( (string) $order->get_id() ); ?>">
			<p>
				<strong><?php esc_html_e( 'Square payment link (Pay for Order)', 'payments-connect-square' ); ?></strong>
			</p>
			<p class="description">
				<?php esc_html_e( 'Send this link to your customer. They open it, click Pay, and complete payment on Square Hosted Checkout — no card form on your site.', 'payments-connect-square' ); ?>
			</p>
			<p>
				<input
					type="text"
					class="widefat shc4wc-pay-for-order-url"
					readonly="readonly"
					value="<?php echo esc_attr( $pay_url ); ?>"
				/>
			</p>
			<p>
				<button type="button" class="button button-secondary shc4wc-copy-pay-url">
					<?php esc_html_e( 'Copy payment link', 'payments-connect-square' ); ?>
				</button>
				<button
					type="button"
					class="button button-primary shc4wc-send-pay-url-email"
					<?php echo $can_send_email ? '' : ' disabled="disabled"'; ?>
				>
					<?php esc_html_e( 'Email payment link to customer', 'payments-connect-square' ); ?>
				</button>
				<span class="shc4wc-pay-for-order-notice" aria-live="polite" style="display:none;margin-left:8px;"></span>
			</p>
			<?php if ( $can_send_email ) : ?>
				<p class="description">
					<?php
					printf(
						/* translators: %s: customer billing email address. */
						esc_html__( 'Email will be sent to %s via WordPress.', 'payments-connect-square' ),
						'<strong>' . esc_html( $billing_email ) . '</strong>'
					);
					?>
				</p>
			<?php else : ?>
				<p class="description" style="color:#b32d2e;">
					<?php esc_html_e( 'Add a billing email on this order to enable the email button.', 'payments-connect-square' ); ?>
				</p>
			<?php endif; ?>
		</div>
		<?php
	}

	/**
	 * @param array<string, string> $actions Order actions.
	 * @param WC_Order|null         $order   Order object (HPOS).
	 * @return array<string, string>
	 */
	public function register_order_actions( $actions, $order = null ) {
		if ( $order instanceof WC_Order && ! $order->needs_payment() ) {
			return $actions;
		}

		if ( ! SHC4WC_Plugin::is_connected() ) {
			return $actions;
		}

		$gateway_settings = get_option( 'woocommerce_shc4wc_settings', array() );
		if ( empty( $gateway_settings['enabled'] ) || 'yes' !== $gateway_settings['enabled'] ) {
			return $actions;
		}

		$actions['shc4wc_email_payment_link'] = __( 'Email Square payment link to customer', 'payments-connect-square' );
		return $actions;
	}

	/**
	 * @param WC_Order $order WooCommerce order.
	 */
	public function handle_email_payment_link_action( $order ) {
		if ( ! $order instanceof WC_Order ) {
			return;
		}

		$result = self::send_payment_link_for_order( $order );
		if ( is_wp_error( $result ) ) {
			$order->add_order_note( $result->get_error_message() );
		}
	}

	/**
	 * AJAX: send payment link email from the order edit screen button.
	 */
	public function ajax_send_payment_link_email() {
		check_ajax_referer( 'shc4wc_send_payment_link_email', 'nonce' );

		if ( ! current_user_can( 'edit_shop_orders' ) && ! current_user_can( 'manage_woocommerce' ) ) {
			wp_send_json_error(
				array( 'message' => __( 'You do not have permission to email payment links.', 'payments-connect-square' ) ),
				403
			);
		}

		$order_id = isset( $_POST['order_id'] ) ? absint( wp_unslash( $_POST['order_id'] ) ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Missing
		$order    = $order_id ? wc_get_order( $order_id ) : false;
		if ( ! $order ) {
			wp_send_json_error(
				array( 'message' => __( 'Order not found.', 'payments-connect-square' ) ),
				404
			);
		}

		$result = self::send_payment_link_for_order( $order );
		if ( is_wp_error( $result ) ) {
			wp_send_json_error( array( 'message' => $result->get_error_message() ), 400 );
		}

		wp_send_json_success(
			array(
				'message' => sprintf(
					/* translators: %s: customer billing email address. */
					__( 'Payment link emailed to %s.', 'payments-connect-square' ),
					$order->get_billing_email()
				),
			)
		);
	}

	/**
	 * @param WC_Order $order WooCommerce order.
	 * @return true|WP_Error
	 */
	public static function send_payment_link_for_order( WC_Order $order ) {
		if ( ! $order->needs_payment() ) {
			return new WP_Error( 'shc4wc_order_paid', __( 'This order does not need payment.', 'payments-connect-square' ) );
		}

		if ( ! SHC4WC_Plugin::is_connected() ) {
			return new WP_Error( 'shc4wc_not_connected', __( 'Square is not connected.', 'payments-connect-square' ) );
		}

		$gateway_settings = get_option( 'woocommerce_shc4wc_settings', array() );
		if ( empty( $gateway_settings['enabled'] ) || 'yes' !== $gateway_settings['enabled'] ) {
			return new WP_Error( 'shc4wc_gateway_disabled', __( 'Payments Square Connect is not enabled.', 'payments-connect-square' ) );
		}

		if ( 'shc4wc' !== $order->get_payment_method() ) {
			$order->set_payment_method( 'shc4wc' );
			$order->save();
		}

		$sent = self::email_payment_link_to_customer( $order );
		if ( ! $sent ) {
			return new WP_Error(
				'shc4wc_email_failed',
				__( 'Could not send email. Add a billing email on this order and check that WordPress mail (wp_mail) is working.', 'payments-connect-square' )
			);
		}

		$order->add_order_note(
			__( 'Square payment link emailed to customer (Pay for Order / hosted checkout).', 'payments-connect-square' )
		);

		/**
		 * Fires after a Pay for Order payment link email is sent.
		 *
		 * @param WC_Order $order WooCommerce order.
		 */
		do_action( 'shc4wc_pay_for_order_email_sent', $order );

		return true;
	}

	/**
	 * @param WC_Order $order WooCommerce order.
	 * @param array    $args  Optional: is_reminder (bool), reminder_number (int).
	 * @return bool
	 */
	public static function email_payment_link_to_customer( WC_Order $order, array $args = array() ) {
		$to = $order->get_billing_email();
		if ( '' === trim( (string) $to ) ) {
			return false;
		}

		$is_reminder = ! empty( $args['is_reminder'] );
		$pay_url     = self::get_customer_payment_url( $order );
		$site_name   = wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES );

		if ( $is_reminder ) {
			$subject = sprintf(
				/* translators: 1: site name, 2: order number. */
				__( '[%1$s] Reminder: complete payment for order #%2$s', 'payments-connect-square' ),
				$site_name,
				$order->get_order_number()
			);
		} else {
			$subject = sprintf(
				/* translators: 1: site name, 2: order number. */
				__( '[%1$s] Complete payment for order #%2$s', 'payments-connect-square' ),
				$site_name,
				$order->get_order_number()
			);
		}

		$total_html = wp_kses_post( $order->get_formatted_order_total() );
		$name       = $order->get_billing_first_name() ? $order->get_billing_first_name() : __( 'there', 'payments-connect-square' );

		if ( $is_reminder ) {
			$message = sprintf(
				/* translators: 1: customer first name, 2: order number, 3: formatted total, 4: payment URL, 5: site name. */
				__(
					'<p>Hi %1$s,</p><p>This is a friendly reminder to complete payment for order <strong>#%2$s</strong> (%3$s).</p><p><a href="%4$s">Pay with Square</a></p><p>You will be taken to Square secure hosted checkout to pay by card or digital wallet.</p><p>Thank you,<br />%5$s</p>',
					'payments-connect-square'
				),
				esc_html( $name ),
				esc_html( $order->get_order_number() ),
				$total_html,
				esc_url( $pay_url ),
				esc_html( $site_name )
			);
		} else {
			$message = sprintf(
				/* translators: 1: customer first name, 2: order number, 3: formatted total, 4: payment URL, 5: site name. */
				__(
					'<p>Hi %1$s,</p><p>Please complete payment for order <strong>#%2$s</strong> (%3$s).</p><p><a href="%4$s">Pay with Square</a></p><p>You will be taken to Square secure hosted checkout to pay by card or digital wallet. When payment is complete, you will return to our site and your order will be marked paid.</p><p>Thank you,<br />%5$s</p>',
					'payments-connect-square'
				),
				esc_html( $name ),
				esc_html( $order->get_order_number() ),
				$total_html,
				esc_url( $pay_url ),
				esc_html( $site_name )
			);
		}

		$headers = array( 'Content-Type: text/html; charset=UTF-8' );
		return (bool) wp_mail( $to, $subject, $message, $headers );
	}

	/**
	 * @param string $hook_suffix Admin screen hook.
	 */
	public function enqueue_admin_scripts( $hook_suffix ) {
		$is_order_screen = in_array( $hook_suffix, array( 'post.php', 'woocommerce_page_wc-orders' ), true );
		if ( ! $is_order_screen ) {
			return;
		}

		$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
		if ( $screen && 'shop_order' !== $screen->id && 'woocommerce_page_wc-orders' !== $screen->id ) {
			return;
		}

		wp_register_script( 'shc4wc-pay-for-order-admin', false, array( 'jquery' ), SHC4WC_VERSION, true );
		wp_enqueue_script( 'shc4wc-pay-for-order-admin' );
		wp_localize_script(
			'shc4wc-pay-for-order-admin',
			'shc4wcPayForOrder',
			array(
				'ajaxUrl' => admin_url( 'admin-ajax.php' ),
				'nonce'   => wp_create_nonce( 'shc4wc_send_payment_link_email' ),
				'i18n'    => array(
					'copied'  => __( 'Copied!', 'payments-connect-square' ),
					'sending' => __( 'Sending…', 'payments-connect-square' ),
					'failed'  => __( 'Could not send email. Try again or check WooCommerce logs.', 'payments-connect-square' ),
				),
			)
		);
		wp_add_inline_script(
			'shc4wc-pay-for-order-admin',
			"(function($){function showNotice(panel,msg,isError){var notice=panel.querySelector('.shc4wc-pay-for-order-notice');if(!notice){return;}notice.textContent=msg;notice.style.display='inline';notice.style.color=isError?'#b32d2e':'#2271b1';setTimeout(function(){notice.style.display='none';},4000);}document.addEventListener('click',function(e){var copyBtn=e.target.closest('.shc4wc-copy-pay-url');if(copyBtn){e.preventDefault();var panel=copyBtn.closest('.shc4wc-pay-for-order-panel');if(!panel){return;}var input=panel.querySelector('.shc4wc-pay-for-order-url');if(!input){return;}var done=function(){showNotice(panel,shc4wcPayForOrder.i18n.copied,false);};if(navigator.clipboard&&navigator.clipboard.writeText){navigator.clipboard.writeText(input.value).then(done).catch(function(){input.select();document.execCommand('copy');done();});}else{input.select();document.execCommand('copy');done();}return;}var emailBtn=e.target.closest('.shc4wc-send-pay-url-email');if(!emailBtn||emailBtn.disabled){return;}e.preventDefault();var panel2=emailBtn.closest('.shc4wc-pay-for-order-panel');if(!panel2){return;}var orderId=panel2.getAttribute('data-order-id');if(!orderId){return;}var label=emailBtn.textContent;emailBtn.disabled=true;emailBtn.textContent=shc4wcPayForOrder.i18n.sending;$.post(shc4wcPayForOrder.ajaxUrl,{action:'shc4wc_send_payment_link_email',nonce:shc4wcPayForOrder.nonce,order_id:orderId}).done(function(res){if(res&&res.success&&res.data&&res.data.message){showNotice(panel2,res.data.message,false);}else{showNotice(panel2,shc4wcPayForOrder.i18n.failed,true);}}).fail(function(xhr){var msg=shc4wcPayForOrder.i18n.failed;if(xhr.responseJSON&&xhr.responseJSON.data&&xhr.responseJSON.data.message){msg=xhr.responseJSON.data.message;}showNotice(panel2,msg,true);}).always(function(){emailBtn.disabled=false;emailBtn.textContent=label;});});})(jQuery);"
		);
	}
}
