<?php
/**
 * Main plugin class (singleton).
 *
 * @package KwiroAISalesAgent
 */

defined( 'ABSPATH' ) || exit;

/**
 * Class Kwiro_Plugin
 *
 * Singleton class that initializes and orchestrates all plugin components.
 */
class Kwiro_Plugin {

	/**
	 * Single instance of the class.
	 *
	 * @var Kwiro_Plugin|null
	 */
	private static $instance = null;

	/**
	 * Admin instance.
	 *
	 * @var Kwiro_Admin|null
	 */
	private $admin = null;

	/**
	 * API Client instance.
	 *
	 * @var Kwiro_API_Client|null
	 */
	private $api_client = null;

	/**
	 * Product Sync instance.
	 *
	 * @var Kwiro_Product_Sync|null
	 */
	private $product_sync = null;

	/**
	 * Batch Processor instance.
	 *
	 * @var Kwiro_Batch_Processor|null
	 */
	private $batch_processor = null;

	/**
	 * Widget Injector instance.
	 *
	 * @var Kwiro_Widget_Injector|null
	 */
	private $widget_injector = null;

	/**
	 * Hooks instance.
	 *
	 * @var Kwiro_Hooks|null
	 */
	private $hooks = null;

	/**
	 * Sales Tracker instance.
	 *
	 * @var Kwiro_Sales_Tracker|null
	 */
	private $sales_tracker = null;

	/**
	 * Get the single instance of the class.
	 *
	 * @return Kwiro_Plugin
	 */
	public static function instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Constructor. Private to enforce singleton.
	 */
	private function __construct() {
		$this->load_dependencies();
		$this->init_components();
		$this->register_hooks();
	}

	/**
	 * Prevent cloning.
	 */
	private function __clone() {}

	/**
	 * Prevent unserializing.
	 *
	 * @throws \Exception Always.
	 */
	public function __wakeup() {
		throw new \Exception( 'Cannot unserialize singleton' );
	}

	/**
	 * Load required files.
	 */
	private function load_dependencies() {
		$includes_dir = KWIRO_PLUGIN_DIR . 'includes/';

		require_once $includes_dir . 'class-admin.php';
		require_once $includes_dir . 'class-api-client.php';
		require_once $includes_dir . 'class-product-sync.php';
		require_once $includes_dir . 'class-batch-processor.php';
		require_once $includes_dir . 'class-widget-injector.php';
		require_once $includes_dir . 'class-hooks.php';
		require_once $includes_dir . 'class-sales-tracker.php';
	}

	/**
	 * Initialize plugin components.
	 */
	private function init_components() {
		$this->api_client      = new Kwiro_API_Client();
		$this->product_sync    = new Kwiro_Product_Sync( $this->api_client );
		$this->batch_processor = new Kwiro_Batch_Processor( $this->product_sync );
		$this->widget_injector = new Kwiro_Widget_Injector( $this->api_client );
		$this->hooks           = new Kwiro_Hooks( $this->api_client, $this->product_sync );
		$this->sales_tracker   = new Kwiro_Sales_Tracker( $this->api_client );

		if ( is_admin() ) {
			$this->admin = new Kwiro_Admin( $this->api_client, $this->product_sync );
		}
	}

	/**
	 * Register WordPress hooks.
	 */
	private function register_hooks() {
		add_action( 'kwiro_batch_sync', array( $this->batch_processor, 'process_batch' ) );
	}

	/**
	 * Get the Admin instance.
	 *
	 * @return Kwiro_Admin|null
	 */
	public function get_admin() {
		return $this->admin;
	}

	/**
	 * Get the API Client instance.
	 *
	 * @return Kwiro_API_Client
	 */
	public function get_api_client() {
		return $this->api_client;
	}

	/**
	 * Get the Product Sync instance.
	 *
	 * @return Kwiro_Product_Sync
	 */
	public function get_product_sync() {
		return $this->product_sync;
	}

	/**
	 * Get the Batch Processor instance.
	 *
	 * @return Kwiro_Batch_Processor
	 */
	public function get_batch_processor() {
		return $this->batch_processor;
	}

	/**
	 * Get the Widget Injector instance.
	 *
	 * @return Kwiro_Widget_Injector|null
	 */
	public function get_widget_injector() {
		return $this->widget_injector;
	}

	/**
	 * Get the Hooks instance.
	 *
	 * @return Kwiro_Hooks|null
	 */
	public function get_hooks() {
		return $this->hooks;
	}

	/**
	 * Get the Sales Tracker instance.
	 *
	 * @return Kwiro_Sales_Tracker|null
	 */
	public function get_sales_tracker() {
		return $this->sales_tracker;
	}

	/**
	 * Reset the singleton instance (for testing only).
	 */
	public static function reset() {
		self::$instance = null;
	}
}
