<?php
/**
 * Cash App Payment Gateway
 *
 * Square Cash App Pay integration for WooCommerce.
 * Supports US, CA, AU markets with USD, CAD, AUD currencies.
 *
 * @package FunnelKit_Square
 * @subpackage Payment
 */

namespace FKWCSQ\Includes\Modules\Payment\Gateways;

use FKWCSQ\Includes\Logger;
use FKWCSQ\Includes\Traits\Instance;
use FKWCSQ\Square;
use WC_Order;

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

/**
 * Cash_App Class.
 *
 * Handles Cash App Pay payments via Square.
 */
class Cash_App extends \WC_Payment_Gateway {
	use Instance;

	/**
	 * Gateway ID.
	 *
	 * @var string
	 */
	public $id = 'fkwcsq_cash_app';

	/**
	 * API instance.
	 *
	 * @var \FKWCSQ\Includes\API
	 */
	protected $api;

	/**
	 * Capture method.
	 *
	 * @var string
	 */
	protected $capture_method;

	/**
	 * Supported countries for Cash App.
	 *
	 * @var array
	 */
	protected $supported_countries = array( 'US' );

	/**
	 * Supported currencies for Cash App.
	 *
	 * @var array
	 */
	protected $supported_currencies = array( 'USD' );

	/**
	 * Constructor.
	 */
	public function __construct() {
		$this->setup_gateway_properties();
		$this->init_form_fields();
		$this->init_settings();
		$this->load_settings();
		$this->init_hooks();
	}

	/**
	 * Set up basic gateway properties.
	 *
	 * @return void
	 */
	public function setup_gateway_properties() {
		$this->has_fields         = true;
		$this->method_title       = __( 'Square Cash App Pay', 'funnelkit-payment-gateway-square-for-woocommerce' );
		$this->method_description = __( 'Accept payments via Cash App using Square. Available in US, Canada, and Australia.', 'funnelkit-payment-gateway-square-for-woocommerce' );
		$this->supports           = array(
			'products',
			'refunds',
		);

		$this->api = \FKWCSQ\Includes\API::get_instance();
	}

	/**
	 * Load settings from database.
	 *
	 * @return void
	 */
	public function load_settings() {
		$this->title          = $this->get_option( 'title' );
		$this->description    = $this->get_option( 'description' );
		$this->capture_method = $this->get_option( 'capture_method', 'automatic' );
	}

	/**
	 * Initialize action hooks.
	 *
	 * @return void
	 */
	public function init_hooks() {
		add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
		add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) );
		add_action( 'woocommerce_review_order_after_submit', array( $this, 'render_cash_app_button_wrapper' ) );
		add_action( 'wfacp_woocommerce_review_order_after_submit', array( $this, 'render_cash_app_button_wrapper' ) );
	}

	/**
	 * Initialize form fields for admin settings.
	 *
	 * @return void
	 */
	public function init_form_fields() {
		$this->form_fields = array(
			'enabled'        => array(
				'title'   => __( 'Enable/Disable', 'funnelkit-payment-gateway-square-for-woocommerce' ),
				'label'   => __( 'Enable Square Cash App Pay', 'funnelkit-payment-gateway-square-for-woocommerce' ),
				'type'    => 'checkbox',
				'default' => 'no',
			),
			'title'          => array(
				'title'       => __( 'Title', 'funnelkit-payment-gateway-square-for-woocommerce' ),
				'type'        => 'text',
				'description' => __( 'Payment method title shown to customer.', 'funnelkit-payment-gateway-square-for-woocommerce' ),
				'default'     => __( 'Cash App Pay', 'funnelkit-payment-gateway-square-for-woocommerce' ),
				'desc_tip'    => true,
			),
			'description'    => array(
				'title'       => __( 'Description', 'funnelkit-payment-gateway-square-for-woocommerce' ),
				'type'        => 'textarea',
				'description' => __( 'Payment method description shown to customer.', 'funnelkit-payment-gateway-square-for-woocommerce' ),
				'default'     => __( 'Pay securely with Cash App.', 'funnelkit-payment-gateway-square-for-woocommerce' ),
				'desc_tip'    => true,
			),
			'capture_method' => array(
				'title'       => __( 'Payment Action', 'funnelkit-payment-gateway-square-for-woocommerce' ),
				'type'        => 'select',
				'description' => __( 'Choose whether to capture payment immediately or authorize only.', 'funnelkit-payment-gateway-square-for-woocommerce' ),
				'default'     => 'automatic',
				'desc_tip'    => true,
				'options'     => array(
					'automatic' => __( 'Capture', 'funnelkit-payment-gateway-square-for-woocommerce' ),
					'manual'    => __( 'Authorize', 'funnelkit-payment-gateway-square-for-woocommerce' ),
				),
			),
		);
	}

	/**
	 * Check if the gateway is available.
	 *
	 * @return bool
	 */
	public function is_available() {
		if ( 'yes' !== $this->enabled ) {
			return false;
		}

		// Check HTTPS (required for production).
		if ( ! Square::is_sandbox_mode() && ! is_ssl() ) {
			return false;
		}

		// Check country restriction.
		$base_country = WC()->countries->get_base_country();
		if ( ! in_array( $base_country, $this->supported_countries, true ) ) {
			return false;
		}

		// Check currency restriction.
		$currency = get_woocommerce_currency();
		if ( ! in_array( $currency, $this->supported_currencies, true ) ) {
			return false;
		}

		// Check Square connection.
		if ( ! Square::get_application_id() || ! $this->api->get_location_id() ) {
			return false;
		}

		return true;
	}

	/**
	 * Enqueue payment scripts.
	 *
	 * @return void
	 */
	/**
	 * Get localize data for this gateway.
	 *
	 * @return array Gateway-specific data.
	 */
	public function get_gateway_data() {
		$cart_total = WC()->cart ? WC()->cart->get_total( 'edit' ) : 0;

		return array(
			'currency_code'   => get_woocommerce_currency(),
			'checkout_url'    => wc_get_checkout_url(),
			'payment_request' => array(
				'total' => array(
					'label'  => get_bloginfo( 'name', 'display' ),
					'amount' => number_format( (float) $cart_total, 2, '.', '' ),
				),
			),
			'i18n'            => array(
				'not_supported' => __( 'Cash App Pay is not available.', 'funnelkit-payment-gateway-square-for-woocommerce' ),
			),
		);
	}

	/**
	 * Enqueue payment scripts.
	 *
	 * @return void
	 */
	public function payment_scripts() {
		if ( ! is_checkout() && ! is_add_payment_method_page() ) {
			return;
		}

		if ( ! $this->is_available() ) {
			return;
		}

		$checkout_scripts = \FKWCSQ\Includes\Checkout_Scripts::get_instance();
		$checkout_scripts->enqueue_checkout_script();
		$checkout_scripts->localize_gateway_data( 'fkwcsq_cash_app_params', $this->id, $this->get_gateway_data() );

		// Add inline CSS for Cash App button visibility toggle (CSS body class approach).
		$inline_css = '
			/* Hide Place Order button when Cash App is selected (classic and blocks checkout) */
			body.fkwcsq-cash-app-selected #place_order,
			body.fkwcsq-cash-app-selected .wfacp-order-place-btn-wrap,
			body.fkwcsq-cash-app-selected .wc-block-components-checkout-place-order-button {
				display: none !important;
			}

			/* Show Cash App button wrapper when Cash App is selected */
			body.fkwcsq-cash-app-selected #fkwcsq-cash-app-button-wrapper {
				display: block !important;
			}

			/* Hide Cash App button wrapper by default */
			#fkwcsq-cash-app-button-wrapper {
				display: none;
			}

			#fkwcsq-cash-app-container {
				margin: 10px 0;
			}

			#fkwcsq-cash-app-error {
				color: #dc3545;
				margin-top: 10px;
				display: none;
			}
		';

		// Register and enqueue inline CSS.
		wp_register_style( 'fkwcsq-cash-app-inline', false, array(), FKWCSQ_VERSION );
		wp_enqueue_style( 'fkwcsq-cash-app-inline' );
		wp_add_inline_style( 'fkwcsq-cash-app-inline', $inline_css );
	}

	/**
	 * Render payment fields on checkout.
	 *
	 * @return void
	 */
	public function payment_fields() {
		if ( $this->description ) {
			echo '<p>' . wp_kses_post( $this->description ) . '</p>';
		}

		// Hidden input for the nonce - button is rendered near Place Order via render_cash_app_button_wrapper().
		?>
		<input type="hidden" name="fkwcsq_cash_app_nonce" id="fkwcsq_cash_app_nonce" value="" />
		<?php
	}

	/**
	 * Render Cash App button wrapper near Place Order button.
	 *
	 * This renders the Cash App button after the Place Order button.
	 * JavaScript will toggle visibility based on selected payment method.
	 *
	 * @return void
	 */
	public function render_cash_app_button_wrapper() {
		if ( ! $this->is_available() ) {
			return;
		}

		?>
		<div id="fkwcsq-cash-app-button-wrapper" style="margin-top: 10px;">
			<div id="fkwcsq-cash-app-container"></div>
			<div id="fkwcsq-cash-app-error" class="fkwcsq-error" style="display: none; color: #dc3545; margin-top: 10px;"></div>
		</div>
		<?php
	}

	/**
	 * Process payment.
	 *
	 * @param int $order_id Order ID.
	 * @return array Result array.
	 */
	public function process_payment( $order_id ) {
		$order = wc_get_order( $order_id );

		if ( ! $order ) {
			wc_add_notice( __( 'Order not found.', 'funnelkit-payment-gateway-square-for-woocommerce' ), 'error' );
			return array( 'result' => 'failure' );
		}

		// Get the nonce from POST.
		// phpcs:ignore WordPress.Security.NonceVerification.Missing, FKWCS.CodeAnalysis.FKWCSSpecific.MissingCapabilityCheck -- WooCommerce handles nonce, guest checkout allowed
		$nonce = isset( $_POST['fkwcsq_cash_app_nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['fkwcsq_cash_app_nonce'] ) ) : '';

		if ( empty( $nonce ) ) {
			wc_add_notice( __( 'Payment token not received. Please try again.', 'funnelkit-payment-gateway-square-for-woocommerce' ), 'error' );
			return array( 'result' => 'failure' );
		}

		try {
			$result = $this->create_payment( $order, $nonce );

			if ( is_wp_error( $result ) ) {
				throw new \Exception( $result->get_error_message() );
			}

			// API returns decoded JSON array.
			if ( ! isset( $result['payment'] ) ) {
				throw new \Exception( __( 'Invalid payment response.', 'funnelkit-payment-gateway-square-for-woocommerce' ) );
			}

			$payment = $result['payment'];

			// Verify it's a wallet payment (Cash App).
			$source_type = $payment['source_type'] ?? '';
			if ( 'WALLET' !== $source_type ) {
				throw new \Exception( __( 'Invalid payment source type.', 'funnelkit-payment-gateway-square-for-woocommerce' ) );
			}

			$payment_id     = $payment['id'] ?? '';
			$payment_status = $payment['status'] ?? '';

			// Store payment info (consistent with other gateways).
			$order->update_meta_data( '_square_payment_id', $payment_id );
			$order->update_meta_data( '_square_payment_status', $payment_status );
			$order->update_meta_data( '_square_payment_source', 'CASH_APP' );

			if ( 'COMPLETED' === $payment_status ) {
				$order->payment_complete( $payment_id );
			} else {
				/* translators: %s: Payment ID */
				$order->set_status( 'on-hold', sprintf( __( 'Cash App payment authorized. Payment ID: %s', 'funnelkit-payment-gateway-square-for-woocommerce' ), $payment_id ) );

			}

			$order->save();

			WC()->cart->empty_cart();

			return array(
				'result'   => 'success',
				'redirect' => $this->get_return_url( $order ),
			);

		} catch ( \Throwable $e ) {
			Logger::error( 'Cash App payment error: ' . $e->getMessage() );
			wc_add_notice( $e->getMessage(), 'error' );
			return array( 'result' => 'failure' );
		}
	}

	/**
	 * Create payment via Square API.
	 *
	 * @param WC_Order $order Order object.
	 * @param string   $nonce Payment nonce.
	 * @return \Square\Models\CreatePaymentResponse|\WP_Error
	 */
	protected function create_payment( $order, $nonce ) {
		$amount   = $this->format_amount( $order->get_total() );
		$currency = $order->get_currency();

		$payment_data = array(
			'source_id'           => $nonce,
			'idempotency_key'     => fkwcsq_idempotency_key( 'fkwcsq_cashapp_' ),
			'amount_money'        => array(
				'amount'   => $amount,
				'currency' => $currency,
			),
			'reference_id'        => $this->api->get_reference_id( $order->get_order_number() ),
			'autocomplete'        => 'automatic' === $this->capture_method,
			'location_id'         => $this->api->get_location_id(),
			'buyer_email_address' => $order->get_billing_email(),
			'billing_address'     => $this->get_billing_address( $order ),
			'shipping_address'    => $this->get_shipping_address( $order ),
			'note'                => $this->get_order_note( $order ),
		);

		return $this->api->create_payment( $payment_data );
	}

	/**
	 * Format amount for Square API (convert to cents).
	 *
	 * @param float $amount Amount in dollars.
	 * @return int Amount in cents.
	 */
	protected function format_amount( $amount ) {
		return (int) round( $amount * 100 );
	}

	/**
	 * Get billing address array.
	 *
	 * @param WC_Order $order Order object.
	 * @return array Billing address.
	 */
	protected function get_billing_address( $order ) {
		return array(
			'address_line_1'                  => $order->get_billing_address_1(),
			'address_line_2'                  => $order->get_billing_address_2(),
			'locality'                        => $order->get_billing_city(),
			'administrative_district_level_1' => $order->get_billing_state(),
			'postal_code'                     => $order->get_billing_postcode(),
			'country'                         => $order->get_billing_country(),
			'first_name'                      => $order->get_billing_first_name(),
			'last_name'                       => $order->get_billing_last_name(),
		);
	}

	/**
	 * Get shipping address array.
	 *
	 * @param WC_Order $order Order object.
	 * @return array Shipping address.
	 */
	protected function get_shipping_address( $order ) {
		if ( ! $order->has_shipping_address() ) {
			return $this->get_billing_address( $order );
		}

		return array(
			'address_line_1'                  => $order->get_shipping_address_1(),
			'address_line_2'                  => $order->get_shipping_address_2(),
			'locality'                        => $order->get_shipping_city(),
			'administrative_district_level_1' => $order->get_shipping_state(),
			'postal_code'                     => $order->get_shipping_postcode(),
			'country'                         => $order->get_shipping_country(),
			'first_name'                      => $order->get_shipping_first_name(),
			'last_name'                       => $order->get_shipping_last_name(),
		);
	}

	/**
	 * Get order note for Square.
	 *
	 * @param WC_Order $order Order object.
	 * @return string Order note.
	 */
	protected function get_order_note( $order ) {
		/* translators: %s: Order number */
		return sprintf( __( 'WooCommerce Order #%s', 'funnelkit-payment-gateway-square-for-woocommerce' ), $order->get_order_number() );
	}

	/**
	 * Process refund.
	 *
	 * @param int    $order_id Order ID.
	 * @param float  $amount   Refund amount.
	 * @param string $reason   Refund reason.
	 * @return bool|\WP_Error
	 */
	public function process_refund( $order_id, $amount = null, $reason = '' ) {
		$order = wc_get_order( $order_id );

		if ( ! $order ) {
			return new \WP_Error( 'invalid_order', __( 'Invalid order.', 'funnelkit-payment-gateway-square-for-woocommerce' ) );
		}

		$payment_id = $order->get_meta( '_square_payment_id' );

		if ( empty( $payment_id ) ) {
			return new \WP_Error( 'no_payment_id', __( 'No Square payment ID found for this order.', 'funnelkit-payment-gateway-square-for-woocommerce' ) );
		}

		$response = $this->api->process_refund( $payment_id, $amount );

		if ( is_wp_error( $response ) ) {
			Logger::error( 'Cash App refund error: ' . $response->get_error_message() );
			return $response;
		}

		$refund_id = isset( $response['refund_id'] ) ? $response['refund_id'] : 'N/A';

		$order->add_order_note(
			sprintf(
				/* translators: 1: refund amount, 2: Square refund ID */
				__( 'Refunded %1$s via Square Cash App. Refund ID: %2$s', 'funnelkit-payment-gateway-square-for-woocommerce' ),
				wc_price( $amount ),
				$refund_id
			)
		);

		return true;
	}

	/**
	 * Get gateway icon.
	 *
	 * @return string Icon HTML.
	 */
	public function get_icon() {
		$icon_url = FKWCSQ_PLUGIN_URL . 'assets/images/cash-app.svg';
		$icon     = '<img src="' . esc_url( $icon_url ) . '" alt="' . esc_attr( $this->get_title() ) . '" style="max-height: 24px;" />';
		return apply_filters( 'woocommerce_gateway_icon', $icon, $this->id );
	}
}
