<?php
/**
 * Fluent Forms payment processor (redirect to Square Hosted Checkout).
 *
 * @package SHC4WC
 */

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

class SHC4WC_FluentForms_Processor extends \FluentForm\App\Modules\Payments\PaymentMethods\BaseProcessor {
	/** @var string */
	public $method = '';

	public function __construct() {
		$this->method = SHC4WC_FluentForms::GATEWAY_KEY;
	}

	public function init() {
		add_action( 'fluentform/process_payment_' . $this->method, array( $this, 'handlePaymentAction' ), 10, 6 );
		add_action( 'fluentform/payment_frameless_' . $this->method, array( $this, 'handle_session_redirect_back' ) );
	}

	/**
	 * @param int                  $submission_id      Submission id.
	 * @param array<string, mixed> $submission_data    Submission data.
	 * @param object               $form               Form object.
	 * @param array<string, mixed> $method_settings    Method settings.
	 * @param bool                 $has_subscriptions  Has subscription items.
	 * @param int                  $total_payable      Payable total in cents.
	 */
	public function handlePaymentAction( $submission_id, $submission_data, $form, $method_settings, $has_subscriptions, $total_payable ) {
		unset( $method_settings );

		if ( $has_subscriptions ) {
			wp_send_json_success(
				array(
					'message' => __( 'Square subscription signup through Fluent Forms is not supported yet. Use one-time payment items only.', 'payments-connect-square' ),
				),
				423
			);
		}

		if ( ! SHC4WC_Plugin::is_connected() ) {
			wp_send_json_success(
				array(
					'message' => __( 'Square is not connected. Ask the site administrator to connect under Payments Square Connect.', 'payments-connect-square' ),
				),
				423
			);
		}

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

		$this->setSubmissionId( $submission_id );
		$this->form = $form;

		$amount_cents = $this->resolve_payment_amount_cents( $form, $submission_data, (int) $total_payable );
		if ( $amount_cents <= 0 ) {
			wp_send_json_success(
				array(
					'message' => __( 'Enter a valid payment amount.', 'payments-connect-square' ),
				),
				423
			);
		}

		$currency   = $this->resolve_currency( $form );
		$line_items = $this->build_square_payment_line_items( $form, $submission_data, $currency, $amount_cents );
		$line_total = $this->sum_square_line_items_cents( $line_items );
		if ( $line_total > 0 ) {
			$amount_cents = $line_total;
		}

		$amount   = (float) $amount_cents / 100;
		$ref      = 'fluentform_' . wp_generate_password( 16, false, false );
		$key      = wp_hash( $ref . wp_salt( 'auth' ) );
		$api      = new SHC4WC_API( $settings );

		$transaction_id = $this->insertTransaction(
			array(
				'transaction_type' => 'onetime',
				'status'           => 'pending',
				'payment_total'    => $amount_cents,
				'payment_mode'     => $this->get_payment_mode(),
				'currency'         => $currency,
			)
		);

		$transaction = $this->getTransaction( $transaction_id );
		$form_title  = isset( $form->title ) ? trim( (string) $form->title ) : __( 'Fluent Forms payment', 'payments-connect-square' );
		$item_name   = $this->resolve_square_order_item_name( $form, $submission_data, $line_items );
		$customer    = $this->extract_buyer_from_submission( $form, $submission_data );

		$response = $api->create_payment_link(
			$amount,
			$currency,
			$ref,
			array(
				'location_id' => $location_id,
				'description' => sprintf(
					/* translators: 1: form title, 2: reference id. */
					__( 'Fluent Forms: %1$s (%2$s)', 'payments-connect-square' ),
					$form_title,
					$ref
				),
				'line_name'   => $item_name,
				'line_items'  => $line_items,
				'return_args' => array(
					'type'             => 'fluentform',
					'ref'              => $ref,
					'key'              => $key,
					'submission_id'    => (int) $submission_id,
					'transaction_id'   => (int) $transaction_id,
				),
				'customer'    => $customer,
			)
		);

		if ( is_wp_error( $response ) ) {
			$api->log( 'Fluent Forms create payment link failed', array( 'error' => $response->get_error_data() ), 'error' );
			wp_send_json_success(
				array(
					'message' => SHC4WC_Plugin::format_payment_start_error( $response ),
				),
				423
			);
		}

		$link = isset( $response['payment_link']['url'] ) ? esc_url_raw( $response['payment_link']['url'] ) : '';
		if ( '' === $link ) {
			wp_send_json_success(
				array(
					'message' => __( 'Invalid response from Square.', 'payments-connect-square' ),
				),
				423
			);
		}

		set_transient(
			'shc4wc_fluentform_' . $ref,
			array(
				'submission_id'  => (int) $submission_id,
				'transaction_id' => (int) $transaction_id,
				'form_id'        => isset( $form->id ) ? (int) $form->id : 0,
				'return_url'     => $this->resolve_return_url( $form ),
				'link_id'        => isset( $response['payment_link']['id'] ) ? (string) $response['payment_link']['id'] : '',
				'square_order_id'=> self::extract_square_order_id( $response ),
			),
			DAY_IN_SECONDS
		);

		wp_send_json_success(
			array(
				'nextAction'   => 'payment',
				'actionName'   => 'normalRedirect',
				'redirect_url' => $link,
				'message'      => __( 'Redirecting to Square…', 'payments-connect-square' ),
				'result'       => array(
					'insert_id' => (int) $submission_id,
				),
			),
			200
		);
	}

	/**
	 * Frameless return handler (fallback if Fluent Forms routes here).
	 *
	 * @param array<string, mixed> $data Query data.
	 */
	public function handle_session_redirect_back( $data ) {
		$ref = isset( $data['ref'] ) ? sanitize_text_field( (string) $data['ref'] ) : '';
		$key = isset( $data['key'] ) ? sanitize_text_field( (string) $data['key'] ) : '';
		if ( '' !== $ref && '' !== $key ) {
			SHC4WC_FluentForms::handle_return( $ref, $key );
		}
	}

	/**
	 * @param array<string, mixed> $stored Transient payload.
	 */
	public static function complete_stored_payment( array $stored ) {
		if ( ! class_exists( '\FluentForm\App\Modules\Payments\PaymentMethods\BaseProcessor' ) ) {
			return;
		}

		$submission_id  = isset( $stored['submission_id'] ) ? (int) $stored['submission_id'] : 0;
		$transaction_id = isset( $stored['transaction_id'] ) ? (int) $stored['transaction_id'] : 0;
		if ( $submission_id <= 0 || $transaction_id <= 0 ) {
			return;
		}

		$processor = new self();
		$processor->setSubmissionId( $submission_id );

		if ( 'yes' === $processor->getMetaData( 'is_form_action_fired' ) ) {
			return;
		}

		$note = __( 'Paid via Square Hosted Checkout', 'payments-connect-square' );
		if ( ! empty( $stored['square_order_id'] ) ) {
			$note .= ' — order:' . sanitize_text_field( (string) $stored['square_order_id'] );
		}
		if ( ! empty( $stored['link_id'] ) ) {
			$note .= ' link:' . sanitize_text_field( (string) $stored['link_id'] );
		}

		$square_payment_id = '';
		if ( ! empty( $stored['square_order_id'] ) ) {
			$settings    = SHC4WC_Plugin::get_settings();
			$location_id = isset( $settings['location_id'] ) ? trim( (string) $settings['location_id'] ) : '';
			$square_payment_id = SHC4WC_Plugin::instance()->retrieve_square_payment_id_for_hosted_checkout(
				sanitize_text_field( (string) $stored['square_order_id'] ),
				! empty( $stored['link_id'] ) ? sanitize_text_field( (string) $stored['link_id'] ) : '',
				$location_id,
				time()
			);
		}

		$processor->updateTransaction(
			$transaction_id,
			array(
				'payment_note' => $note,
				'charge_id'    => '' !== $square_payment_id
					? $square_payment_id
					: ( ! empty( $stored['link_id'] ) ? sanitize_text_field( (string) $stored['link_id'] ) : '' ),
			)
		);
		$processor->changeTransactionStatus( $transaction_id, 'paid' );
		$processor->changeSubmissionPaymentStatus( 'paid' );
		$processor->recalculatePaidTotal();
		$processor->setMetaData( 'is_form_action_fired', 'yes' );

		if ( class_exists( '\FluentForm\App\Services\Form\SubmissionHandlerService' ) ) {
			$submission = $processor->getSubmission();
			$form       = $processor->getForm();
			if ( $submission && $form ) {
				( new \FluentForm\App\Services\Form\SubmissionHandlerService() )->processSubmissionData(
					$submission_id,
					$submission->response,
					$form
				);
				return;
			}
		}

		if ( method_exists( $processor, 'completePaymentSubmission' ) ) {
			$processor->completePaymentSubmission( false );
		}
	}

	private function get_payment_mode() {
		$settings = SHC4WC_Plugin::get_settings();
		return ( isset( $settings['environment'] ) && 'live' === $settings['environment'] ) ? 'live' : 'test';
	}

	/**
	 * Resolve buyer details for Square customer linking.
	 *
	 * @param object               $form            Fluent Forms form.
	 * @param array<string, mixed> $submission_data Submission payload.
	 * @return array{email:string,given_name:string,family_name:string,phone:string,wp_user_id:int}
	 */
	private function extract_buyer_from_submission( $form, $submission_data ) {
		$buyer = array(
			'email'       => '',
			'given_name'  => '',
			'family_name' => '',
			'phone'       => '',
			'wp_user_id'  => get_current_user_id(),
		);

		$submission = $this->getSubmission();
		$response   = $this->extract_submission_response( $submission_data );

		if ( $submission && class_exists( '\FluentForm\App\Modules\Payments\PaymentHelper' ) ) {
			$email = \FluentForm\App\Modules\Payments\PaymentHelper::getCustomerEmail( $submission, $form );
			if ( is_email( (string) $email ) ) {
				$buyer['email'] = sanitize_email( (string) $email );
			}
			$name = \FluentForm\App\Modules\Payments\PaymentHelper::getCustomerName( $submission, $form );
			if ( is_string( $name ) && '' !== trim( $name ) ) {
				$parts = preg_split( '/\s+/', trim( $name ), 2 );
				if ( ! empty( $parts[0] ) ) {
					$buyer['given_name'] = sanitize_text_field( $parts[0] );
				}
				if ( ! empty( $parts[1] ) ) {
					$buyer['family_name'] = sanitize_text_field( $parts[1] );
				}
			}
			if ( method_exists( '\FluentForm\App\Modules\Payments\PaymentHelper', 'getCustomerPhoneNumber' ) ) {
				$phone = \FluentForm\App\Modules\Payments\PaymentHelper::getCustomerPhoneNumber( $submission, $form );
				if ( is_string( $phone ) && '' !== trim( $phone ) ) {
					$buyer['phone'] = sanitize_text_field( $phone );
				}
			}
		}

		if ( '' === $buyer['email'] && is_array( $response ) ) {
			foreach ( $response as $value ) {
				if ( is_string( $value ) && is_email( $value ) ) {
					$buyer['email'] = sanitize_email( $value );
					break;
				}
			}
		}

		if ( '' === $buyer['email'] && is_user_logged_in() ) {
			$user = wp_get_current_user();
			if ( $user && is_email( $user->user_email ) ) {
				$buyer['email'] = sanitize_email( $user->user_email );
			}
		}

		return $buyer;
	}

	/**
	 * Resolve payable total in cents (price × quantity, minus discounts when present).
	 *
	 * @param object               $form            Fluent Forms form object.
	 * @param array<string, mixed> $submission_data Submission payload.
	 * @param int                  $total_payable   Total passed by Fluent Forms (cents).
	 * @return int
	 */
	private function resolve_payment_amount_cents( $form, $submission_data, $total_payable ) {
		$amount_cents = 0;
		if ( method_exists( $this, 'getAmountTotal' ) ) {
			$amount_cents = (int) $this->getAmountTotal();
		}
		if ( $amount_cents <= 0 && $total_payable > 0 ) {
			$amount_cents = (int) $total_payable;
		}
		if ( $amount_cents <= 0 ) {
			$amount_cents = $this->compute_payment_total_from_form_fields( $form, $submission_data );
		}
		if ( $amount_cents <= 0 ) {
			$amount_cents = $this->adjust_amount_for_submission_quantity( $form, $submission_data, $amount_cents );
		}

		return max( 0, $amount_cents );
	}

	/**
	 * @param array<string, mixed> $submission_data Submission payload.
	 * @return array<string, mixed>
	 */
	private function extract_submission_response( $submission_data ) {
		if ( ! is_array( $submission_data ) ) {
			return array();
		}

		$response = isset( $submission_data['response'] ) ? $submission_data['response'] : array();
		if ( is_string( $response ) ) {
			$decoded = json_decode( $response, true );
			$response  = is_array( $decoded ) ? $decoded : array();
		}

		return is_array( $response ) ? $response : array();
	}

	/**
	 * @param object $form Fluent Forms form object.
	 * @return array{payment_inputs: array<int, array<string, mixed>>, quantity_map: array<string, string>}
	 */
	private function parse_payment_form_fields( $form ) {
		$payment_inputs    = array();
		$quantity_map      = array();
		$orphan_qty        = '';
		$last_payment_name = '';
		$payment_count     = 0;
		$fields            = $this->decode_form_fields( $form );

		foreach ( $fields as $field ) {
			if ( ! is_array( $field ) ) {
				continue;
			}

			$element = isset( $field['element'] ) ? (string) $field['element'] : '';
			if ( in_array( $element, array( 'custom_payment_component', 'multi_payment_component' ), true ) ) {
				$payment_inputs[] = $field;
				++$payment_count;
				$field_name = isset( $field['attributes']['name'] ) ? $this->normalize_payment_field_name( (string) $field['attributes']['name'] ) : '';
				if ( '' !== $field_name ) {
					$last_payment_name = $field_name;
				}
				continue;
			}

			if ( 'item_quantity_component' === $element || 'rangeslider' === $element ) {
				if ( 'rangeslider' === $element && 'yes' !== ( isset( $field['settings']['enable_target_product'] ) ? (string) $field['settings']['enable_target_product'] : '' ) ) {
					continue;
				}

				$target_product = isset( $field['settings']['target_product'] ) ? $this->normalize_payment_field_name( (string) $field['settings']['target_product'] ) : '';
				$qty_name       = isset( $field['attributes']['name'] ) ? (string) $field['attributes']['name'] : '';
				if ( '' === $qty_name ) {
					continue;
				}

				if ( '' !== $target_product ) {
					$quantity_map[ $target_product ] = $qty_name;
				} elseif ( 1 === $payment_count && '' !== $last_payment_name ) {
					// One payment field directly above quantity (e.g. Payment Item -> Qty -> other fields).
					$quantity_map[ $last_payment_name ] = $qty_name;
				} else {
					$orphan_qty = $qty_name;
				}
			}
		}

		if ( '' !== $orphan_qty && 1 === count( $payment_inputs ) ) {
			$payment_name = isset( $payment_inputs[0]['attributes']['name'] ) ? $this->normalize_payment_field_name( (string) $payment_inputs[0]['attributes']['name'] ) : '';
			if ( '' !== $payment_name && ! isset( $quantity_map[ $payment_name ] ) ) {
				$quantity_map[ $payment_name ] = $orphan_qty;
			}
		}

		return array(
			'payment_inputs' => $payment_inputs,
			'quantity_map'   => $quantity_map,
		);
	}

	/**
	 * @param object $form Fluent Forms form object.
	 * @return array<int, array<string, mixed>>
	 */
	private function decode_form_fields( $form ) {
		$raw = '';
		if ( is_object( $form ) && isset( $form->form_fields ) ) {
			$raw = (string) $form->form_fields;
		}

		if ( '' === $raw ) {
			return array();
		}

		$decoded = json_decode( $raw, true );
		if ( ! is_array( $decoded ) ) {
			return array();
		}

		$fields = isset( $decoded['fields'] ) && is_array( $decoded['fields'] ) ? $decoded['fields'] : array();
		return $this->flatten_form_fields( $fields );
	}

	/**
	 * @param array<int, array<string, mixed>> $fields Form fields (may include containers).
	 * @return array<int, array<string, mixed>>
	 */
	private function flatten_form_fields( array $fields ) {
		$flat = array();
		foreach ( $fields as $field ) {
			if ( ! is_array( $field ) ) {
				continue;
			}

			if ( isset( $field['element'] ) ) {
				$flat[] = $field;
			}

			if ( isset( $field['columns'] ) && is_array( $field['columns'] ) ) {
				foreach ( $field['columns'] as $column ) {
					if ( ! is_array( $column ) || empty( $column['fields'] ) || ! is_array( $column['fields'] ) ) {
						continue;
					}
					$flat = array_merge( $flat, $this->flatten_form_fields( $column['fields'] ) );
				}
			}

			if ( isset( $field['fields'] ) && is_array( $field['fields'] ) ) {
				foreach ( $field['fields'] as $nested ) {
					if ( is_array( $nested ) ) {
						$flat[] = $nested;
					}
				}
			}
		}

		return $flat;
	}

	/**
	 * @param array<string, string> $quantity_map Quantity field map.
	 * @param string                $product_name Payment field name.
	 * @param array<string, mixed>  $response     Submission response.
	 * @return int
	 */
	private function get_field_quantity( array $quantity_map, $product_name, array $response ) {
		if ( ! isset( $quantity_map[ $product_name ] ) ) {
			return 1;
		}

		$qty_name = $quantity_map[ $product_name ];
		if ( ! isset( $response[ $qty_name ] ) || '' === $response[ $qty_name ] ) {
			return 0;
		}

		return max( 0, (int) $response[ $qty_name ] );
	}

	/**
	 * Normalize multi payment field name (checkbox fields use [] in markup).
	 *
	 * @param string $field_name Raw field name.
	 * @return string
	 */
	private function normalize_payment_field_name( $field_name ) {
		return str_replace( '[]', '', (string) $field_name );
	}

	/**
	 * @param array<string, mixed> $payment_input Payment field definition.
	 * @param object               $form          Fluent Forms form object.
	 * @return array<int, array<string, mixed>>
	 */
	private function get_payment_pricing_options( array $payment_input, $form ) {
		$options = isset( $payment_input['settings']['pricing_options'] ) && is_array( $payment_input['settings']['pricing_options'] )
			? $payment_input['settings']['pricing_options']
			: array();

		$element = isset( $payment_input['element'] ) ? (string) $payment_input['element'] : '';
		if ( '' !== $element ) {
			/**
			 * Matches Fluent Forms PaymentAction::getItemFromVariables().
			 *
			 * @param array<int, array<string, mixed>> $options       Pricing options.
			 * @param array<string, mixed>             $payment_input Field definition.
			 * @param object                           $form          Form object.
			 */
			$options = apply_filters( 'fluentform/payment_field_' . $element . '_pricing_options', $options, $payment_input, $form );
		}

		return is_array( $options ) ? $options : array();
	}

	/**
	 * Fluent Forms stores option labels in submissions for select/radio/checkbox payment items.
	 *
	 * @param array<string, mixed> $option   Pricing option.
	 * @param mixed                $selected Submitted value.
	 * @return bool
	 */
	private function payment_option_matches_selected( array $option, $selected ) {
		if ( ! is_scalar( $selected ) ) {
			return false;
		}

		$selected = (string) $selected;
		if ( '' === $selected ) {
			return false;
		}

		$label = isset( $option['label'] ) ? sanitize_text_field( (string) $option['label'] ) : '';
		$value = isset( $option['value'] ) ? $option['value'] : '';

		if ( $label === $selected || (string) $value === $selected ) {
			return true;
		}

		return ( '' !== $label && $label == $selected ) || ( is_numeric( $value ) && is_numeric( $selected ) && (float) $value == (float) $selected );
	}

	/**
	 * Mirror Fluent Forms PaymentAction::getItemFromVariables().
	 *
	 * @param array<string, mixed> $payment_input Payment field definition.
	 * @param mixed                $selected      Submitted option label/value.
	 * @param object               $form          Fluent Forms form object.
	 * @return array<string, mixed>|null
	 */
	private function resolve_payment_option_from_field( array $payment_input, $selected, $form ) {
		foreach ( $this->get_payment_pricing_options( $payment_input, $form ) as $option ) {
			if ( ! is_array( $option ) || ! $this->payment_option_matches_selected( $option, $selected ) ) {
				continue;
			}

			if ( ! isset( $option['value'] ) || ! is_numeric( $option['value'] ) || (float) $option['value'] <= 0 ) {
				return null;
			}

			$field_name = isset( $payment_input['attributes']['name'] ) ? $this->normalize_payment_field_name( (string) $payment_input['attributes']['name'] ) : '';
			$item_name  = isset( $option['label'] ) ? sanitize_text_field( (string) $option['label'] ) : '';
			if ( '' === $item_name && isset( $option['value'] ) ) {
				$item_name = sanitize_text_field( (string) $option['value'] );
			}

			return array(
				'parent_holder' => $field_name,
				'item_name'     => $item_name,
				'item_price'    => (float) $option['value'],
			);
		}

		return null;
	}

	/**
	 * @param array<string, mixed> $payment_input Payment field definition.
	 * @param mixed                $selected      Submitted option label/value.
	 * @param object               $form          Fluent Forms form object.
	 * @return float
	 */
	private function get_option_price_from_payment_field( array $payment_input, $selected, $form = null ) {
		if ( null === $form ) {
			$form = $this->form;
		}

		$resolved = $this->resolve_payment_option_from_field( $payment_input, $selected, $form );
		return is_array( $resolved ) ? (float) $resolved['item_price'] : 0.0;
	}

	/**
	 * @param array<string, mixed> $payment_input Payment field definition.
	 * @param mixed                $selected      Submitted option label/value.
	 * @param object               $form          Fluent Forms form object.
	 * @return string
	 */
	private function get_option_label_from_payment_field( array $payment_input, $selected, $form = null ) {
		if ( null === $form ) {
			$form = $this->form;
		}

		$resolved = $this->resolve_payment_option_from_field( $payment_input, $selected, $form );
		return is_array( $resolved ) ? (string) $resolved['item_name'] : '';
	}

	/**
	 * @param float $amount Dollar amount.
	 * @return int
	 */
	private function convert_amount_to_cents( $amount ) {
		if ( class_exists( '\FluentForm\App\Modules\Payments\PaymentHelper' ) ) {
			return (int) \FluentForm\App\Modules\Payments\PaymentHelper::convertToCents( $amount );
		}

		return (int) round( (float) $amount * 100 );
	}

	/**
	 * @param object               $form            Fluent Forms form object.
	 * @param array<string, mixed> $submission_data Submission payload.
	 * @return int
	 */
	private function compute_payment_total_from_form_fields( $form, $submission_data ) {
		$line_items = $this->resolve_payment_line_items_from_form_fields( $form, $submission_data, 'USD' );
		$total      = 0;

		foreach ( $line_items as $line_item ) {
			$qty  = isset( $line_item['quantity'] ) ? max( 1, (int) $line_item['quantity'] ) : 1;
			$unit = isset( $line_item['base_price_money']['amount'] ) ? (int) $line_item['base_price_money']['amount'] : 0;
			$total += $unit * $qty;
		}

		return $total;
	}

	/**
	 * Build payable line items from Fluent Forms payment fields (multi_payment select/radio/checkbox compatible).
	 *
	 * @param object               $form            Fluent Forms form object.
	 * @param array<string, mixed> $submission_data Submission payload.
	 * @param string               $currency        ISO currency code.
	 * @return array<int, array<string, mixed>>
	 */
	private function resolve_payment_line_items_from_form_fields( $form, $submission_data, $currency ) {
		$response = $this->extract_submission_response( $submission_data );
		if ( empty( $response ) ) {
			return array();
		}

		$parsed       = $this->parse_payment_form_fields( $form );
		$quantity_map = $parsed['quantity_map'];
		$currency     = strtoupper( sanitize_text_field( (string) $currency ) );
		$line_items   = array();

		foreach ( $parsed['payment_inputs'] as $payment_input ) {
			$field_name = isset( $payment_input['attributes']['name'] ) ? $this->normalize_payment_field_name( (string) $payment_input['attributes']['name'] ) : '';
			if ( '' === $field_name || ! isset( $response[ $field_name ] ) || '' === $response[ $field_name ] ) {
				continue;
			}

			$input_type = isset( $payment_input['attributes']['type'] ) ? (string) $payment_input['attributes']['type'] : '';
			$selected   = $response[ $field_name ];

			if ( 'checkbox' === $input_type && is_array( $selected ) ) {
				foreach ( $selected as $selected_item ) {
					$item = $this->resolve_payment_option_from_field( $payment_input, $selected_item, $form );
					if ( ! is_array( $item ) ) {
						continue;
					}

					$qty = $this->get_field_quantity( $quantity_map, $field_name, $response );
					if ( $qty <= 0 ) {
						continue;
					}

					$line_items[] = $this->make_square_line_item_from_payment(
						$this->resolve_payment_item_row_name( $payment_input, $item ),
						$qty,
						$this->convert_amount_to_cents( $item['item_price'] ),
						$currency
					);
				}
				continue;
			}

			if ( in_array( $input_type, array( 'radio', 'select' ), true ) ) {
				$item = $this->resolve_payment_option_from_field( $payment_input, $selected, $form );
				if ( ! is_array( $item ) ) {
					continue;
				}

				$qty = $this->get_field_quantity( $quantity_map, $field_name, $response );
				if ( $qty <= 0 ) {
					continue;
				}

				$line_items[] = $this->make_square_line_item_from_payment(
					$this->resolve_payment_item_row_name( $payment_input, $item ),
					$qty,
					$this->convert_amount_to_cents( $item['item_price'] ),
					$currency
				);
				continue;
			}

			$price = 0.0;
			if ( 'number' === $input_type ) {
				$price = (float) $selected;
			} elseif ( 'single' === $input_type ) {
				if ( ! empty( $payment_input['settings']['dynamic_default_value'] ) ) {
					$price = (float) $selected;
				} elseif ( isset( $payment_input['attributes']['value'] ) && is_numeric( $payment_input['attributes']['value'] ) ) {
					$price = (float) $payment_input['attributes']['value'];
				} elseif ( is_numeric( $selected ) ) {
					$price = (float) $selected;
				}
			}

			if ( $price <= 0 ) {
				continue;
			}

			$qty = $this->get_field_quantity( $quantity_map, $field_name, $response );
			if ( $qty <= 0 ) {
				continue;
			}

			$item_name = isset( $payment_input['settings']['label'] ) ? trim( (string) $payment_input['settings']['label'] ) : '';
			if ( '' === $item_name ) {
				$item_name = isset( $payment_input['settings']['admin_field_label'] ) ? trim( (string) $payment_input['settings']['admin_field_label'] ) : $field_name;
			}

			$line_items[] = $this->make_square_line_item_from_payment( $item_name, $qty, $this->convert_amount_to_cents( $price ), $currency );
		}

		return $line_items;
	}

	/**
	 * Name shown on the Square order line item row (pricing option label from Payment Items).
	 *
	 * @param array<string, mixed> $payment_input Payment field definition.
	 * @param array<string, mixed> $item          Resolved payment option.
	 * @return string
	 */
	private function resolve_payment_item_row_name( array $payment_input, array $item ) {
		$item_name = isset( $item['item_name'] ) ? trim( (string) $item['item_name'] ) : '';
		if ( '' !== $item_name ) {
			return sanitize_text_field( $item_name );
		}

		$field_label = isset( $payment_input['settings']['label'] ) ? trim( (string) $payment_input['settings']['label'] ) : '';
		if ( '' !== $field_label ) {
			return sanitize_text_field( $field_label );
		}

		$field_name = isset( $payment_input['attributes']['name'] ) ? $this->normalize_payment_field_name( (string) $payment_input['attributes']['name'] ) : '';
		return '' !== $field_name ? sanitize_text_field( $field_name ) : __( 'Payment item', 'payments-connect-square' );
	}

	/**
	 * Square checkout order-summary item name (not the page description/title).
	 *
	 * @param object               $form            Fluent Forms form object.
	 * @param array<string, mixed> $submission_data Submission payload.
	 * @param array<int, array<string, mixed>> $line_items Built Square line items.
	 * @return string
	 */
	private function resolve_square_order_item_name( $form, $submission_data, array $line_items ) {
		if ( ! empty( $line_items[0]['name'] ) ) {
			return sanitize_text_field( (string) $line_items[0]['name'] );
		}

		return $this->resolve_payment_item_display_name( $form, $submission_data );
	}

	/**
	 * @param object               $form            Fluent Forms form object.
	 * @param array<string, mixed> $submission_data Submission payload.
	 * @return string
	 */
	private function resolve_payment_item_display_name( $form, $submission_data ) {
		$form_line_items = $this->resolve_payment_line_items_from_form_fields( $form, $submission_data, 'USD' );
		if ( ! empty( $form_line_items[0]['name'] ) ) {
			return sanitize_text_field( (string) $form_line_items[0]['name'] );
		}

		if ( method_exists( $this, 'getOrderItems' ) ) {
			foreach ( $this->getOrderItems() as $item ) {
				if ( ! is_object( $item ) ) {
					continue;
				}

				$item_type = isset( $item->type ) ? (string) $item->type : 'single';
				if ( 'discount' === $item_type ) {
					continue;
				}

				$name = isset( $item->item_name ) ? trim( (string) $item->item_name ) : '';
				if ( '' !== $name ) {
					return sanitize_text_field( $name );
				}
			}
		}

		$field_label = $this->resolve_payment_field_label( $form, $submission_data );
		if ( '' !== $field_label ) {
			return $field_label;
		}

		return __( 'Payment item', 'payments-connect-square' );
	}

	/**
	 * @param string $name       Line item label.
	 * @param int    $quantity   Quantity.
	 * @param int    $unit_cents Unit price in cents.
	 * @param string $currency   ISO currency code.
	 * @return array<string, mixed>
	 */
	private function make_square_line_item_from_payment( $name, $quantity, $unit_cents, $currency ) {
		$name = sanitize_text_field( (string) $name );
		if ( '' === $name ) {
			$name = __( 'Payment item', 'payments-connect-square' );
		}

		return array(
			'name'             => $name,
			'quantity'         => (string) max( 1, (int) $quantity ),
			'base_price_money' => array(
				'amount'   => max( 0, (int) $unit_cents ),
				'currency' => strtoupper( sanitize_text_field( (string) $currency ) ),
			),
		);
	}

	/**
	 * @param array<int, array<string, mixed>> $line_items Square line items.
	 * @return int
	 */
	private function sum_square_line_items_cents( array $line_items ) {
		$total = 0;
		foreach ( $line_items as $line_item ) {
			$qty  = isset( $line_item['quantity'] ) ? max( 1, (int) $line_item['quantity'] ) : 1;
			$unit = isset( $line_item['base_price_money']['amount'] ) ? (int) $line_item['base_price_money']['amount'] : 0;
			$total += $unit * $qty;
		}

		return max( 0, $total );
	}

	/**
	 * @param object               $form            Fluent Forms form object.
	 * @param array<string, mixed> $submission_data Submission payload.
	 * @param int                  $amount_cents    Current total in cents.
	 * @return int
	 */
	private function adjust_amount_for_submission_quantity( $form, $submission_data, $amount_cents ) {
		$response = $this->extract_submission_response( $submission_data );
		if ( empty( $response ) || $amount_cents <= 0 || ! method_exists( $this, 'getOrderItems' ) ) {
			return $amount_cents;
		}

		$parsed      = $this->parse_payment_form_fields( $form );
		$quantity_map = $parsed['quantity_map'];
		if ( empty( $quantity_map ) ) {
			return $amount_cents;
		}

		$order_items = $this->getOrderItems();
		if ( empty( $order_items ) ) {
			$computed = $this->compute_payment_total_from_form_fields( $form, $submission_data );
			return $computed > 0 ? $computed : $amount_cents;
		}

		foreach ( $order_items as $item ) {
			if ( ! is_object( $item ) ) {
				continue;
			}

			$item_type = isset( $item->type ) ? (string) $item->type : 'single';
			if ( 'discount' === $item_type ) {
				continue;
			}

			$parent = isset( $item->parent_holder ) ? (string) $item->parent_holder : '';
			if ( '' === $parent || ! isset( $quantity_map[ $parent ] ) ) {
				continue;
			}

			$submission_qty = $this->get_field_quantity( $quantity_map, $parent, $response );
			$stored_qty     = isset( $item->quantity ) ? (int) $item->quantity : 1;
			if ( $submission_qty <= $stored_qty ) {
				continue;
			}

			$unit_price = isset( $item->item_price ) ? (int) $item->item_price : 0;
			if ( $unit_price <= 0 ) {
				continue;
			}

			$old_line = isset( $item->line_total ) ? (int) $item->line_total : ( $unit_price * $stored_qty );
			$new_line = $unit_price * $submission_qty;
			$amount_cents = $amount_cents - $old_line + $new_line;
		}

		return max( 0, $amount_cents );
	}

	/**
	 * @param object               $form            Fluent Forms form object.
	 * @param array<string, mixed> $submission_data Submission payload.
	 * @param string               $field_name      Optional payment field name.
	 * @return string
	 */
	private function resolve_payment_field_label( $form, $submission_data, $field_name = '' ) {
		$parsed   = $this->parse_payment_form_fields( $form );
		$response = $this->extract_submission_response( $submission_data );

		foreach ( $parsed['payment_inputs'] as $payment_input ) {
			$name = isset( $payment_input['attributes']['name'] ) ? $this->normalize_payment_field_name( (string) $payment_input['attributes']['name'] ) : '';
			if ( '' !== $field_name && $name !== $this->normalize_payment_field_name( $field_name ) ) {
				continue;
			}

			if ( '' !== $name && isset( $response[ $name ] ) && '' !== $response[ $name ] ) {
				$selected = $response[ $name ];
				if ( is_array( $selected ) ) {
					$selected = reset( $selected );
				}
				$option_label = $this->get_option_label_from_payment_field( $payment_input, $selected, $form );
				if ( '' !== $option_label ) {
					return $option_label;
				}
			}

			$label = isset( $payment_input['settings']['label'] ) ? trim( (string) $payment_input['settings']['label'] ) : '';
			if ( '' !== $label ) {
				return sanitize_text_field( $label );
			}

			$admin_label = isset( $payment_input['settings']['admin_field_label'] ) ? trim( (string) $payment_input['settings']['admin_field_label'] ) : '';
			if ( '' !== $admin_label ) {
				return sanitize_text_field( $admin_label );
			}

			if ( '' !== $name ) {
				return sanitize_text_field( $name );
			}
		}

		return '';
	}

	/**
	 * Build Square line items from Fluent Forms order items (name, unit price, quantity).
	 *
	 * @param object               $form            Fluent Forms form object.
	 * @param array<string, mixed> $submission_data Submission payload.
	 * @param string               $currency        ISO currency code.
	 * @param int                  $amount_cents    Expected total in cents.
	 * @return array<int, array<string, mixed>>
	 */
	private function build_square_payment_line_items( $form, $submission_data, $currency, $amount_cents ) {
		$currency   = strtoupper( sanitize_text_field( (string) $currency ) );
		$line_items = $this->build_square_line_items_from_order_items( $form, $submission_data, $currency );
		if ( ! empty( $line_items ) ) {
			return $line_items;
		}

		$line_items = $this->resolve_payment_line_items_from_form_fields( $form, $submission_data, $currency );
		if ( ! empty( $line_items ) ) {
			return $line_items;
		}

		return array(
			array(
				'name'             => $this->resolve_payment_item_display_name( $form, $submission_data ),
				'quantity'         => '1',
				'base_price_money' => array(
					'amount'   => max( 0, (int) $amount_cents ),
					'currency' => $currency,
				),
			),
		);
	}

	/**
	 * Prefer Fluent Forms order items (same source as payment summary).
	 *
	 * @param object               $form            Fluent Forms form object.
	 * @param array<string, mixed> $submission_data Submission payload.
	 * @param string               $currency        ISO currency code.
	 * @return array<int, array<string, mixed>>
	 */
	private function build_square_line_items_from_order_items( $form, $submission_data, $currency ) {
		if ( ! method_exists( $this, 'getOrderItems' ) ) {
			return array();
		}

		$line_items = array();
		foreach ( $this->getOrderItems() as $item ) {
			if ( ! is_object( $item ) ) {
				continue;
			}

			$item_type = isset( $item->type ) ? (string) $item->type : 'single';
			if ( 'discount' === $item_type ) {
				continue;
			}

			$name = isset( $item->item_name ) ? trim( (string) $item->item_name ) : '';
			if ( '' === $name ) {
				$parent = isset( $item->parent_holder ) ? (string) $item->parent_holder : '';
				$name   = $this->resolve_payment_field_label( $form, $submission_data, $parent );
			}
			if ( '' === $name ) {
				$name = $this->resolve_payment_item_display_name( $form, $submission_data );
			}

			$qty = max( 1, isset( $item->quantity ) ? (int) $item->quantity : 1 );
			$unit_cents = isset( $item->item_price ) ? (int) $item->item_price : 0;
			if ( $unit_cents <= 0 && $qty > 0 && isset( $item->line_total ) ) {
				$unit_cents = (int) round( (int) $item->line_total / $qty );
			}
			if ( $unit_cents <= 0 ) {
				continue;
			}

			$line_items[] = array(
				'name'             => sanitize_text_field( $name ),
				'quantity'         => (string) $qty,
				'base_price_money' => array(
					'amount'   => $unit_cents,
					'currency' => $currency,
				),
			);
		}

		return $line_items;
	}

	/**
	 * @param object $form Form object.
	 * @return string
	 */
	private function resolve_currency( $form ) {
		if ( class_exists( '\FluentForm\App\Modules\Payments\PaymentHelper' ) && isset( $form->id ) ) {
			return (string) \FluentForm\App\Modules\Payments\PaymentHelper::getFormCurrency( (int) $form->id );
		}

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

		return 'USD';
	}

	/**
	 * @param object $form Form object.
	 * @return string
	 */
	private function resolve_return_url( $form ) {
		$form_id = isset( $form->id ) ? (int) $form->id : 0;
		if ( $form_id > 0 && function_exists( 'wpFluent' ) ) {
			$row = wpFluent()->table( 'fluentform_forms' )->find( $form_id );
			if ( $row && ! empty( $row->settings ) ) {
				$settings = json_decode( (string) $row->settings, true );
				if ( is_array( $settings ) && ! empty( $settings['confirmation']['redirectTo'] ) ) {
					return esc_url_raw( (string) $settings['confirmation']['redirectTo'] );
				}
			}
		}

		$referer = wp_get_referer();
		if ( is_string( $referer ) && '' !== $referer ) {
			return esc_url_raw( $referer );
		}

		return home_url( '/' );
	}

	/**
	 * @param array<string, mixed> $response Square API response.
	 * @return string
	 */
	private static function extract_square_order_id( $response ) {
		if ( ! empty( $response['payment_link']['order_id'] ) ) {
			return sanitize_text_field( (string) $response['payment_link']['order_id'] );
		}
		return '';
	}
}
