<?php
/**
 * Payment Token Editor for FunnelKit Square Payment Gateway
 *
 * Handles token editing functionality in admin user profile
 *
 * @package FunnelKit_Square
 * @subpackage Admin
 */

namespace FKWCSQ\Admin;

use FKWCSQ\Includes\Traits\Instance;
use WC_Payment_Tokens;
use WC_Payment_Token_CC;

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

/**
 * Payment Token Editor Class
 */
class Payment_Token_Editor {
	use Instance;

	/**
	 * Gateway instance
	 *
	 * @var \WC_Payment_Gateway
	 */
	protected $gateway;

	/**
	 * Constructor
	 *
	 * @param \WC_Payment_Gateway $gateway Gateway instance
	 */
	public function __construct( $gateway ) {
		$this->gateway = $gateway;
		$this->init_hooks();
	}

	/**
	 * Initialize hooks
	 */
	private function init_hooks() {
		// Enqueue scripts and styles
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts_styles' ) );

		// Display tokens
		add_action( 'fkwcsq_square_token_editor_tokens', array( $this, 'display_tokens' ) );

		// AJAX handlers
		add_action( 'wp_ajax_fkwcsq_square_admin_get_blank_payment_token', array( $this, 'ajax_get_blank_token' ) );
		add_action( 'wp_ajax_fkwcsq_square_admin_remove_payment_token', array( $this, 'ajax_remove_token' ) );
		add_action( 'wp_ajax_fkwcsq_square_admin_refresh_payment_tokens', array( $this, 'ajax_refresh_tokens' ) );
		add_action( 'wp_ajax_fkwcsq_square_admin_save_payment_tokens', array( $this, 'ajax_save_tokens' ) );
	}

	/**
	 * Enqueue scripts and styles
	 */
	public function enqueue_scripts_styles() {
		if ( ! current_user_can( 'edit_users' ) ) {
			return;
		}

		// Enqueue CSS
		wp_enqueue_style(
			'fkwcsq-token-editor',
			FKWCSQ_PLUGIN_URL . 'assets/css/token-editor' . ( defined( 'FKWCSQ_IS_DEV' ) && FKWCSQ_IS_DEV ? '' : '.min' ) . '.css',
			array(),
			FKWCSQ_VERSION
		);

		// Enqueue JavaScript
		wp_enqueue_script(
			'fkwcsq-token-editor',
			FKWCSQ_PLUGIN_URL . 'assets/js/token-editor' . ( defined( 'FKWCSQ_IS_DEV' ) && FKWCSQ_IS_DEV ? '' : '.min' ) . '.js',
			array( 'jquery' ),
			FKWCSQ_VERSION,
			true
		);

		// Localize script
		wp_localize_script(
			'fkwcsq-token-editor',
			'fkwcsq_token_editor',
			array(
				'ajax_url' => admin_url( 'admin-ajax.php' ),
				'actions'  => array(
					'remove_token' => array(
						'ays'   => esc_html__( 'Are you sure you want to remove this token?', 'funnelkit-payment-gateway-square-for-woocommerce' ),
						'nonce' => wp_create_nonce( 'fkwcsq_admin_remove_payment_token' ),
					),
					'add_token'    => array(
						'nonce' => wp_create_nonce( 'fkwcsq_admin_get_blank_payment_token' ),
					),
					'refresh'      => array(
						'nonce' => wp_create_nonce( 'fkwcsq_admin_refresh_payment_tokens' ),
					),
					'save'         => array(
						'nonce' => wp_create_nonce( 'fkwcsq_admin_save_payment_tokens' ),
						'error' => esc_html__( 'Invalid token data', 'funnelkit-payment-gateway-square-for-woocommerce' ),
					),
				),
				'i18n'     => array(
					'general_error' => esc_html__( 'An error occurred. Please try again.', 'funnelkit-payment-gateway-square-for-woocommerce' ),
				),
			)
		);
	}

	/**
	 * Display token editor
	 *
	 * @param int $user_id User ID
	 */
	public function display( $user_id ) {
		$id      = $this->gateway->get_id();
		$title   = $this->get_title();
		$columns = $this->get_columns();
		$actions = $this->get_actions();

		include FKWCSQ_PLUGIN_DIR . 'includes/admin/views/html-user-payment-token-editor.php';
	}

	/**
	 * Display tokens
	 *
	 * @param int $user_id User ID
	 */
	public function display_tokens( $user_id ) {
		$tokens = $this->get_tokens( $user_id );

		$fields     = $this->get_fields();
		$input_name = $this->get_input_name();
		$actions    = $this->get_token_actions();
		$type       = $this->get_payment_type();

		$index = 0;

		foreach ( $tokens as $token ) {
			$user_id = $user_id; // Make sure user_id is available in template
			include FKWCSQ_PLUGIN_DIR . 'includes/admin/views/html-user-payment-token-editor-token.php';
			++$index;
		}
	}

	/**
	 * Save token editor
	 *
	 * @param int $user_id User ID
	 */
	public function save( $user_id ) {
		$token_key = $this->get_input_name();

		// Verify nonce for security
		if ( ! isset( $_POST['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), 'update-user_' . $user_id ) ) {
			return;
		}

		// Use wp_unslash only — sanitize_text_field() strips '<', '>' and encodes special chars,
		// which corrupts JSON payloads. Individual array values are sanitised below.
		$tokens_raw = isset( $_POST[ $token_key ] ) ? wp_unslash( $_POST[ $token_key ] ) : ''; //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- JSON is decoded and each value sanitised individually below

		// Handle JSON data from AJAX
		if ( is_string( $tokens_raw ) && ! empty( $tokens_raw ) ) {
			$tokens = json_decode( $tokens_raw, true );
		} elseif ( is_array( $tokens_raw ) ) {
			$tokens = $tokens_raw;
		} else {
			$tokens = array();
		}

		if ( ! is_array( $tokens ) ) {
			return;
		}

		$sanitized_tokens = array();

		foreach ( $tokens as $token ) {
			if ( ! is_array( $token ) ) {
				continue;
			}

			$sanitized_tokens[] = array_map( 'sanitize_text_field', $token );
		}

		$gateway_id      = method_exists( $this->gateway, 'get_id' ) ? $this->gateway->get_id() : 'fkwcsq_square';
		$customer_tokens = WC_Payment_Tokens::get_customer_tokens( $user_id, $gateway_id );

		foreach ( $sanitized_tokens as $data ) {
			$token_id = $data['id'];

			unset( $data['id'] );

			if ( ! $token_id ) {
				continue;
			}

			if ( 'credit_card' === $data['type'] ) {
				$data = $this->prepare_expiry_date( $data );
			}

			// Set the default method
			$default_token   = isset( $_POST[ $this->get_input_name() . '_default' ] ) //phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce verified at top of save()
				? sanitize_text_field( wp_unslash( $_POST[ $this->get_input_name() . '_default' ] ) )
				: '';
			$data['default'] = ( $default_token === $token_id );

			$data = $this->validate_token_data( $token_id, $data );

			if ( $data ) {
				$token_found           = false;
				$matched_payment_token = null;
				$token_obj             = false;

				foreach ( $customer_tokens as $payment_token => $customer_token ) {
					if ( $customer_token->get_token() === $token_id ) {
						$token_found           = true;
						$matched_payment_token = $payment_token;
						break;
					}
				}

				if ( $token_found ) {
					$token_obj = WC_Payment_Tokens::get( $matched_payment_token );
				} else {
					$token_obj = new WC_Payment_Token_CC();
				}

				$token_obj->set_token( $token_id );
				$token_obj->set_gateway_id( $gateway_id );

				if ( method_exists( $token_obj, 'set_last4' ) ) {
					$token_obj->set_last4( $data['last_four'] );
				}
				if ( method_exists( $token_obj, 'set_expiry_year' ) ) {
					$token_obj->set_expiry_year( $data['exp_year'] );
				}
				if ( method_exists( $token_obj, 'set_expiry_month' ) ) {
					$token_obj->set_expiry_month( $data['exp_month'] );
				}
				if ( method_exists( $token_obj, 'set_card_type' ) ) {
					$token_obj->set_card_type( $data['card_type'] );
				}
				if ( method_exists( $token_obj, 'set_default' ) ) {
					$token_obj->set_default( $data['default'] );
				}
				if ( method_exists( $token_obj, 'set_user_id' ) ) {
					$token_obj->set_user_id( $user_id );
				}
				$token_obj->save();
			}
		}
	}

	/**
	 * AJAX: Get blank token
	 */
	public function ajax_get_blank_token() {
		check_ajax_referer( 'fkwcsq_admin_get_blank_payment_token', 'security' );

		if ( ! current_user_can( 'edit_users' ) ) {
			wp_send_json_error();
		}

		$index = isset( $_POST['index'] ) ? intval( $_POST['index'] ) : 0;

		if ( $index ) {
			$fields = $this->get_fields();

			$token            = array_fill_keys( array_keys( $fields ), '' );
			$token['id']      = '';
			$token['expiry']  = '';
			$token['default'] = false;

			ob_start();

			include FKWCSQ_PLUGIN_DIR . 'includes/admin/views/html-user-payment-token-editor-token.php';

			$html = ob_get_clean();

			wp_send_json_success( $html );
		} else {
			wp_send_json_error();
		}
	}

	/**
	 * AJAX: Remove token
	 */
	public function ajax_remove_token() {
		try {
			if ( ! current_user_can( 'edit_users' ) || ! check_ajax_referer( 'fkwcsq_admin_remove_payment_token', 'security', false ) ) {
				throw new \Exception( 'Invalid permissions' );
			}

			$user_id          = isset( $_POST['user_id'] ) ? intval( $_POST['user_id'] ) : 0;
			$token_id         = isset( $_POST['token_id'] ) ? sanitize_text_field( wp_unslash( $_POST['token_id'] ) ) : '';
			$payment_token_id = isset( $_POST['payment_token_id'] ) ? intval( $_POST['payment_token_id'] ) : 0;

			if ( ! $user_id ) {
				throw new \Exception( 'User ID is missing' );
			}

			if ( ! $token_id ) {
				throw new \Exception( 'Token ID is missing' );
			}

			$token = WC_Payment_Tokens::get( $payment_token_id );

			if ( ! $token || $token->get_user_id() !== $user_id ) {
				throw new \Exception( 'Token does not belong to specified user.' );
			}

			$is_deleted = $token->delete();

			if ( $is_deleted ) {
				wp_send_json_success();
			} else {
				throw new \Exception( 'Could not remove token' );
			}
		} catch ( \Exception $e ) {
			wp_send_json_error( $e->getMessage() );
		}
	}

	/**
	 * AJAX: Refresh tokens
	 */
	public function ajax_refresh_tokens() {
		try {
			if ( ! current_user_can( 'edit_users' ) || ! check_ajax_referer( 'fkwcsq_admin_refresh_payment_tokens', 'security', false ) ) {
				throw new \Exception( 'Invalid permissions' );
			}

			$user_id = isset( $_POST['user_id'] ) ? intval( $_POST['user_id'] ) : 0;

			if ( ! $user_id ) {
				throw new \Exception( 'User ID is missing' );
			}

			ob_start();

			$this->display_tokens( $user_id );

			$html = ob_get_clean();

			wp_send_json_success( trim( $html ) );
		} catch ( \Exception $e ) {
			wp_send_json_error( $e->getMessage() );
		}
	}

	/**
	 * AJAX: Save tokens
	 */
	public function ajax_save_tokens() {
		try {
			if ( ! current_user_can( 'edit_users' ) || ! check_ajax_referer( 'fkwcsq_admin_save_payment_tokens', 'security', false ) ) {
				throw new \Exception( 'Invalid permissions' );
			}

			$user_id = isset( $_POST['user_id'] ) ? intval( $_POST['user_id'] ) : 0;

			if ( ! $user_id ) {
				throw new \Exception( 'User ID is missing' );
			}

			// Save the tokens
			$this->save( $user_id );

			wp_send_json_success( 'Tokens saved successfully' );
		} catch ( \Exception $e ) {
			wp_send_json_error( $e->getMessage() );
		}
	}

	/**
	 * Get tokens for user
	 *
	 * @param int $user_id User ID
	 * @return array
	 */
	protected function get_tokens( $user_id ) {
		$gateway_id    = method_exists( $this->gateway, 'get_id' ) ? $this->gateway->get_id() : 'fkwcsq_square';
		$stored_tokens = WC_Payment_Tokens::get_customer_tokens( $user_id, $gateway_id );

		// If no tokens found with the gateway ID, try with alternative IDs
		if ( empty( $stored_tokens ) ) {
			$alternative_ids = array( 'square', 'fkwcsq_square', 'square_credit_card' );
			foreach ( $alternative_ids as $alt_id ) {
				if ( $alt_id !== $gateway_id ) {
					$alt_tokens = WC_Payment_Tokens::get_customer_tokens( $user_id, $alt_id );
					if ( ! empty( $alt_tokens ) ) {
						$stored_tokens = $alt_tokens;
						break;
					}
				}
			}
		}

		return $stored_tokens;
	}

	/**
	 * Get editor title
	 *
	 * @return string
	 */
	protected function get_title() {
		$title = method_exists( $this->gateway, 'get_title' ) ? $this->gateway->get_title() : 'Square Credit Card';

		return apply_filters( 'fkwcsq_token_editor_title', $title, $this );
	}

	/**
	 * Get editor columns
	 *
	 * @return array
	 */
	protected function get_columns() {
		$fields  = $this->get_fields();
		$columns = array();

		foreach ( $fields as $field_id => $field ) {
			$columns[ $field_id ] = isset( $field['label'] ) ? $field['label'] : '';
		}

		$columns['default'] = esc_html__( 'Default', 'funnelkit-payment-gateway-square-for-woocommerce' );
		$columns['actions'] = '';

		return apply_filters( 'fkwcsq_token_editor_columns', $columns, $this );
	}

	/**
	 * Get editor fields
	 *
	 * @return array
	 */
	protected function get_fields() {
		$fields = array(
			'id'        => array(
				'label'    => esc_html__( 'Token ID', 'funnelkit-payment-gateway-square-for-woocommerce' ),
				'editable' => false,
				'required' => true,
			),
			'card_type' => array(
				'label'   => esc_html__( 'Card Type', 'funnelkit-payment-gateway-square-for-woocommerce' ),
				'type'    => 'select',
				'options' => $this->get_card_type_options(),
			),
			'last_four' => array(
				'label'      => esc_html__( 'Last Four', 'funnelkit-payment-gateway-square-for-woocommerce' ),
				'attributes' => array(
					'pattern'   => '[0-9]{4}',
					'maxlength' => 4,
				),
			),
			'expiry'    => array(
				'label'      => esc_html__( 'Expiration (MM/YYYY)', 'funnelkit-payment-gateway-square-for-woocommerce' ),
				'attributes' => array(
					'placeholder' => 'MM/YYYY',
					'pattern'     => '^(0[1-9]|1[0-2])\/?([0-9]{4})$',
					'maxlength'   => 7,
				),
			),
		);

		// Parse each field against the defaults
		foreach ( $fields as $field_id => $field ) {
			$fields[ $field_id ] = wp_parse_args(
				$field,
				array(
					'label'      => '',
					'type'       => 'text',
					'attributes' => array(),
					'editable'   => true,
					'required'   => false,
				)
			);
		}

		return apply_filters( 'fkwcsq_token_editor_fields', $fields, $this );
	}

	/**
	 * Get card type options
	 *
	 * @return array
	 */
	protected function get_card_type_options() {
		$card_types = array(
			'visa'       => __( 'Visa', 'funnelkit-payment-gateway-square-for-woocommerce' ),
			'mastercard' => __( 'Mastercard', 'funnelkit-payment-gateway-square-for-woocommerce' ),
			'amex'       => __( 'American Express', 'funnelkit-payment-gateway-square-for-woocommerce' ),
			'discover'   => __( 'Discover', 'funnelkit-payment-gateway-square-for-woocommerce' ),
			'diners'     => __( 'Diners Club', 'funnelkit-payment-gateway-square-for-woocommerce' ),
			'jcb'        => __( 'JCB', 'funnelkit-payment-gateway-square-for-woocommerce' ),
			'unionpay'   => __( 'UnionPay', 'funnelkit-payment-gateway-square-for-woocommerce' ),
		);

		return $card_types;
	}

	/**
	 * Get input name
	 *
	 * @return string
	 */
	protected function get_input_name() {
		return 'fkwcsq_square_tokens';
	}

	/**
	 * Get actions
	 *
	 * @return array
	 */
	protected function get_actions() {
		$actions = array(
			'refresh' => esc_html__( 'Refresh', 'funnelkit-payment-gateway-square-for-woocommerce' ),
			'save'    => esc_html__( 'Save', 'funnelkit-payment-gateway-square-for-woocommerce' ),
		);

		return apply_filters( 'fkwcsq_token_editor_actions', $actions, $this );
	}

	/**
	 * Get token actions
	 *
	 * @return array
	 */
	protected function get_token_actions() {
		$actions = array(
			'remove' => esc_html__( 'Remove', 'funnelkit-payment-gateway-square-for-woocommerce' ),
		);

		return apply_filters( 'fkwcsq_token_editor_token_actions', $actions, $this );
	}

	/**
	 * Get payment type
	 *
	 * @return string
	 */
	protected function get_payment_type() {
		return 'credit_card';
	}

	/**
	 * Prepare expiry date
	 *
	 * @param array $data Token data
	 * @return array
	 */
	protected function prepare_expiry_date( $data ) {
		if ( ! $data['expiry'] || ! strpos( $data['expiry'], '/' ) || 7 !== strlen( $data['expiry'] ) ) {
			unset( $data['expiry'] );
			return $data;
		}

		list( $data['exp_month'], $data['exp_year'] ) = explode( '/', $data['expiry'] );

		unset( $data['expiry'] );

		return $data;
	}

	/**
	 * Validate token data
	 *
	 * @param string $token_id Token ID
	 * @param array  $data Token data
	 * @return array|bool
	 */
	protected function validate_token_data( $token_id, $data ) {
		return apply_filters( 'fkwcsq_token_editor_validate_token_data', $data, $token_id, $this );
	}
}
