<?php
/**
 * Main Plugin Class
 *
 * Implements singleton pattern and orchestrates plugin initialization.
 *
 * @package DonorCore
 */

namespace DonorCore;

defined( 'ABSPATH' ) || exit;

/**
 * Main Plugin Singleton
 */
final class Plugin {

	/**
	 * Singleton instance.
	 *
	 * @var Plugin|null
	 */
	private static $instance = null;

	/**
	 * Dependency Injection Container.
	 *
	 * @var Utils\Container
	 */
	private $container;

	/**
	 * Hook Loader.
	 *
	 * @var Utils\Hook_Loader
	 */
	private $loader;

	/**
	 * Run on plugin deactivation.
	 */
	public static function deactivate() {
		// Remove custom roles.
		Security\Role_Manager::remove_roles();

		// Flush rewrite rules.
		flush_rewrite_rules();
	}

	/**
	 * Run on plugin activation.
	 */
	public static function activate() {
		// Run database migrations.
		$migration_manager = new Database\Migration_Manager();
		$migration_manager->run_migrations();

		// Create security tables.
		Security\Security_Schema::create_tables();

		// Create custom roles.
		Security\Role_Manager::create_roles();

		// Add database indexes for performance.
		Performance\Query_Optimizer::add_indexes();

		// Flush rewrite rules.
		flush_rewrite_rules();
	}

	/**
	 * Get singleton instance.
	 *
	 * @return Plugin
	 */
	public static function instance() {
		if ( is_null( self::$instance ) ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Private constructor to enforce singleton.
	 */
	private function __construct() {
		$this->load_dependencies();
		$this->init_hooks();
		$this->setup_currency_filter();
	}
	
	/**
	 * Setup global currency symbol filter for dollar currencies.
	 */
	private function setup_currency_filter() {
		add_filter( 'woocommerce_currency_symbol', array( $this, 'custom_currency_symbol' ), 10, 2 );
	}
	
	/**
	 * Customize currency symbols for dollar currencies to show distinct symbols.
	 * Applies globally to all wc_price() calls.
	 *
	 * @param string $symbol   Currency symbol.
	 * @param string $currency Currency code.
	 * @return string Modified currency symbol.
	 */
	public function custom_currency_symbol( $symbol, $currency ) {
		// Get the currently active WooCommerce currency
		$active_currency = get_woocommerce_currency();
		
		// Only customize if this is the active currency
		if ( $currency !== $active_currency ) {
			return $symbol;
		}
		
		// Map dollar currencies to distinct symbols
		$dollar_symbols = array(
			'AUD' => 'A$',   // Australian Dollar
			'CAD' => 'CA$',  // Canadian Dollar
			'NZD' => 'NZ$',  // New Zealand Dollar
			'SGD' => 'S$',   // Singapore Dollar
			'HKD' => 'HK$',  // Hong Kong Dollar
		);
		
		// If the active currency is in our list, return the distinct symbol
		if ( isset( $dollar_symbols[ $currency ] ) ) {
			return $dollar_symbols[ $currency ];
		}
		
		// Otherwise, use WooCommerce's default symbol
		return $symbol;
	}

	/**
	 * Load dependencies and initialize DI container.
	 */
	private function load_dependencies() {
		// Initialize DI Container.
		$this->container = new Utils\Container();
		$this->loader    = new Utils\Hook_Loader();

		// Register core services.
		$this->register_services();
	}

	/**
	 * Register services in the DI container.
	 */
	private function register_services() {
		// Database services.
		$this->container->register( 'db_installer', Database\Schema_Installer::class );
		$this->container->register( 'migration_manager', Database\Migration_Manager::class );
		$this->container->register( 'donation_log_repo', Database\Donation_Log_Repository::class );
		$this->container->register( 'donor_analytics_repo', Database\Donor_Analytics_Repository::class );

		// WooCommerce services.
		$this->container->register( 'product_type_registration', WooCommerce\Product_Type_Registration::class );
		$this->container->register( 'campaign_product_bridge', WooCommerce\Campaign_Product_Bridge::class );
		$this->container->register( 'checkout_manager', WooCommerce\Checkout_Manager::class );

		// Post Type services.
		$this->container->register( 'campaign_post_type', PostTypes\Campaign_Post_Type::class );

		// Frontend services.
		$this->container->register( 'block_registration', Frontend\Block_Registration::class );
		$this->container->register( 'block_styles', Frontend\Block_Styles::class );
		$this->container->register( 'style_generator', Frontend\Style_Generator::class );

		// Receipt services.
		$this->container->register( 'pdf_generator', Receipts\PDF_Generator::class );
		$this->container->register( 'receipt_manager', Receipts\Receipt_Manager::class );
		$this->container->register( 'receipt_downloader', Receipts\Receipt_Downloader::class );

		// Performance services.
		$this->container->register( 'asset_manager', Performance\Asset_Manager::class );
		$this->container->register( 'cache_manager', Performance\Cache_Manager::class );
		$this->container->register( 'query_optimizer', Performance\Query_Optimizer::class );

		// Privacy services (GDPR compliance).
		$this->container->register( 'privacy_exporter', Privacy\Privacy_Exporter::class );
		$this->container->register( 'privacy_eraser', Privacy\Privacy_Eraser::class );
		$this->container->register( 'privacy_policy', Privacy\Privacy_Policy::class );



		// Admin services (lazy loaded).
		$this->container->register(
			'admin_manager',
			Admin\Menu_Manager::class,
			function() {
				return new Admin\Menu_Manager( $this->container );
			}
		);

		// Frontend services (lazy loaded).
		$this->container->register(
			'frontend_manager',
			Frontend\Form_Manager::class,
			function() {
				return new Frontend\Form_Manager( $this->container );
			}
		);
		
		// Shortcodes service (manually load file first).
		require_once DONOR_CORE_PLUGIN_DIR . 'includes/Shortcodes/class-shortcodes.php';
		$this->container->register(
			'shortcodes',
			Shortcodes\Shortcodes::class,
			function() {
				return new Shortcodes\Shortcodes();
			}
		);
	}

	/**
	 * Initialize WordPress hooks.
	 */
	private function init_hooks() {
		// HPOS Compatibility Declaration - must run before WooCommerce init.
		$this->loader->add_action(
			'before_woocommerce_init',
			$this,
			'declare_hpos_compatibility'
		);

		// Main initialization.
		$this->loader->add_action( 'init', $this, 'on_init' );

		// Load text domain.
		$this->loader->add_action( 'init', $this, 'load_textdomain' );

		// Admin initialization.
		if ( is_admin() ) {
			$this->loader->add_action( 'admin_init', $this, 'init_admin' );
		}

		// Run all registered hooks.
		$this->loader->run();
	}

	/**
	 * Declare HPOS compatibility for WooCommerce.
	 */
	public function declare_hpos_compatibility() {
		if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
			\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
				'custom_order_tables',
				DONOR_CORE_PLUGIN_FILE,
				true
			);
		}
	}

	/**
	 * Load plugin text domain for translations.
	 * 
	 * WordPress.org will automatically override this with community translations
	 * from translate.wordpress.org, but we still load local translations for:
	 * - Development environments
	 * - Custom translations
	 * - Premium/non-WordPress.org versions
	 * - Backward compatibility
	 */
	public function load_textdomain() {
		// phpcs:ignore PluginCheck.CodeAnalysis.DiscouragedFunctions.load_plugin_textdomainFound -- Local fallback for development/custom languages
		load_plugin_textdomain(
			'donorcore-donations',
			false,
			dirname( DONOR_CORE_PLUGIN_BASENAME ) . '/languages'
		);
	}

	/**
	 * Initialize on WordPress 'init' hook.
	 */
	public function on_init() {
		// Initialize WooCommerce services.
			if ( class_exists( 'WooCommerce' ) ) {
			$this->container->get( 'product_type_registration' )->init();
			$this->container->get( 'campaign_product_bridge' )->init();
			$this->container->get( 'checkout_manager' )->init();
		}

		// Initialize Post Type services.
		$this->container->get( 'campaign_post_type' )->init();

		// Initialize Frontend services.
		$this->container->get( 'block_registration' )->init();
		
		// Manually load Block_Styles and initialize
		require_once DONOR_CORE_PLUGIN_DIR . 'includes/Frontend/class-block-styles.php';
		$block_styles = new Frontend\Block_Styles();
		$block_styles->init();
		
		// Manually load and initialize Style Generator for dynamic CSS
		require_once DONOR_CORE_PLUGIN_DIR . 'includes/Frontend/class-style-generator.php';
		$style_generator = new Frontend\Style_Generator();


		// Initialize Receipt services.
		$this->container->get( 'receipt_manager' )->init();
		$this->container->get( 'receipt_downloader' )->init();

		// Initialize Performance services.
		$this->container->get( 'asset_manager' )->init();
		$this->container->get( 'cache_manager' )->init();
		$this->container->get( 'query_optimizer' )->init();

		// Initialize Privacy services (GDPR compliance).
		$this->container->get( 'privacy_exporter' )->init();
		$this->container->get( 'privacy_eraser' )->init();
		$this->container->get( 'privacy_policy' )->init();

		// Initialize Shortcodes.
		$this->container->get( 'shortcodes' )->init();
		
		// Initialize Admin services
		$admin_manager = $this->container->get( 'admin_manager' );
		$admin_manager->init();

		// Register REST API endpoints.
		$this->register_rest_routes();
	}

	/**
	 * Initialize admin-specific functionality (called by hook).
	 */
	public function init_admin() {
		// Admin manager already initialized in on_init
	}

	/**
	 * Register REST API routes.
	 */
	private function register_rest_routes() {
		add_action(
			'rest_api_init',
			function() {
				// Register API controllers.
				$campaigns_controller = new API\Campaigns_Controller();
				$campaigns_controller->register_routes();

				$analytics_controller = new API\Analytics_Controller();
				$analytics_controller->register_routes();

				$donors_controller = new API\Donors_Controller();
				$donors_controller->register_routes();

				require_once DONOR_CORE_PLUGIN_DIR . 'includes/API/class-settings-controller.php';
				$settings_controller = new API\Settings_Controller();
				$settings_controller->register_routes();
			}
		);
	}

	/**
	 * Get the DI container.
	 *
	 * @return Utils\Container
	 */
	public function get_container() {
		return $this->container;
	}
}
