<?php
/**
 * Plugin Name: FunnelKit Payment Gateway for Square WooCommerce
 * Plugin URI: https://funnelkit.com/
 * Description: Connect your WooCommerce store with inventory, products and orders with ease. Process payments with Square.
 * Author: FunnelKit
 * Author URI: https://funnelkit.com
 * License: GPLv2 or later
 * Version: 1.4.5
 * Text Domain: funnelkit-payment-gateway-square-for-woocommerce
 * Domain Path: /languages
 * Requires at least: 5.0
 * Requires PHP: 7.4
 * WC requires at least: 4.0
 * WC tested up to: 10.8.0
 * Requires Plugins: woocommerce
 *
 * FunnelKit Payment Gateway for Square WooCommerce is free software.
 * You can redistribute it and/or modify it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * FunnelKit Payment Gateway for Square WooCommerce is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Funnel Builder. If not, see <http://www.gnu.org/licenses/>.
 * /
 *
 * @package FunnelKit_Square
 */

namespace FKWCSQ;

use FKWCSQ\Includes\Logger;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}

// Load global helper functions (no namespace) so they are callable from any namespaced class.
require_once __DIR__ . '/includes/helpers.php';

/**
 * Main plugin class
 */
final class Square {
	/**
	 * Single instance of the plugin
	 *
	 * @var Square
	 */
	protected static $instance = null;

	/**
	 * Plugin file path
	 *
	 * @var string
	 */
	public static $plugin_file = __FILE__;

	/**
	 * Plugin directory path
	 *
	 * @var string
	 */
	public static $plugin_dir;

	/**
	 * Plugin URL
	 *
	 * @var string
	 */
	public static $plugin_url;

	/**
	 * Plugin basename
	 *
	 * @var string
	 */
	public static $plugin_basename;

	/**
	 * Constructor
	 */
	public function __construct() {
		// Initialize static properties
		self::$plugin_dir      = plugin_dir_path( self::$plugin_file );
		self::$plugin_url      = plugin_dir_url( self::$plugin_file );
		self::$plugin_basename = plugin_basename( self::$plugin_file );

		spl_autoload_register( array( __CLASS__, 'autoloader' ) );
		$this->check_dependencies();
		$this->define_constants();
		$this->init_hooks();

		do_action( 'fkwcsq_square_loaded' );
	}

	/**
	 * Check plugin dependencies and compatibility
	 */
	private function check_dependencies() {

		// Declare HPOS compatibility
		add_action(
			'before_woocommerce_init',
			function () {
				if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
					\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true );
				}
			}
		);
	}

	/**
	 * Display WooCommerce missing notice
	 */
	public function woocommerce_missing_notice() {
		?>
		<div class="error">
			<p><?php esc_attr_e( 'FunnelKit Square requires WooCommerce to be installed and active.', 'funnelkit-payment-gateway-square-for-woocommerce' ); ?></p>
		</div>
		<?php
	}

	/**
	 * Autoloader for plugin classes
	 *
	 * @param string $class_name The class name to load
	 */
	private static function autoloader( $class_name ) {
		// Check if the class name starts with our namespace
		if ( strpos( $class_name, 'FKWCSQ\\' ) !== 0 ) {
			return;
		}

		// Convert namespace to file path
		$file = str_replace( 'FKWCSQ\\', '', $class_name );
		$file = str_replace( '\\', '/', $file );
		$file = strtolower( str_replace( '_', '-', $file ) );

		// Build file path
		$file_path = self::$plugin_dir . $file . '.php';

		// Debug log
		if ( defined( 'WP_DEBUG' ) && WP_DEBUG && ! file_exists( $file_path ) ) {
			Logger::debug( sprintf( 'FKWCSQ Autoloader - File not found: %s', $file_path ) );
		}

		// Load the class file if it exists
		if ( file_exists( $file_path ) ) {
			require_once $file_path;
		}
	}

	/**
	 * Define plugin constants
	 */
	private function define_constants() {
		// Define WordPress specific constants
		define( 'FKWCSQ_ABSPATH', dirname( self::$plugin_file ) . '/' );
		define( 'FKWCSQ_PLUGIN_BASENAME', self::$plugin_basename );
		define( 'FKWCSQ_PLUGIN_DIR', self::$plugin_dir );
		define( 'FKWCSQ_PLUGIN_URL', self::$plugin_url );
		( defined( 'FKWCSQ_IS_DEV' ) && true === FKWCSQ_IS_DEV ) ? define( 'FKWCSQ_VERSION', time() ) : define( 'FKWCSQ_VERSION', '1.4.5' );
		define( 'FKWCSQ_TEXT_DOMAIN', 'funnelkit-payment-gateway-square-for-woocommerce' );
		// Define Square API constants
		define( 'FKWCSQ_APPLICATION_ID', 'sq0idp-mJ_dFa6xGghMxrLXgDtNRg' );
		define( 'FKWCSQ_SANDBOX_APPLICATION_ID', 'sandbox-sq0idb-e-cXYrtlo_Fg1SLfnCTzqQ' );
		define( 'FKWCSQ_API_URL', 'https://connect.squareup.com' );
		define( 'FKWCSQ_SANDBOX_API_URL', 'https://connect.squareupsandbox.com' );
		define( 'FKWCSQ_WEB_SDK_URL', 'https://web.squarecdn.com/v1/square.js' );
		define( 'FKWCSQ_SANDBOX_WEB_SDK_URL', 'https://sandbox.web.squarecdn.com/v1/square.js' );
		define( 'FKWCSQ_SANDBOX', true );
	}

	/**
	 * Include required files
	 */
	private function includes() {
		// Manually load admin classes
		require_once plugin_dir_path( __FILE__ ) . 'includes/admin/user-handler.php';
		require_once plugin_dir_path( __FILE__ ) . 'includes/admin/payment-token-editor.php';

		// Initialize sync classes
		Includes\Sync\Category::get_instance();
		Includes\Sync\Customer::get_instance();
		Includes\Sync\Inventory::get_instance();
		Includes\Sync\Order::get_instance();
		Includes\Sync\Product::get_instance();
		// WooCommerce integration
		Includes\Cron::get_instance();
		Includes\Conversions\Controller::get_instance();
		Includes\Funnelkit\Checkout::get_instance();

		// Initialize middleware
		Includes\Modules\Connection\MiddleWare::get_instance();

		// Initialize SmartButtons
		Includes\SmartButtons::get_instance();

		// Initialize Checkout Scripts (centralized script loading)
		Includes\Checkout_Scripts::get_instance();

		// Initialize onboarding
		Admin\Onboard::get_instance();

		Admin\User_Handler::get_instance();

		// Initialize Product Meta Box
		Includes\Integrations\Product_Meta_Box::init();

		// Initialize WooCommerce Settings
		if ( $this->is_woocommerce_active() ) {
			add_action( 'init', array( $this, 'init_wc_settings' ) );
		}
	}

	/**
	 * Initialize WooCommerce Settings
	 */
	public function init_wc_settings() {
		if ( ! class_exists( 'WC_Settings_Page' ) ) {
			return;
		}

		add_filter(
			'woocommerce_get_settings_pages',
			function ( $settings ) {
				$settings[] = require self::$plugin_dir . 'includes/integrations/wc-settings.php';

				return $settings;
			}
		);
	}

	/**
	 * Initialize hooks
	 */
	private function init_hooks() {

		// Initialize WooCommerce specific functionality after WC is loaded
		add_action( 'plugins_loaded', array( $this, 'on_plugins_loaded' ), 10 );

		// Add settings link on plugin page
		add_filter( 'plugin_action_links_' . self::$plugin_basename, array( $this, 'plugin_action_links' ) );

		// Gateway management hooks (same as Stripe)
		add_filter( 'option_woocommerce_gateway_order', array( $this, 'move_square_gateway_to_first' ), 9999 );
		add_filter( 'default_option_woocommerce_gateway_order', array( $this, 'move_square_gateway_to_first' ), 9999 );
		add_action( 'fkwcsq_after_connection', array( $this, 'disable_other_square_gateways' ) );
		add_action( 'fkwcsq_after_connection', array( $this, 'enable_funnelkit_square_gateway' ) );
	}



	/**
	 * Register activation and deactivation hooks
	 */
	public function register_activation_hooks() {
		register_activation_hook( self::$plugin_file, array( \FKWCSQ\Includes\Install::get_instance(), 'install' ) );
		register_deactivation_hook( self::$plugin_file, array( \FKWCSQ\Includes\Install::get_instance(), 'deactivate' ) );
	}

	/**
	 * Main plugin instance
	 *
	 * @return Square
	 */
	public static function instance() {
		if ( is_null( self::$instance ) ) {
			self::$instance = new self();
		}

		return self::$instance;
	}

	/**
	 * On plugins loaded
	 */
	public function on_plugins_loaded() {
		// Initialize components when WooCommerce is loaded
		if ( ! $this->is_woocommerce_active() ) {
			// Initialize WooCommerce specific functionality
			return false;

		}
		// autoload plugin and vendor files
		$autoload_file = plugin_dir_path( __FILE__ ) . 'vendor/autoload.php';
		if ( ! file_exists( $autoload_file ) ) {
			add_action(
				'admin_notices',
				function () {
					echo '<div class="notice notice-error"><p><strong>FunnelKit Square:</strong> The plugin <code>vendor/</code> directory is missing. Please reinstall the plugin.</p></div>';
				}
			);
			return false;
		}
		$loader = require_once $autoload_file;

		if ( ! class_exists( 'Square\SquareClient' ) ) {
			add_action(
				'admin_notices',
				function () {
					echo '<div class="notice notice-error"><p><strong>FunnelKit Square:</strong> The Square PHP SDK is missing from <code>vendor/</code>. Please reinstall the plugin.</p></div>';
				}
			);
			return false;
		}

		// register plugin namespace with autoloader
		$loader->addPsr4( 'FKWCSQ\\', __DIR__ . '/includes' );

		Includes\Integrations\WooCommerce::init();

		// Initialize WooCommerce Blocks support.
		if ( class_exists( 'Automattic\WooCommerce\Blocks\Package' ) ) {
			Includes\Blocks\Blocks_Support::init();
		}

		$this->includes();
	}

	/**
	 * Check if WooCommerce is active
	 */
	public function is_woocommerce_active() {
		return in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ), true );
	}

	/**
	 * Add action links on plugin page
	 */
	public function plugin_action_links( $links ) {
		$plugin_links = array(
			'<a href="' . admin_url( 'admin.php?page=wc-settings&tab=fkwcsq_square_api' ) . '">' . __( 'Settings', 'funnelkit-payment-gateway-square-for-woocommerce' ) . '</a>',
			'<a href="https://funnelkit.com/docs/square-gateway-for-woocommerce/" target="_blank">' . __( 'Documentation', 'funnelkit-payment-gateway-square-for-woocommerce' ) . '</a>',
		);

		return array_merge( $plugin_links, $links );
	}

	/**
	 * Check if sandbox mode is enabled
	 *
	 * @return bool
	 */
	public static function is_sandbox_mode() {

		// Check if middleware connection mode is set and use it if not null, otherwise fallback to settings.
		if ( class_exists( '\FKWCSQ\Includes\Modules\Connection\MiddleWare' ) ) {
			$middleware = \FKWCSQ\Includes\Modules\Connection\MiddleWare::get_instance();
			if ( property_exists( $middleware, 'connect_mode' ) && null !== $middleware->connect_mode ) {
				return $middleware->connect_mode === 'sandbox';
			}
		}

		$settings    = get_option( 'fkwcsq_settings', array() );
		$environment = isset( $settings['environment'] ) ? $settings['environment'] : 'production';

		// Handle test mode for administrators only
		if ( 'sandbox_admin_only' === $environment ) {
			return is_super_admin();
		}

		// Otherwise use the environment setting
		return $environment === 'sandbox';
	}

	/**
	 * Retrieves the option name for storing tokens based on the current mode.
	 *
	 * Returns a different option name depending on whether the system is in sandbox mode.
	 *
	 * @return string The option name used to store tokens.
	 */
	public static function get_tokens_option_name() {
		return self::is_sandbox_mode() ? 'fkwcsq_sandbox_tokens' : 'fkwcsq_tokens';
	}

	/**
	 * Retrieves the stored tokens from the WordPress options table.
	 *
	 * Uses the appropriate option name based on the current mode (sandbox or live).
	 *
	 * @return array The array of stored tokens. Returns an empty array if no tokens are found.
	 */
	public static function get_tokens() {
		return get_option( self::get_tokens_option_name(), array() );
	}

	/**
	 * Get API URL based on mode
	 *
	 * @return string
	 */
	public static function get_api_url() {
		return self::is_sandbox_mode() ? FKWCSQ_SANDBOX_API_URL : FKWCSQ_API_URL;
	}

	/**
	 * Get Web SDK URL based on mode
	 *
	 * @return string
	 */
	public static function get_web_sdk_url() {
		return self::is_sandbox_mode() ? FKWCSQ_SANDBOX_WEB_SDK_URL : FKWCSQ_WEB_SDK_URL;
	}

	/**
	 * Get application ID based on mode
	 *
	 * @return string
	 */
	public static function get_application_id() {
		$settings = get_option( 'fkwcsq_sandbox_tokens', array() );
		if ( self::is_sandbox_mode() ) {
			return ! empty( $settings['application_id'] ) ? $settings['application_id'] : '';
		} else {
			return FKWCSQ_APPLICATION_ID;
		}
	}

	/**
	 * Check if Square integration is properly configured
	 *
	 * @return bool True if configured, false otherwise
	 */
	public static function is_configured() {
		$tokens         = get_option( 'fkwcsq_tokens', array() );
		$sandbox_tokens = get_option( 'fkwcsq_sandbox_tokens', array() );

		if ( ! empty( $sandbox_tokens['access_token'] ) ) {
			return true;
		}

		if ( ! empty( $tokens['access_token'] ) ) {
			return true;
		}

		return false;
	}

	/**
	 * Check if product should sync with Square
	 *
	 * @param int $product_id Product ID
	 * @return bool
	 */
	public static function should_sync_product_with_square( $product_id ) {
		return get_post_meta( $product_id, '_wc_square_synced', true ) === 'yes';
	}

	/**
	 * Whether the current cart contains a subscription or a subscription renewal.
	 * Covers WooCommerce Subscriptions and Sublium.
	 * Use this instead of repeating the individual guards inline.
	 *
	 * @return bool
	 */
	public static function cart_contains_subscription(): bool {
		// WooCommerce Subscriptions
		if (
			( class_exists( 'WC_Subscriptions_Cart' ) && class_exists( 'WC_Subscriptions_Product' ) && \WC_Subscriptions_Cart::cart_contains_subscription() )
			|| ( function_exists( 'wcs_cart_contains_renewal' ) && wcs_cart_contains_renewal() )
		) {
			return true;
		}

		// Sublium subscriptions
		if ( class_exists( '\Sublium_WCS\Includes\Main\Cart' ) ) {
			$sublium_cart = \Sublium_WCS\Includes\Main\Cart::get_instance();
			if ( method_exists( $sublium_cart, 'cart_contains_plan' ) && $sublium_cart->cart_contains_plan() ) {
				return true;
			}
		}

		return false;
	}

	/**
	 * Whether a given product has a Sublium installment/subscription plan attached.
	 * Used on product pages to prevent smart buttons from rendering.
	 *
	 * @param \WC_Product $product
	 * @return bool
	 */
	public static function product_has_sublium_plan( $product ): bool {
		if ( ! class_exists( '\Sublium_WCS\Includes\Main\Plans' ) ) {
			return false;
		}
		return ! empty( \Sublium_WCS\Includes\Main\Plans::get_sorted_plans_by_product( $product ) );
	}

	/**
	 * Move Square gateway to the top of the payment methods list
	 *
	 * @param array $ordering Existing ordering
	 * @return array Modified ordering
	 */
	public function move_square_gateway_to_first( $ordering ) {
		$ordering = (array) $ordering;

		$key = 'fkwcsq_square';
		if ( ! isset( $ordering[ $key ] ) || ! is_numeric( $ordering[ $key ] ) ) {
			$is_empty         = empty( $ordering ) || ( count( $ordering ) === 1 && $ordering[0] === false );
			$ordering[ $key ] = $is_empty ? 0 : ( min( $ordering ) - 1 );
		}

		return $ordering;
	}

	/**
	 * Disable other Square gateways when FunnelKit Square is connected
	 */
	public function disable_other_square_gateways() {
		$gateways = WC()->payment_gateways->payment_gateways();

		// List of competing Square plugin gateway IDs to disable
		$square_gateway_ids = array(
			'square_credit_card',
			'square_cash_app_pay',
			'gift_cards_pay',
			'square_plus',
			'square_plus_sandbox',
			'square_ach_payment',
			'square_ach_payment_sandbox',
			'square_google_pay',
			'square_google_pay_sandbox',
			'square_apple_pay',
			'square_apple_pay_sandbox',
			'square_terminal_pay',
			'square_terminal_pay_sandbox',
			'square_gift_card_coupen_pay',
			'square_gift_card_coupen_pay_sandbox',
		);

		foreach ( $square_gateway_ids as $gateway_id ) {
			if ( isset( $gateways[ $gateway_id ] ) && 'yes' === $gateways[ $gateway_id ]->enabled ) {
				$gateways[ $gateway_id ]->update_option( 'enabled', 'no' );
			}
		}
	}

	/**
	 * Enable FunnelKit Square gateway after connection
	 */
	public function enable_funnelkit_square_gateway() {
		$gateways = WC()->payment_gateways->payment_gateways();

		$funnelkit_square_gateways = array(
			'fkwcsq_square',
			'fkwcsq_apple_pay',
			'fkwcsq_google_pay',
		);

		foreach ( $funnelkit_square_gateways as $gateway_id ) {
			if ( isset( $gateways[ $gateway_id ] ) && 'no' === $gateways[ $gateway_id ]->enabled ) {
				$gateways[ $gateway_id ]->update_option( 'enabled', 'yes' );
			}
		}

		if ( class_exists( 'WFOCU_Core' ) ) {
			$all_options               = WFOCU_Core()->data->get_option();
			$funnelkit_square_gateways = array(
				'fkwcsq_square',
				'fkwcsq_apple_pay',
				'fkwcsq_google_pay',
			);

			foreach ( $funnelkit_square_gateways as $gateway_id ) {
				if ( ! in_array( $gateway_id, $all_options['gateways'], true ) ) {
					array_push( $all_options['gateways'], $gateway_id );
				}
			}

			WFOCU_Core()->data->update_options( $all_options );
		}
	}
}

/**
 * Start the plugin
 */
function FKWCSQ() {
	// Create instance and register hooks
	$instance = Square::instance();
	$instance->register_activation_hooks();

	return $instance;
}

// Initialize the plugin
FKWCSQ();
