<?php
/**
 * Main application bootstrap for the PDFDraft WooCommerce plugin.
 *
 * @package PDFDraft_WooCommerce
 */

namespace PDFDraft\Woocommerce;

use PDFDraft\Traits\Hooks;
use PDFDraft\Woocommerce\Admin\Menu;
use PDFDraft\Woocommerce\Admin\OrderEdit;
use PDFDraft\Woocommerce\Admin\OrdersTable;
use PDFDraft\Woocommerce\Admin\Settings\PageAssets as SettingsPageAssets;
use PDFDraft\Woocommerce\Admin\Settings\Registry as SettingsRegistry;
use PDFDraft\Woocommerce\Admin\Settings\Sections\InvoicesSection;
use PDFDraft\Services\StorageService;
use PDFDraft\Woocommerce\Core\ActiveDesign;
use PDFDraft\Woocommerce\Core\Assets;
use PDFDraft\Woocommerce\Core\OrderEmailAttachment;
use PDFDraft\Woocommerce\Core\OrderInvoiceGenerator;
use PDFDraft\Woocommerce\Core\OrderInvoiceService;
use PDFDraft\Woocommerce\Core\PdfSettingsOption;
use PDFDraft\Woocommerce\Core\Settings;
use PDFDraft\Woocommerce\Core\VirtualOrderEmailSuppressor;
use PDFDraft\Woocommerce\Controllers\DownloadInvoiceController;
use PDFDraft\Woocommerce\Frontend\CheckoutPage;
use PDFDraft\Woocommerce\Frontend\MyAccount;
use PDFDraft\Woocommerce\Frontend\OrderReceived;

/**
 * Singleton application class that wires all plugin components together.
 */
class App {

	use Hooks;

	/**
	 * Singleton instance.
	 *
	 * @var \PDFDraft\Woocommerce\App|null
	 */
	private static ?\PDFDraft\Woocommerce\App $instance = null;

	/**
	 * Active design manager.
	 *
	 * @var ActiveDesign
	 */
	private ActiveDesign $activeDesign;

	/**
	 * Assets service.
	 *
	 * @var Assets
	 */
	private Assets $assets;

	/**
	 * Settings section registry.
	 *
	 * @var SettingsRegistry
	 */
	private SettingsRegistry $settingsRegistry;

	/**
	 * Settings page CSS assets.
	 *
	 * @var SettingsPageAssets
	 */
	private SettingsPageAssets $settingsPageAssets;

	/**
	 * Download invoice REST controller.
	 *
	 * @var DownloadInvoiceController
	 */
	private DownloadInvoiceController $downloadInvoiceController;

	/**
	 * Admin menu handler.
	 *
	 * @var Menu
	 */
	private Menu $menu;

	/**
	 * PDF settings option handler.
	 *
	 * @var PdfSettingsOption
	 */
	private PdfSettingsOption $pdfSettingsOption;

	/**
	 * Settings manager.
	 *
	 * @var Settings
	 */
	private Settings $settings;

	/**
	 * Orders table integration.
	 *
	 * @var OrdersTable
	 */
	private OrdersTable $ordersTable;

	/**
	 * Order edit screen integration.
	 *
	 * @var OrderEdit
	 */
	private OrderEdit $orderEdit;

	/**
	 * My Account page integration.
	 *
	 * @var MyAccount
	 */
	private MyAccount $myAccount;

	/**
	 * Get or create the singleton instance.
	 *
	 * @return \PDFDraft\Woocommerce\App
	 */
	public static function instance() {

		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Initialize properties and hooks.
	 */
	protected function __construct() {
		$this->initProps();
		$this->initHooks();
	}

	/**
	 * Instantiate all plugin service objects.
	 *
	 * @return void
	 */
	private function initProps() {
		$this->pdfSettingsOption = new PdfSettingsOption();
		$storage                 = pdfdraft( StorageService::class );
		$storage->protectDirectory();
		$orderInvoiceSvc    = new OrderInvoiceService( $storage, $this->pdfSettingsOption );
		$this->activeDesign = new ActiveDesign();

		// Settings registry — register core sections then allow third-party extension via filter.
		$this->settingsRegistry = new SettingsRegistry();
		$this->settingsRegistry->addSection( new InvoicesSection() );

		$this->settingsPageAssets        = new SettingsPageAssets();
		$this->assets                    = new Assets( $this->settingsRegistry );
		$this->downloadInvoiceController = new DownloadInvoiceController( $orderInvoiceSvc );
		$this->menu                      = new Menu( $this->settingsRegistry );
		$this->settings                  = new Settings();
		$this->ordersTable               = new OrdersTable( $this->assets );
		$this->orderEdit                 = new OrderEdit( $this->assets );
		$this->myAccount                 = new MyAccount( $this->assets, $this->pdfSettingsOption );
		$orderInvoiceGenerator           = new OrderInvoiceGenerator( $orderInvoiceSvc, $this->pdfSettingsOption );
		$orderInvoiceGenerator->initHooks();
		( new OrderEmailAttachment( $orderInvoiceSvc ) )->initHooks();
		( new VirtualOrderEmailSuppressor( $orderInvoiceSvc, $this->pdfSettingsOption ) )->initHooks();
	}

	/**
	 * Register all WordPress hooks for the plugin.
	 *
	 * @return void
	 */
	private function initHooks() {
		$this->addAction( 'init', array( $this, 'onInit' ), 0 );
		$this->addAction( 'rest_api_init', array( $this->downloadInvoiceController, 'register_routes' ) );
		$this->activeDesign->initHooks();
		$this->pdfSettingsOption->initHooks();
		$this->settings->initHooks();
		if ( is_admin() ) {
			if ( current_user_can( 'manage_woocommerce' ) || current_user_can( 'manage_options' ) ) { // phpcs:ignore WordPress.WP.Capabilities.Unknown
				$this->assets->initHooks();
				$this->settingsPageAssets->initHooks();
			}
			$this->menu->initHooks();
			$this->ordersTable->initHooks();
			$this->orderEdit->initHooks();
		} else {
			$this->myAccount->initHooks();
			( new CheckoutPage() )->initHooks();
			( new OrderReceived() )->initHooks();
		}
	}

	/**
	 * Handle the WordPress init action.
	 *
	 * @return void
	 */
	public function onInit() {
		$this->doAction( 'pdfdraft:woocommerce:init' );
	}
}
