<?php
/**
 * FunnelKit Square Integration Middleware Connection Handler
 *
 * @package FunnelKit_Square
 * @subpackage Connection
 * @since 1.0.0
 */

namespace FKWCSQ\Includes\Modules\Connection;

use FKWCSQ\Includes\API;
use FKWCSQ\Includes\Traits\Instance;
use Exception;
use WP_Error;

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

// Import WordPress functions
use function admin_url;
use function wp_remote_post;
use function wp_safe_redirect;
use function add_settings_error;
use function update_option;
use function get_option;
use function delete_option;

/**
 * FKWCSQ_Middleware_Connection Class
 * Handles connection through middleware server
 */
class MiddleWare {
	use Instance;

	/**
	 * Middleware API URL
	 *
	 * @var string
	 */
	private $middleware_url = 'https://secure-auth.funnelkit.com/square/index.php';
	/**
	 * The current connection mode ('sandbox' or 'production').
	 *
	 * @var string
	 */
	public $connect_mode = null;
	/**
	 * Constructor
	 */
	private function __construct() {
	}

	/**
	 * Get middleware connection URL
	 *
	 * @param bool $deauthorize Whether to deauthorize existing connection before reconnecting
	 * @return string
	 */
	public function get_connection_url( $deauthorize = false ) {
		$redirect_uri = admin_url( 'admin.php?page=wc-settings&tab=fkwcsq_square_api&fkwcsq-callback=1' );

		$params = array(
			'site_url'     => trailingslashit( get_home_url( null, '', 'rest' ) ),
			'redirect_uri' => $redirect_uri,
			'sandbox'      => '0',
		);

		// If deauthorizing, include the current access token and deauthorize flag
		if ( $deauthorize ) {
			$tokens = \FKWCSQ\Square::get_tokens();
			if ( ! empty( $tokens['access_token'] ) ) {
				$params['deauthorize']  = '1';
				$params['access_token'] = $tokens['access_token'];
			}
		}

		$get_unique_id = get_option( 'fkwcsq_wp_square', '' );
		if ( ! empty( $get_unique_id ) ) {
			$params['wp_square'] = $get_unique_id;
		}

		return $this->middleware_url . '/connect?' . http_build_query( $params );
	}

	/**
	 * Handle middleware callback
	 */
	public function handle_middleware_callback() {
		// Require WooCommerce management capability for security
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			return;
		}

		if ( isset( $_GET['page'] ) && 'wc-settings' === $_GET['page'] ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
			// Handle tokens from middleware
			if ( isset( $_GET['fkwcsq_tokens'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
				$this->process_middleware_tokens();
			}
		}
	}

	/**
	 * Process tokens from middleware
	 *
	 * @return void
	 * @throws \Exception When token processing fails.
	 * @since 1.0.0
	 */
	private function process_middleware_tokens() {
		try {

			// Decode and validate tokens
			$tokens_data = isset( $_GET['fkwcsq_tokens'] ) ? sanitize_text_field( wp_unslash( $_GET['fkwcsq_tokens'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$tokens      = json_decode( base64_decode( $tokens_data ), true );

			if ( ! $tokens || ! isset( $tokens['access_token'] ) ) {
				throw new Exception( __( 'Invalid tokens received from middleware.', 'funnelkit-payment-gateway-square-for-woocommerce' ) );
			}

			// Process tokens based on environment mode
			$this->save_tokens( $tokens );
			$this->initialize_api_and_process_locations( $tokens );
			$this->save_site_id();
			$this->redirect_to_success_page();

		} catch ( Exception $e ) {
			$this->redirect_to_error_page( $e->getMessage() );
		}
	}

	private function set_connect_mode() {
		$this->connect_mode = isset( $_GET['sandbox'] ) && $_GET['sandbox'] === '1' ? 'sandbox' : 'production'; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
	}

	/**
	 * Save tokens based on sandbox mode
	 */
	private function save_tokens( array $tokens ) {
		$token_data = array(
			'access_token'  => $tokens['access_token'],
			'refresh_token' => $tokens['refresh_token'],
			'expires_at'    => $tokens['expires_at'],
			'merchant_id'   => $tokens['merchant_id'],
		);

		$this->set_connect_mode();
		if ( $this->connect_mode === 'sandbox' ) {
			$token_data['application_id'] = FKWCSQ_SANDBOX_APPLICATION_ID;
		}
		$option_name = $this->connect_mode === 'sandbox' ? 'fkwcsq_sandbox_tokens' : 'fkwcsq_tokens';
		update_option( $option_name, $token_data );
	}

	/**
	 * Initialize API client and handle location processing
	 */
	private function initialize_api_and_process_locations( array $tokens ) {
		$this->update_production_settings( $tokens, array() );
		$api = API::get_instance();

		$api->maybe_init_client();

		$locations = $api->get_locations();

		// Check if locations is a WP_Error (API call failed)
		if ( is_wp_error( $locations ) ) {
			$locations = array();
		}

		$this->update_production_settings( $tokens, $locations );
	}

	/**
	 * Update settings for production mode (non-sandbox)
	 */
	private function update_production_settings( array $tokens, array $locations ) {

		if ( ! \FKWCSQ\Square::is_sandbox_mode() ) {
			$settings                      = get_option( 'fkwcsq_settings', array() );
			$settings['connection_status'] = 'connected';
			$settings['environment']       = 'production';
			$settings['merchant_id']       = $tokens['merchant_id'];

			if ( ! empty( $locations ) ) {
				$settings['location_id'] = $locations[0]['id'];
			}

			update_option( 'fkwcsq_settings', $settings );

			// Save connection timestamp for version tracking
			update_option( 'fkwcsq_connection_timestamp', time(), false );

			// Trigger action for gateway management
			do_action( 'fkwcsq_after_connection' );
		}
	}

	/**
	 * Save site ID from GET parameter
	 */
	private function save_site_id() {
		$site_id = isset( $_GET['site_id'] ) ? sanitize_text_field( wp_unslash( $_GET['site_id'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended

		if ( ! empty( $site_id ) ) {
			update_option( 'fkwcsq_site_id', $site_id, false );
		}
	}

	/**
	 * Redirect to success page
	 */
	private function redirect_to_success_page() {
		wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=fkwcsq_square_api&connection=success' ) );
		exit;
	}

	/**
	 * Redirect to error page with message
	 */
	private function redirect_to_error_page( string $message ) {
		wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=fkwcsq_square_api&connection=error&message=' . rawurlencode( $message ) ) );
		exit;
	}

	/**
	 * Handle disconnect action
	 */
	public function handle_disconnect_action() {
		// Require WooCommerce management capability for security
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			return;
		}

		$is_valid_page     = isset( $_GET['page'] ) && $_GET['page'] === 'wc-settings';
		$is_disconnect_req = isset( $_GET['fkwcsq_disconnect'] ) && $_GET['fkwcsq_disconnect'] === '1';
		$is_nonce_valid    = isset( $_GET['_wpnonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'fkwcsq_disconnect' );

		if ( $is_valid_page && $is_disconnect_req && $is_nonce_valid ) {
			$this->disconnect();
		} elseif ( $is_valid_page && $is_disconnect_req && ! $is_nonce_valid ) {
			add_settings_error( 'fkwcsq_settings', 'fkwcsq_disconnect_error', esc_html__( 'Security check failed.', 'funnelkit-payment-gateway-square-for-woocommerce' ), 'error' );
		}
	}

	/**
	 * Check if connected through middleware
	 *
	 * @return bool
	 */
	public function is_connected() {
		$settings   = get_option( 'fkwcsq_settings', array() );
		$is_sandbox = \FKWCSQ\Square::is_sandbox_mode();

		if ( $is_sandbox ) {
			$sandbox_tokens = get_option( 'fkwcsq_sandbox_tokens', array() );

			return isset( $settings['sandbox_connection_status'] ) && $settings['sandbox_connection_status'] === 'connected' && ! empty( $sandbox_tokens['access_token'] );
		}

		$tokens = get_option( 'fkwcsq_tokens', array() );

		return isset( $settings['connection_status'] ) && $settings['connection_status'] === 'connected' && ! empty( $tokens['access_token'] );
	}

	/**
	 * Disconnect from Square through middleware
	 */
	public function disconnect() {
		try {
			$settings = get_option( 'fkwcsq_settings', array() );

			delete_option( 'fkwcsq_sandbox_tokens' );
			delete_option( 'fkwcsq_sandbox_locations' );
			unset( $settings['sandbox_location_id'] );
			unset( $settings['sandbox_connection_status'] );

			// Delete production tokens and settings
			delete_option( 'fkwcsq_tokens' );
			delete_option( 'fkwcsq_locations' );
			delete_option( 'fkwcsq_site_id' );
			unset( $settings['location_id'] );
			unset( $settings['connection_status'] );
			unset( $settings['merchant_id'] );

			// Clear any transients
			global $wpdb;
			$wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_fkwcsq_%'" ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery
			$wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_timeout_fkwcsq_%'" ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery

			update_option( 'fkwcsq_settings', $settings );

			wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=fkwcsq_square_api&disconnect=success' ) );
			exit;
		} catch ( Exception $e ) {
			wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=fkwcsq_square_api&disconnect=error&message=' . rawurlencode( $e->getMessage() ) ) );
			exit;
		}
	}

	/**
	 * Refresh access token through middleware
	 *
	 * @return bool
	 */
	public function refresh_access_token_middleware() {
		$tokens = get_option( 'fkwcsq_tokens' );
		if ( ! $tokens || ! isset( $tokens['refresh_token'] ) ) {
			return false;
		}

		try {
			$response = wp_remote_post(
				$this->middleware_url . '/refresh-token',
				array(
					'timeout' => 45,
					'body'    => array(
						'site_url'      => trailingslashit( get_home_url( null, '', 'rest' ) ),
						'refresh_token' => $tokens['refresh_token'],
						'merchant_id'   => $tokens['merchant_id'] ?? '',
						'wp_square'     => '',
					),
				)
			);

			if ( is_wp_error( $response ) ) {
				return false;
			}

			$body   = wp_remote_retrieve_body( $response );
			$result = json_decode( $body, true );

			if ( ! $result || ! isset( $result['access_token'] ) ) {
				return false;
			}

			// Update tokens with new values
			update_option(
				'fkwcsq_tokens',
				array(
					'access_token'  => $result['access_token'],
					'refresh_token' => $result['refresh_token'] ?? $tokens['refresh_token'],
					'expires_at'    => time() + ( $result['expires_in'] ?? 86400 ),
					'merchant_id'   => $tokens['merchant_id'] ?? '',
					'last_refresh'  => current_time( 'mysql' ),
				)
			);

			return true;

		} catch ( Exception $e ) {
			return false;
		}
	}
}
