<?php
/**
 * Cron Handler for Square Token Refresh
 *
 * @package FunnelKit_Square
 */

namespace FKWCSQ\Includes;

use FKWCSQ\Includes\Traits\Instance;

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

/**
 * Class FKWCSQ_Cron
 */
class Cron {
	use Instance;

	/**
	 * Configuration for Action Scheduler sync tasks.
	 *
	 * Defines the mapping between action hooks and their corresponding methods and settings.
	 * Each entry contains:
	 * - 'method': The class method to call when the action is executed
	 * - 'interval_option': The option name in settings that controls sync frequency
	 *
	 * This configuration enables dynamic registration and scheduling of all sync tasks
	 * with consistent behavior while maintaining individual control over each sync type.
	 *
	 * @since 1.0.0
	 * @access private
	 * @var array
	 */
	private static $sync_actions = array(
		'fkwcsq_sync_products'   => array( 'method' => 'sync_products', 'interval_option' => 'sync_interval' ),
		'fkwcsq_sync_categories' => array( 'method' => 'sync_categories', 'interval_option' => 'sync_interval' ),
		'fkwcsq_sync_inventory'  => array( 'method' => 'sync_inventory', 'interval_option' => 'sync_interval' ),
		'fkwcsq_sync_customers'  => array( 'method' => 'sync_customers', 'interval_option' => 'sync_interval' ),
	);

	/**
	 * Constructor.
	 *
	 * Sets up cron job for refreshing Square token, schedules daily refresh,
	 * and registers deactivation hook to clean up scheduled events.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	private function __construct() {
		// Register cron hook
		add_action( 'fkwcsq_refresh_square_token', array( __CLASS__, 'refresh_token' ) );

		// Schedule cron if not already scheduled
		if ( ! wp_next_scheduled( 'fkwcsq_refresh_square_token' ) ) {
			wp_schedule_event( time(), 'daily', 'fkwcsq_refresh_square_token' );
		}

		// Add deactivation hook to clear scheduled event
		register_deactivation_hook( FKWCSQ_ABSPATH, array( __CLASS__, 'clear_scheduled_refresh' ) );

		// Register Action Scheduler actions
		foreach ( array_keys( self::$sync_actions ) as $hook ) {
			add_action( $hook, array( __CLASS__, $hook ) );
		}
		add_action( 'fkwcsq_settings_saved', array( __CLASS__, 'schedule_all_syncs' ) );
	}

	/**
	 * Clear scheduled refresh on plugin deactivation
	 */
	public static function clear_scheduled_refresh() {
		wp_clear_scheduled_hook( 'fkwcsq_refresh_square_token' );
		// Clear all sync actions
		foreach ( array_keys( self::$sync_actions ) as $hook ) {
			if ( function_exists( 'as_unschedule_all_actions' ) ) {
				as_unschedule_all_actions( $hook );
			}
		}
	}

	/**
	 * Refresh Square access token
	 */
	public static function refresh_token() {
		Logger::debug( 'Starting scheduled Square token refresh' );

		try {
			// Initialize API
			$api = API::get_instance();

			// Attempt to refresh token
			$result = $api->refresh_access_token();
			if ( $result ) {
				Logger::info( 'Successfully refreshed Square access token via cron' );
			} else {
				Logger::error( 'Failed to refresh Square access token via cron' );
			}
		} catch ( \Exception $e ) {
			Logger::error( 'Error in scheduled token refresh: ' . $e->getMessage() );
		}
	}

	/**
	 * Schedule and handle unified sync for all types (product, category, inventory, customer)
	 */
	public static function schedule_all_syncs() {
		$settings = get_option( 'fkwcsq_settings', array() );

		$interval = isset( $settings['sync_interval'] ) ? $settings['sync_interval'] : '1h';
		$direction = isset( $settings['sync_direction'] ) ? $settings['sync_direction'] : 'disabled';

		$interval_map = array(
			'15min' => 15 * MINUTE_IN_SECONDS,
			'30min' => 30 * MINUTE_IN_SECONDS,
			'1h'    => HOUR_IN_SECONDS,
			'2h'    => 2 * HOUR_IN_SECONDS,
			'3h'    => 3 * HOUR_IN_SECONDS,
			'6h'    => 6 * HOUR_IN_SECONDS,
			'8h'    => 8 * HOUR_IN_SECONDS,
			'12h'   => 12 * HOUR_IN_SECONDS,
			'24h'   => 24 * HOUR_IN_SECONDS,
		);
		$interval_seconds = isset( $interval_map[ $interval ] ) ? $interval_map[ $interval ] : HOUR_IN_SECONDS;

		$last_interval_seconds = isset( $settings['last_scheduled_interval'] ) ? $settings['last_scheduled_interval'] : 0;

		if ( $direction === 'disabled' ) {
			if ( function_exists( 'as_unschedule_all_actions' ) ) {
				foreach ( array_keys( self::$sync_actions ) as $hook ) {
					as_unschedule_all_actions( $hook );
				}
			}
			$settings['last_scheduled_interval'] = 0;
			update_option( 'fkwcsq_settings', $settings );
			return;
		}

		if ( $interval_seconds !== $last_interval_seconds ) {
			if ( function_exists( 'as_unschedule_all_actions' ) ) {
				foreach ( array_keys( self::$sync_actions ) as $hook ) {
					as_unschedule_all_actions( $hook );
				}
			}
			if ( function_exists( 'as_schedule_recurring_action' ) ) {
				foreach ( array_keys( self::$sync_actions ) as $hook ) {
					as_schedule_recurring_action( time() + $interval_seconds, $interval_seconds, $hook );
				}
			}

			$settings['last_scheduled_interval'] = $interval_seconds;
			update_option( 'fkwcsq_settings', $settings );
		} else {
			foreach ( array_keys( self::$sync_actions ) as $hook ) {
				if ( function_exists( 'as_next_scheduled_action' ) && ! as_next_scheduled_action( $hook ) ) {
					as_schedule_recurring_action( time() + $interval_seconds, $interval_seconds, $hook );
				}
			}
		}
	}


	/**
	 * Synchronize WooCommerce products to Square.
	 *
	 * Checks if sync direction is set to 'woocommerce' in plugin settings
	 * before initiating the product sync process. This method is designed
	 * to be called by the Action Scheduler.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	public static function fkwcsq_sync_products() {
		// Check if Square is properly configured
		if ( ! \FKWCSQ\Square::is_configured() ) {
			Logger::info( 'Product sync skipped: Square integration not configured' );
			return;
		}
		update_option('fkwcsq_last_sync', gmdate('Y-m-d H:i:s'));

		$settings = get_option( 'fkwcsq_settings', array() );
		if ( isset( $settings['sync_direction'] ) ) {
			Logger::info( 'Running scheduled product sync.' );
			if ( $settings['sync_direction'] === 'woocommerce' ) {
				$result = \FKWCSQ\Includes\Sync\Product::get_instance()->schedule_batch_sync();
				if ( is_array($result) ) {
					$message = sprintf('Product sync completed: %d total, %d successful, %d failed',
						$result['total'], $result['success'], $result['failed']);

					// Add successful product IDs (first 10)
					if ( ! empty( $result['success_ids'] ) ) {
						$success_sample = array_slice( $result['success_ids'], 0, 10 );
						$message .= sprintf(' - Successful IDs: %s', implode( ', ', $success_sample ));
						if ( count( $result['success_ids'] ) > 10 ) {
							$message .= sprintf(' (and %d more)', count( $result['success_ids'] ) - 10 );
						}
					}

					// Add failed product IDs (first 5)
					if ( ! empty( $result['failed_ids'] ) ) {
						$failed_sample = array_slice( $result['failed_ids'], 0, 5 );
						$message .= sprintf(' - Failed IDs: %s', implode( ', ', $failed_sample ));
						if ( count( $result['failed_ids'] ) > 5 ) {
							$message .= sprintf(' (and %d more)', count( $result['failed_ids'] ) - 5 );
						}
					}

					if ( $result['failed'] > 0 && ! empty( $result['errors'] ) ) {
						$message .= ' - Errors: ' . implode( '; ', array_slice( $result['errors'], 0, 3 ) );
						if ( count( $result['errors'] ) > 3 ) {
							$message .= ' (and ' . ( count( $result['errors'] ) - 3 ) . ' more)';
						}
					}

					// Store simple product sync status
					$sync_status = array(
						'status' => ($result['failed'] > 0) ? 'failed' : 'succeeded',
						'timestamp' => gmdate('Y-m-d H:i:s')
					);
					update_option('fkwcsq_products_sync_status', $sync_status);
					
					Logger::info( $message );
				}
			} elseif ( $settings['sync_direction'] === 'square' ) {
				$result = \FKWCSQ\Includes\Sync\Product::get_instance()->import_all_from_square();
				if ( is_numeric($result) ) {
					// Store successful import status
					$sync_status = array(
						'status' => 'succeeded',
						'timestamp' => gmdate('Y-m-d H:i:s')
					);
					update_option('fkwcsq_products_sync_status', $sync_status);
					
					Logger::info( sprintf('Product import completed: %d products imported', $result) );
				} elseif ( is_wp_error($result) ) {
					// Store failed import status
					$sync_status = array(
						'status' => 'failed',
						'timestamp' => gmdate('Y-m-d H:i:s')
					);
					update_option('fkwcsq_products_sync_status', $sync_status);
					
					Logger::error( 'Product import failed: ' . $result->get_error_message() );
				}
			}
		}
	}

	/**
	 * Synchronize WooCommerce product categories to Square.
	 *
	 * Checks if sync direction is set to 'woocommerce' in plugin settings
	 * before initiating the category sync process. This method is designed
	 * to be called by the Action Scheduler.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	public static function fkwcsq_sync_categories() {
		// Check if Square is properly configured
		if ( ! \FKWCSQ\Square::is_configured() ) {
			Logger::info( 'Category sync skipped: Square integration not configured' );
			return;
		}

		$settings = get_option( 'fkwcsq_settings', array() );
		if ( isset( $settings['sync_direction'] ) && $settings['sync_direction'] === 'woocommerce' ) {
			Logger::info( 'Running scheduled category sync.' );
			$result = \FKWCSQ\Includes\Sync\Category::get_instance()->schedule_batch_sync();
			if ( is_array($result) ) {
				$message = sprintf('Category sync completed: %d total, %d successful, %d failed',
					$result['total'], $result['success'], $result['failed']);

				// Add successful category IDs (first 10)
				if ( ! empty( $result['success_ids'] ) ) {
					$success_sample = array_slice( $result['success_ids'], 0, 10 );
					$message .= sprintf(' - Successful IDs: %s', implode( ', ', $success_sample ));
					if ( count( $result['success_ids'] ) > 10 ) {
						$message .= sprintf(' (and %d more)', count( $result['success_ids'] ) - 10 );
					}
				}

				// Add failed category IDs (first 5)
				if ( ! empty( $result['failed_ids'] ) ) {
					$failed_sample = array_slice( $result['failed_ids'], 0, 5 );
					$message .= sprintf(' - Failed IDs: %s', implode( ', ', $failed_sample ));
					if ( count( $result['failed_ids'] ) > 5 ) {
						$message .= sprintf(' (and %d more)', count( $result['failed_ids'] ) - 5 );
					}
				}

				if ( $result['failed'] > 0 && ! empty( $result['errors'] ) ) {
					$message .= ' - Errors: ' . implode( '; ', array_slice( $result['errors'], 0, 3 ) );
					if ( count( $result['errors'] ) > 3 ) {
						$message .= ' (and ' . ( count( $result['errors'] ) - 3 ) . ' more)';
					}
				}

				// Store simple category sync status
				$sync_status = array(
					'status' => ($result['failed'] > 0) ? 'failed' : 'succeeded',
					'timestamp' => gmdate('Y-m-d H:i:s')
				);
				update_option('fkwcsq_categories_sync_status', $sync_status);

				Logger::info( $message );
			}
		}
	}

	/**
	 * Synchronize WooCommerce product inventory to Square.
	 *
	 * Checks if sync direction is set to 'woocommerce' in plugin settings
	 * before initiating the inventory sync process. This method is designed
	 * to be called by the Action Scheduler.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	public static function fkwcsq_sync_inventory() {
		// Check if Square is properly configured
		if ( ! \FKWCSQ\Square::is_configured() ) {
			Logger::info( 'Inventory sync skipped: Square integration not configured' );
			return;
		}

		$settings = get_option( 'fkwcsq_settings', array() );
		if ( isset( $settings['sync_direction'] ) && $settings['sync_direction'] === 'woocommerce' ) {
			Logger::info( 'Running scheduled inventory sync.' );
			$result = \FKWCSQ\Includes\Sync\Inventory::get_instance()->schedule_batch_sync();
			if ( is_array($result) ) {
				$message = sprintf('Inventory sync completed: %d total, %d successful, %d failed',
					$result['total'], $result['success'], $result['failed']);

				// Add successful product IDs (first 10)
				if ( ! empty( $result['success_ids'] ) ) {
					$success_sample = array_slice( $result['success_ids'], 0, 10 );
					$message .= sprintf(' - Successful IDs: %s', implode( ', ', $success_sample ));
					if ( count( $result['success_ids'] ) > 10 ) {
						$message .= sprintf(' (and %d more)', count( $result['success_ids'] ) - 10 );
					}
				}

				// Add failed product IDs (first 5)
				if ( ! empty( $result['failed_ids'] ) ) {
					$failed_sample = array_slice( $result['failed_ids'], 0, 5 );
					$message .= sprintf(' - Failed IDs: %s', implode( ', ', $failed_sample ));
					if ( count( $result['failed_ids'] ) > 5 ) {
						$message .= sprintf(' (and %d more)', count( $result['failed_ids'] ) - 5 );
					}
				}

				if ( $result['failed'] > 0 && ! empty( $result['errors'] ) ) {
					$message .= ' - Errors: ' . implode( '; ', array_slice( $result['errors'], 0, 3 ) );
					if ( count( $result['errors'] ) > 3 ) {
						$message .= ' (and ' . ( count( $result['errors'] ) - 3 ) . ' more)';
					}
				}

				// Store simple inventory sync status
				$sync_status = array(
					'status' => ($result['failed'] > 0) ? 'failed' : 'succeeded',
					'timestamp' => gmdate('Y-m-d H:i:s')
				);
				update_option('fkwcsq_inventory_sync_status', $sync_status);

				Logger::info( $message );
			}
		}
	}

	/**
	 * Synchronize WooCommerce customers to Square.
	 *
	 * Checks if sync direction is set to 'woocommerce' in plugin settings
	 * before initiating the customer sync process. This method is designed
	 * to be called by the Action Scheduler.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	public static function fkwcsq_sync_customers() {
		// Check if Square is properly configured
		if ( ! \FKWCSQ\Square::is_configured() ) {
			Logger::info( 'Customer sync skipped: Square integration not configured' );
			return;
		}

		$settings = get_option( 'fkwcsq_settings', array() );
		if ( isset( $settings['sync_direction'] ) && $settings['sync_direction'] === 'woocommerce' ) {
			Logger::info( 'Running scheduled customer sync.' );
			$result = \FKWCSQ\Includes\Sync\Customer::get_instance()->sync_all_customers_to_square();
			if ( is_array($result) ) {
				$message = sprintf('Customer sync completed: %d total, %d successful, %d failed',
					$result['total'], $result['success'], $result['failed']);

				// Add successful customer IDs (first 10)
				if ( ! empty( $result['success_ids'] ) ) {
					$success_sample = array_slice( $result['success_ids'], 0, 10 );
					$message .= sprintf(' - Successful IDs: %s', implode( ', ', $success_sample ));
					if ( count( $result['success_ids'] ) > 10 ) {
						$message .= sprintf(' (and %d more)', count( $result['success_ids'] ) - 10 );
					}
				}

				// Add failed customer IDs (first 5)
				if ( ! empty( $result['failed_ids'] ) ) {
					$failed_sample = array_slice( $result['failed_ids'], 0, 5 );
					$message .= sprintf(' - Failed IDs: %s', implode( ', ', $failed_sample ));
					if ( count( $result['failed_ids'] ) > 5 ) {
						$message .= sprintf(' (and %d more)', count( $result['failed_ids'] ) - 5 );
					}
				}

				if ( $result['failed'] > 0 && ! empty( $result['errors'] ) ) {
					$message .= ' - Errors: ' . implode( '; ', array_slice( $result['errors'], 0, 3 ) );
					if ( count( $result['errors'] ) > 3 ) {
						$message .= ' (and ' . ( count( $result['errors'] ) - 3 ) . ' more)';
					}
				}

				// Store simple customer sync status
				$sync_status = array(
					'status' => ($result['failed'] > 0) ? 'failed' : 'succeeded',
					'timestamp' => gmdate('Y-m-d H:i:s')
				);
				update_option('fkwcsq_customers_sync_status', $sync_status);

				Logger::info( $message );
			}
		}
	}
}
