<?php
/**
 * Smart Buttons Handler Class
 *
 * @package FunnelKit_Square
 * @subpackage Payment
 */

namespace FKWCSQ\Includes;

use FKWCSQ\Includes\Modules\Payment\Gateways\Apple_Pay;
use FKWCSQ\Includes\Modules\Payment\Gateways\Google_Pay;
use FKWCSQ\Includes\Traits\Instance;
use Exception;
use FKWCSQ\Square;
use function add_action;
use function absint;
use function wc_clean;
use function wp_send_json;
use function wp_send_json_error;
use function wp_send_json_success;
use function wp_create_nonce;
use function sanitize_text_field;
use function wp_unslash;
use function wc_maybe_define_constant;
use function get_option;
use function get_woocommerce_currency;
use function get_bloginfo;
use function get_query_var;
use function is_wc_endpoint_url;
use function get_current_user_id;
use function apply_filters;
use function esc_html__;
use function sprintf;
use function number_format;

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

/**
 * Smart Buttons Class
 * Handles AJAX operations and dependencies for smart payment buttons (Google Pay, Apple Pay, etc.)
 */
#[\AllowDynamicProperties]
class SmartButtons {
	use Instance;

	/**
	 * API instance
	 *
	 * @var object
	 */
	public $api;

	/**
	 * Constructor
	 */
	public function __construct() {
		if ( null === self::$instance ) {
			$this->init();
			$this->init_hooks();
			self::$instance = $this;
		}
	}

	/**
	 * Initialize the class
	 */
	public function init() {
		$this->api = API::get_instance();
	}

	/**
	 * Initialize hooks
	 */
	public function init_hooks() {
		// AJAX handlers
		add_filter( 'woocommerce_update_order_review_fragments', array( $this, 'checkout_fragments' ) );
		add_action( 'wc_ajax_fkwcsq_get_request_data', array( $this, 'get_request_data' ) );
		add_action( 'wc_ajax_fkwcsq_fetch_cart_details', array( $this, 'get_cart_details' ) );
		add_action( 'wc_ajax_fkwcsq_add_to_cart', array( $this, 'ajax_add_to_cart' ) );
		add_action( 'wc_ajax_fkwcsq_process_smart_button_payment', array( $this, 'google_pay_payment' ) );
		add_action( 'wp', array( $this, 'setup_gateway' ), 10 );
		add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) );
		add_action( 'woocommerce_proceed_to_checkout', array( $this, 'print_smart_btn_wrapper' ), 14 );
		add_action( 'woocommerce_before_checkout_form', array( $this, 'print_smart_btn_wrapper' ), 15 );
	}

	public function payment_scripts() {
		try {
			// Only load scripts on pages where smart buttons should be displayed
			if ( ! $this->should_load_scripts() ) {
				return;
			}

			$gpay_available      = Google_Pay::get_instance()->is_available_display_location();
			$apple_pay_available = Apple_Pay::get_instance()->is_available_display_location();

			if ( ! ( $gpay_available || $apple_pay_available ) ) {
				return;
			}

			if ( ! wp_script_is( 'square-payment-form' ) ) {
				wp_enqueue_script( 'square-payment-form', Square::get_web_sdk_url(), array(), FKWCSQ_VERSION, true );
			}
			wp_enqueue_script( 'funnelkit-square-smart-buttons', FKWCSQ_PLUGIN_URL . 'assets/js/smart-button' . $this->api->is_min_suffix() . '.js', array( 'jquery' ), FKWCSQ_VERSION, true );
			wp_enqueue_style( 'fkwcsq_smart_css', FKWCSQ_PLUGIN_URL . 'assets/css/smart-button' . $this->api->is_min_suffix() . '.css', array(), FKWCSQ_VERSION );
			wp_localize_script( 'funnelkit-square-smart-buttons', 'fkwcsq_square_smart_buttons', $this->localize_data() );
		} catch ( \Exception | \Error $e ) {

		}
	}

	/**
	 * Check if current page uses WooCommerce Blocks checkout
	 *
	 * @return bool
	 */
	private function is_blocks_checkout() {
		// Check using WooCommerce's built-in utility if available
		if ( class_exists( '\Automattic\WooCommerce\Blocks\Utils\CartCheckoutUtils' ) ) {
			if ( method_exists( '\Automattic\WooCommerce\Blocks\Utils\CartCheckoutUtils', 'is_checkout_block_in_use' ) ) {
				return \Automattic\WooCommerce\Blocks\Utils\CartCheckoutUtils::is_checkout_block_in_use();
			}
		}

		// Fallback: Check if current page contains checkout block
		if ( function_exists( 'is_checkout' ) && is_checkout() ) {
			global $post;
			if ( $post && has_block( 'woocommerce/checkout', $post ) ) {
				return true;
			}
		}

		return false;
	}

	/**
	 * Check if scripts should be loaded on current page
	 *
	 * @return bool
	 */
	private function should_load_scripts() {
		// Don't load on blocks checkout - blocks have their own implementation
		if ( $this->is_blocks_checkout() ) {
			return false;
		}

		// Load on checkout pages (classic only)
		if ( function_exists( 'is_checkout' ) && is_checkout() ) {
			return true;
		}

		// Load on cart page
		if ( function_exists( 'is_cart' ) && is_cart() ) {
			return true;
		}

		// Load on product pages
		if ( function_exists( 'is_product' ) && is_product() ) {
			return true;
		}

		// Load on shop page
		if ( function_exists( 'is_shop' ) && is_shop() ) {
			return true;
		}

		// Load on product category pages
		if ( function_exists( 'is_product_category' ) && is_product_category() ) {
			return true;
		}

		// Load on product tag pages
		if ( function_exists( 'is_product_tag' ) && is_product_tag() ) {
			return true;
		}

		return false;
	}

	public function localize_data() {
		$current_environment = \FKWCSQ\Square::is_sandbox_mode() ? 'TEST' : 'PRODUCTION';

		$is_product = function_exists( 'is_product' ) ? ( is_product() ? 'yes' : 'no' ) : 'no';

		$localize_data = array(
			'location_id'      => $this->api->get_location_id(),
			'ajax_url'         => admin_url( 'admin-ajax.php' ),
			'nonce'            => wp_create_nonce( 'funnelkit-square-google-pay' ),
			'currency'         => get_woocommerce_currency(),
			'country'          => WC()->customer ? WC()->customer->get_billing_country() : WC()->countries->get_base_country(),
			'total'            => WC()->cart ? WC()->cart->get_total( 'raw' ) : '0',
			'is_product'       => $is_product,
			'is_cart'          => function_exists( 'is_cart' ) ? ( is_cart() ? 'yes' : 'no' ) : 'no',
			'is_checkout'      => is_checkout() ? 'yes' : 'no',
			'is_pay_for_order' => isset( $_GET['pay_for_order'] ) ? 'yes' : 'no', //phpcs:ignore WordPress.Security.NonceVerification.Recommended
			'order_id'         => isset( $_GET['pay_for_order'] ) ? absint( $_GET['pay_for_order'] ) : '0', //phpcs:ignore WordPress.Security.NonceVerification.Recommended
			'environment'      => strtoupper( $current_environment ),
			'application_id'   => Square::get_application_id(),
		);

		if ( isset( $_GET['pay_for_order'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$is_pay_for_order_page = isset( $_POST['is_pay_for_order_page'] ) ? 'true' === sanitize_text_field( wp_unslash( $_POST['is_pay_for_order_page'] ) ) : is_wc_endpoint_url( 'order-pay' ); //phpcs:ignore WordPress.Security.NonceVerification.Missing, FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Frontend payment page, nonce handled by WooCommerce, guest users allowed
			$order_id              = isset( $_POST['order_id'] ) ? (int) sanitize_text_field( wp_unslash( $_POST['order_id'] ) ) : absint( get_query_var( 'order-pay' ) ); //phpcs:ignore WordPress.Security.NonceVerification.Missing, FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Frontend payment page, nonce handled by WooCommerce, guest users allowed
			$order                 = wc_get_order( $order_id );
			$payment_request       = $this->build_payment_request(
				$order->get_total(),
				array(
					'order_id'              => $order_id,
					'is_pay_for_order_page' => $is_pay_for_order_page,
				)
			);

			$localize_data['order_pay_data'] = $payment_request;
		}

		return apply_filters( 'fkwcsq_smart_button_localize_data', $localize_data );
	}


	public function checkout_fragments( $fragments ) {
		if ( ! isset( $fragments['fkwcsq_payment_request'] ) ) {
			$payment_request         = $this->get_request_data( true );
			$payment_request['show'] = ! Square::cart_contains_subscription();
			$fragments['fkwcsq_payment_request'] = $payment_request;
		}

		return $fragments;
	}

	public function setup_gateway() {
		try {
			WC()->payment_gateways()->get_available_payment_gateways();
		} catch ( Exception | \Error $e ) {

		}
	}

	/**
	 * AJAX handler for adding to cart and fetching shipping
	 */
	public function ajax_add_to_cart() {
		// Verify nonce for security
		if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'funnelkit-square-google-pay' ) ) { //phpcs:ignore FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Nonce verification in progress, guest users allowed
			wp_send_json_error( __( 'Security check failed.', 'funnelkit-payment-gateway-square-for-woocommerce' ) );
		}

		// Support both simple and variable products
		$product_id   = absint( $_POST['product_id'] ?? ( $_POST['fkwcsq-add-to-cart'] ?? 0 ) ); //phpcs:ignore FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Nonce verified above, guest users allowed
		$variation_id = absint( $_POST['variation_id'] ?? 0 ); //phpcs:ignore FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Nonce verified above, guest users allowed
		$quantity     = absint( $_POST['quantity'] ?? 1 ); //phpcs:ignore FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Nonce verified above, guest users allowed
		// Collect variation attributes from POST
		$attributes = array();
		foreach ( $_POST as $key => $value ) { //phpcs:ignore FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Nonce verified above, guest users allowed
			if ( strpos( $key, 'attribute_' ) === 0 ) {
				$attributes[ $key ] = wc_clean( $value );
			}
		}
		try {
			$cart = WC()->cart;
			$cart->empty_cart();
			// Add to cart logic for variable or simple product
			$cart->add_to_cart( $product_id, $quantity, $variation_id, $attributes );
			$this->get_request_data();
		} catch ( \Exception $e ) {
			wp_send_json( array( 'error' => $e->getMessage() ) );
		}
	}

	/**
	 * Process Google Pay payment
	 */
	public function google_pay_payment() {
		if ( WC()->cart->is_empty() ) {
			wp_send_json_error( __( 'Empty cart', 'funnelkit-payment-gateway-square-for-woocommerce' ) );
		}

		// Auto-detect or create user by billing email for express payments.
		$this->maybe_assign_or_create_customer();

		wc_maybe_define_constant( 'WOOCOMMERCE_CHECKOUT', true );
		$_REQUEST['_wpnonce'] = wp_create_nonce( 'woocommerce-process_checkout' ); //phpcs:ignore WordPress.Security.NonceVerification.Recommended, FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Creating nonce for checkout process, guest users allowed
		$_POST['_wpnonce']    = ! empty( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended, FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Creating nonce for checkout process, guest users allowed
		add_filter( 'woocommerce_cart_needs_payment', '__return_true', PHP_INT_MAX );
		add_filter( 'woocommerce_checkout_fields', array( $this, 'un_required_billing_address' ), PHP_INT_MAX );

		add_action( 'woocommerce_before_checkout_process', array( $this, 'remove_street_address_validation' ), 10 );
		if ( class_exists( '\WC_Subscriptions_Cart' ) ) {
			remove_action( 'woocommerce_after_checkout_validation', 'WC_Subscriptions_Cart::validate_recurring_shipping_methods' );
		}
		WC()->session->reload_checkout = true;

		WC()->checkout()->process_checkout();
		exit();
	}

	/**
	 * Auto-detect existing user by billing email or create a new account.
	 *
	 * For express payments (Google Pay / Apple Pay), the user is typically not logged in.
	 * This method:
	 * 1. Checks if a WordPress user exists with the billing email — if so, auto-assigns the order.
	 * 2. If no user exists and WooCommerce account creation is enabled, flags WooCommerce
	 *    to create an account during checkout.
	 */
	private function maybe_assign_or_create_customer() {
		$billing_email = isset( $_POST['billing_email'] ) ? sanitize_email( wp_unslash( $_POST['billing_email'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Missing, FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Express payment endpoint, guest users allowed

		if ( empty( $billing_email ) || is_user_logged_in() ) {
			return;
		}

		// If guest checkout is enabled, simply return.
		if ( 'yes' === get_option( 'woocommerce_enable_guest_checkout' ) ) {
			return;
		}

		$existing_user = get_user_by( 'email', $billing_email );

		if ( $existing_user ) {
			// Existing user found — auto-assign the order to this customer.
			wp_set_current_user( $existing_user->ID );
			wc_set_customer_auth_cookie( $existing_user->ID );
		} elseif ( 'yes' === get_option( 'woocommerce_enable_signup_and_login_from_checkout' ) ) {
			// No user found — tell WooCommerce to create an account during checkout.
			$_POST['createaccount'] = 1; //phpcs:ignore WordPress.Security.NonceVerification.Missing, FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Express payment endpoint, guest users allowed, value is a flag
		// Also set the username field as the email for further WooCommerce processing.
		$_POST['account_username'] = $billing_email; //phpcs:ignore WordPress.Security.NonceVerification.Missing, FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Express payment endpoint
		}
	}

	/**
	 * Remove street validation for smart button checkout process
	 */
	public function remove_street_address_validation() {
		if ( class_exists( '\WFACP_Template_Common' ) && function_exists( 'wfacp_template' ) ) {
			if ( wfacp_template() instanceof \WFACP_Template_Common ) {
				remove_action( 'woocommerce_checkout_process', array( wfacp_template(), 'process_fields' ) );
			}
		}
	}

	/**
	 * Get WooCommerce default fields
	 */
	public function get_wc_default_fields_fields() {
		return array(
			'billing_first_name',
			'billing_last_name',
			'account_password',
			'billing_company',
			'billing_address_1',
			'billing_address_2',
			'billing_city',
			'billing_state',
			'billing_email',
			'billing_same_as_shipping',
			'billing_phone',
			'shipping_first_name',
			'shipping_last_name',
			'shipping_company',
			'shipping_address_1',
			'shipping_address_2',
			'shipping_city',
			'shipping_state',
			'shipping_postcode',
			'shipping_country',
			'shipping_phone',
		);
	}

	/**
	 * Make billing fields unrequired for smart button interfaces
	 */
	public function un_required_billing_address( $fields ) {
		if ( ! isset( $fields['billing'] ) || empty( $fields['billing'] ) ) {
			return $fields;
		}

		$required_fields = $this->get_wc_default_fields_fields();

		foreach ( $fields['billing'] as $key => $field ) {
			if ( in_array( $key, $required_fields, true ) && isset( $fields['billing'][ $key ] ) && isset( $fields['billing'][ $key ]['required'] ) ) {
				$fields['billing'][ $key ]['required'] = false;
			}
		}

		if ( isset( $fields['account'] ) && isset( $fields['account']['account_password'] ) ) {
			$fields['account']['account_password']['required'] = false;
		}
		if ( ! empty( $_POST ) && isset( $_POST['billing_email'] ) && isset( $_POST['billing_email_2'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Missing, FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Creating nonce for checkout process, guest users allowed
			$_POST['billing_email_2'] = sanitize_email( wp_unslash( $_POST['billing_email'] ) ); //phpcs:ignore WordPress.Security.NonceVerification.Missing, FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Creating nonce for checkout process, guest users allowed
		}

		return $fields;
	}

	/**
	 * Get request data for payment
	 */
	public function get_request_data( $return = false ) {
		WC()->cart->calculate_totals();
		$amount          = WC()->cart->get_total( 'raw' );
		$payment_request = $this->build_payment_request( $amount );

		if ( $return === true ) {
			return $payment_request;
		}
		wp_send_json(
			array(
				'data'    => $payment_request,
				'success' => true,
			)
		);
	}


	/**
	 * Build payment request
	 */
	public function build_payment_request( $amount, $data = array() ) {
		$is_pay_for_order_page = isset( $data['is_pay_for_order_page'] ) ? $data['is_pay_for_order_page'] : false;
		$order_id              = isset( $data['order_id'] ) ? $data['order_id'] : 0;

		if ( $is_pay_for_order_page ) {
			$request_shipping_contact = false;
		} else {
			$request_shipping_contact = isset( WC()->cart ) && WC()->cart->needs_shipping();
		}

		$order_data = array();
		$data       = wp_parse_args(
			$data,
			array(
				'requestShippingContact' => $request_shipping_contact,
				'requestEmailAddress'    => true,
				'requestBillingContact'  => true,
				'countryCode'            => substr( get_option( 'woocommerce_default_country' ), 0, 2 ),
				'currencyCode'           => get_woocommerce_currency(),
			)
		);

		if ( $is_pay_for_order_page ) {
			$order      = wc_get_order( $order_id );
			$order_data = array(
				'subtotal' => $order->get_subtotal(),
				'discount' => $order->get_discount_total(),
				'shipping' => $order->get_shipping_total(),
				'fees'     => $order->get_total_fees(),
				'taxes'    => $order->get_total_tax(),
			);
			unset( $data['is_pay_for_order_page'], $data['order_id'] );
		}

		if ( count( WC()->shipping->get_packages() ) > 1 ) {
			throw new \Exception( esc_html__( 'This payment method cannot be used for multiple shipments.', 'funnelkit-payment-gateway-square-for-woocommerce' ) );
		}

		if ( ! isset( $data['lineItems'] ) ) {
			$data['lineItems'] = $this->build_payment_request_line_items( $order_data );
		}

		if ( true === $data['requestShippingContact'] ) {
			$data['shippingOptions'] = array(
				array(
					'id'      => '0',
					'label'   => __( 'Pending', 'funnelkit-payment-gateway-square-for-woocommerce' ),
					'amount'  => '0.00',
					'pending' => false,
				),
			);
		}

		$data['total'] = array(
			'label'   => get_bloginfo( 'name', 'display' ),
			'amount'  => number_format( $amount, 2, '.', '' ),
			'pending' => false,
		);

		return $data;
	}

	/**
	 * Get cart details
	 */
	public function get_cart_details() {
		// Verify nonce for security
		if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'funnelkit-square-google-pay' ) ) { //phpcs:ignore FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Nonce verification in progress, guest users allowed
			wp_send_json_error( __( 'Security check failed.', 'funnelkit-payment-gateway-square-for-woocommerce' ) );
		}

		wc_maybe_define_constant( 'WOOCOMMERCE_CART', true );
		$payment_request = array();

		$is_pay_for_order_page = isset( $_POST['is_pay_for_order_page'] ) ? 'true' === sanitize_text_field( wp_unslash( $_POST['is_pay_for_order_page'] ) ) : is_wc_endpoint_url( 'order-pay' ); //phpcs:ignore FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Nonce verified above, guest users allowed
		$order_id              = isset( $_POST['order_id'] ) ? (int) sanitize_text_field( wp_unslash( $_POST['order_id'] ) ) : absint( get_query_var( 'order-pay' ) ); //phpcs:ignore FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Nonce verified above, guest users allowed
		$order_data            = array();

		if ( WC()->cart->needs_shipping() || $is_pay_for_order_page ) {
			if ( ! empty( $_POST['fkwcsq_shipping_address_contact'] ) ) { //phpcs:ignore FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Nonce verified above, guest users allowed
				$shipping_address = wp_parse_args(
					wc_clean( wp_unslash( $_POST['fkwcsq_shipping_address_contact'] ) ), //phpcs:ignore FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Nonce verified above, guest users allowed
					array(
						'countryCode' => null,
						'state'       => null,
						'city'        => null,
						'postalCode'  => null,
						'address'     => null,
						'address_2'   => null,
					)
				);

				if ( isset( $shipping_address['countryCode'] ) && isset( $shipping_address['state'] ) ) {
					$shipping_address['state'] = $this->get_state_code( $shipping_address['countryCode'], $shipping_address['state'] );
				}
				$this->calculate_shipping( $shipping_address );
				$payment_request['shippingOptions'] = $this->get_formatted_shipping_methods();
			} elseif ( ! empty( wc_clean( wp_unslash( $_POST['fkwcsq_choosen_shipping_method'] ) ) ) ) { //phpcs:ignore FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Nonce verified above, guest users allowed
				$chosen_methods = array( wc_clean( wp_unslash( $_POST['fkwcsq_choosen_shipping_method'] ) ) ); //phpcs:ignore FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Nonce verified above, guest users allowed
				$this->update_shipping_method( $chosen_methods );
			}
		}

		if ( ! $is_pay_for_order_page ) {
			WC()->cart->calculate_totals();
		}

		if ( $is_pay_for_order_page ) {
			$order      = wc_get_order( $order_id );
			$order_data = array(
				'subtotal' => $order->get_subtotal(),
				'discount' => $order->get_discount_total(),
				'shipping' => $order->get_shipping_total(),
				'fees'     => $order->get_total_fees(),
				'taxes'    => $order->get_total_tax(),
			);
		}

		$payment_request['lineItems'] = $this->build_payment_request_line_items( $order_data );

		if ( $is_pay_for_order_page ) {
			$total_amount = $order->get_total();
		} else {
			// Ensure cart totals are calculated
			WC()->cart->calculate_totals();
			// Get the total including all taxes, fees, and discounts
			$total_amount = WC()->cart->get_total( 'edit' );
		}

		$payment_request['total'] = array(
			'label'   => get_bloginfo( 'name', 'display' ),
			'amount'  => number_format( $total_amount, 2, '.', '' ),
			'pending' => false,
		);

		wp_send_json_success( $payment_request );
	}

	/**
	 * Returns location's state code by state name.
	 */
	public static function get_state_code( $country_code = '', $state_name = '' ) {
		if ( empty( $country_code ) || empty( $state_name ) ) {
			return '';
		}

		$states    = WC()->countries->get_states( $country_code );
		$countries = WC()->countries->get_countries();

		if ( false === $states && isset( $countries[ $country_code ] ) ) {
			return $state_name;
		}

		if ( is_array( $states ) ) {
			if ( isset( $states[ $state_name ] ) ) {
				return $state_name;
			}

			foreach ( $states as $code => $name ) {
				if ( $name === $state_name ) {
					return $code;
				}
			}
		}

		return '';
	}

	/**
	 * Updates shipping method in WC session
	 */
	public function update_shipping_method( $shipping_methods ) {
		$chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' );

		if ( is_array( $shipping_methods ) ) {
			foreach ( $shipping_methods as $i => $value ) {
				$chosen_shipping_methods[ $i ] = wc_clean( $value );
			}
		}

		WC()->session->set( 'chosen_shipping_methods', $chosen_shipping_methods );
	}

	/**
	 * Calculate shipping with given address
	 */
	public function calculate_shipping( $address = array() ) {
		WC()->shipping->reset_shipping();

		if ( $address['countryCode'] ) {
			WC()->customer->set_location( strtoupper( $address['countryCode'] ), $address['state'], $address['postalCode'], $address['city'] );
			WC()->customer->set_shipping_location( strtoupper( $address['countryCode'] ), $address['state'], $address['postalCode'], $address['city'] );
		} else {
			WC()->customer->set_billing_address_to_base();
			WC()->customer->set_shipping_address_to_base();
		}

		WC()->customer->set_calculated_shipping( true );
		WC()->customer->save();

		$packages                                = array();
		$packages[0]['contents']                 = WC()->cart->get_cart();
		$packages[0]['contents_cost']            = 0;
		$packages[0]['applied_coupons']          = WC()->cart->applied_coupons;
		$packages[0]['user']['ID']               = get_current_user_id();
		$packages[0]['destination']['country']   = $address['countryCode'];
		$packages[0]['destination']['state']     = $address['state'];
		$packages[0]['destination']['postcode']  = $address['postalCode'];
		$packages[0]['destination']['city']      = $address['city'];
		$packages[0]['destination']['address']   = $address['address'];
		$packages[0]['destination']['address_2'] = $address['address_2'];

		foreach ( WC()->cart->get_cart() as $item ) {
			if ( $item['data']->needs_shipping() ) {
				if ( isset( $item['line_total'] ) ) {
					$packages[0]['contents_cost'] += $item['line_total'];
				}
			}
		}

		$packages = apply_filters( 'woocommerce_cart_shipping_packages', $packages );
		WC()->shipping->calculate_shipping( $packages );
	}

	/**
	 * Build payment request line items
	 */
	public function build_payment_request_line_items( $totals = array() ) {
		$totals     = empty( $totals ) ? $this->get_cart_totals() : $totals;
		$line_items = array();
		$order_id   = isset( $_POST['order_id'] ) ? (int) sanitize_text_field( wp_unslash( $_POST['order_id'] ) ) : absint( get_query_var( 'order-pay' ) ); //phpcs:ignore WordPress.Security.NonceVerification.Missing, FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- Creating nonce for checkout process, guest users allowed

		if ( $order_id ) {
			$order    = wc_get_order( $order_id );
			$iterable = $order->get_items();
		} else {
			$iterable = WC()->cart->get_cart();
		}

		foreach ( $iterable as $item ) {
			if ( $order_id ) {
				$amount         = number_format( $item->get_total(), 2, '.', '' );
				$quantity_label = 1 < $item->get_quantity() ? ' x ' . $item->get_quantity() : '';
				$item_name      = $item->get_name();
			} else {
				// For cart items, use line_total which includes discounts
				$amount         = number_format( $item['line_total'], 2, '.', '' );
				$quantity_label = 1 < $item['quantity'] ? ' x ' . $item['quantity'] : '';
				$item_name      = $item['data']->get_name();
			}

			$line_item = array(
				'label'   => $item_name . $quantity_label,
				'amount'  => $amount,
				'pending' => false,
			);

			$line_items[] = $line_item;
		}

		if ( $totals['shipping'] > 0 ) {
			$line_items[] = array(
				'label'   => __( 'Shipping', 'funnelkit-payment-gateway-square-for-woocommerce' ),
				'amount'  => number_format( $totals['shipping'], 2, '.', '' ),
				'pending' => false,
			);
		}

		if ( $totals['taxes'] > 0 ) {
			$line_items[] = array(
				'label'   => __( 'Tax', 'funnelkit-payment-gateway-square-for-woocommerce' ),
				'amount'  => number_format( $totals['taxes'], 2, '.', '' ),
				'pending' => false,
			);
		}

		if ( $totals['discount'] > 0 ) {
			$line_items[] = array(
				'label'   => __( 'Discount', 'funnelkit-payment-gateway-square-for-woocommerce' ),
				'amount'  => number_format( $totals['discount'], 2, '.', '' ),
				'pending' => false,
			);
		}

		if ( $totals['fees'] > 0 ) {
			$line_items[] = array(
				'label'   => __( 'Fees', 'funnelkit-payment-gateway-square-for-woocommerce' ),
				'amount'  => number_format( $totals['fees'], 2, '.', '' ),
				'pending' => false,
			);
		}

		return $line_items;
	}

	/**
	 * Returns cart totals in an array format
	 */
	public function get_cart_totals() {
		if ( ! isset( WC()->cart ) ) {
			throw new \Exception( 'Cart data cannot be found.' );
		}

		// Ensure cart totals are calculated
		WC()->cart->calculate_totals();

		return array(
			'subtotal' => WC()->cart->subtotal_ex_tax,
			'discount' => WC()->cart->get_cart_discount_total(),
			'shipping' => WC()->cart->shipping_total,
			'fees'     => WC()->cart->fee_total,
			'taxes'    => WC()->cart->tax_total + WC()->cart->shipping_tax_total,
		);
	}


	/**
	 * @return array
	 */
	public function get_shipping_packages() {
		return WC()->shipping()->get_packages();
	}

	/**
	 * Return whether or not the cart is displaying prices including tax, rather than excluding tax
	 *
	 * @return bool
	 */
	public function display_prices_including_tax() {
		$cart = WC()->cart;
		if ( method_exists( $cart, 'display_prices_including_tax' ) ) {
			return $cart->display_prices_including_tax();
		}
		if ( is_callable( array( $cart, 'get_tax_price_display_mode' ) ) ) {
			return 'incl' === $cart->get_tax_price_display_mode() && ( WC()->customer && ! WC()->customer->is_vat_exempt() );
		}

		return 'incl' === $cart->tax_display_cart && ( WC()->customer && ! WC()->customer->is_vat_exempt() );
	}

	protected function get_shipping_method_id( $id ) {
		return $id;
	}

	/**
	 * Get all Shipping methods
	 *
	 * @param $methods
	 *
	 * @return array|mixed
	 */
	public function get_formatted_shipping_methods( $methods = array() ) {
		if ( function_exists( 'wcs_is_subscription' ) && \WC_Subscriptions_Change_Payment_Gateway::$is_request_to_change_payment ) {
			return $methods;
		}

		$methods  = array();
		$packages = $this->get_shipping_packages();
		$incl_tax = $this->display_prices_including_tax();

		foreach ( $packages as $i => $package ) {
			foreach ( $package['rates'] as $rate ) {
				$price     = $incl_tax ? (float) $rate->cost + (float) $rate->get_shipping_tax() : (float) $rate->cost;
				$methods[] = $this->get_formatted_shipping_method( $price, $rate, $i, $package, $incl_tax );
			}
		}

		/**
		 * @param array $methods
		 */
		$methods = apply_filters( 'wc_stripe_get_formatted_shipping_methods', $methods, $this );
		if ( empty( $methods ) ) {
			/** GPay does not like empty shipping methods. Make a temporary one */
			$methods[] = array(
				'id'          => 'default',
				'amount'      => '0.00',
				'label'       => __( 'Waiting...', 'funnelkit-payment-gateway-square-for-woocommerce' ),
				'description' => __( 'loading shipping methods...', 'funnelkit-payment-gateway-square-for-woocommerce' ),
			);
		}

		return $methods;
	}

	public function get_formatted_shipping_method( $price, $rate, $i, $package, $incl_tax ) {
		$method = array(
			'id'     => $this->get_shipping_method_id( $rate->id ),
			'label'  => $this->get_formatted_shipping_label( $price, $rate, $incl_tax ),
			'detail' => '',
			'amount' => (string) $price,
		);

		if ( $incl_tax ) {
			if ( $rate->get_shipping_tax() > 0 && ! wc_prices_include_tax() ) {
				$method['detail'] = WC()->countries->inc_tax_or_vat();
			}
		} elseif ( $rate->get_shipping_tax() > 0 && wc_prices_include_tax() ) {
				$method['detail'] = WC()->countries->ex_tax_or_vat();
		}

		return $method;
	}

	/**
	 * Get formatted shipping label
	 *
	 * @param $price
	 * @param \WC_Shipping_Rate $rate
	 * @param $incl_tax
	 *
	 * @return string
	 */
	protected function get_formatted_shipping_label( $price, $rate, $incl_tax ) {
		$label = sprintf( '%s: %s %s', esc_attr( $rate->get_label() ), number_format( $price, 2 ), get_woocommerce_currency() );
		if ( $incl_tax ) {
			if ( $rate->get_shipping_tax() > 0 && ! wc_prices_include_tax() ) {
				$label .= ' ' . WC()->countries->inc_tax_or_vat();
			}
		} elseif ( $rate->get_shipping_tax() > 0 && wc_prices_include_tax() ) {
				$label .= ' ' . WC()->countries->ex_tax_or_vat();
		}

		return $label;
	}


	public function print_smart_btn_wrapper() {
		$is_cart = current_action() === 'woocommerce_proceed_to_checkout';
		if ( $is_cart ) {
			return;
		}
		if ( ! $is_cart && Square::cart_contains_subscription() ) {
			return;
		}

		$wrapper_action = $is_cart ? 'fkwcsq_smart_button_cart_wrapper' : 'fkwcsq_smart_button_wrapper';
		ob_start();
		do_action( $wrapper_action );
		$buttons_markup = ob_get_clean();
		if ( empty( trim( (string) $buttons_markup ) ) ) {
			return;
		}

		$google = Google_Pay::get_instance();
		$apple  = Apple_Pay::get_instance();

		$separator = ( $google->enabled === 'yes' && ! empty( $google->get_option( 'separator_text' ) ) || $apple->enabled === 'yes' && ! empty( $apple->get_option( 'separator_text' ) ) );

		$or_text = '';
		if ( $separator ) {
			$or_text = $google->get_option( 'separator_text' );
			if ( empty( $or_text ) ) {
				$or_text = $apple->get_option( 'separator_text' );
			}
		}

		?>
		<div class="fkwcsq_express_container <?php echo esc_attr( current_action() ); ?>" style="<?php echo $is_cart ? '' : 'display:none;'; ?>">
			<fieldset>
				<legend>
					<legend><?php echo esc_html__( 'Express Checkout', 'funnelkit-payment-gateway-square-for-woocommerce' ); ?></legend>
				</legend>
				<div id="fkwcsq-smart-button-wrapper" style="display:flex">
					<?php
					echo wp_kses_post( $buttons_markup );
					?>
				</div>
			</fieldset>
			<?php
			if ( $separator && ! empty( $or_text ) ) {
				?>
				<div class="fkwcsq-smart-button-separator"><?php echo esc_html( $or_text ); ?></div>
			<?php } ?>
		</div>
		<?php
	}
}

