<?php
/**
 * Main application bootstrap class.
 *
 * @package PDFDraft
 */

namespace PDFDraft;

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

use PDFDraft\PostsToPdf\PostsToPdf;
use PDFDraft\PostTypes\PDFDesign;
use PDFDraft\PostTypes\PostType;
use PDFDraft\Services\StorageService;
use PDFDraft\Traits\Hooks;

/**
 * Bootstraps the PDFDraft plugin components.
 */
class App {
	use Hooks;

	/**
	 * Initialize and run all plugin components.
	 *
	 * @return void
	 */
	public function run() {
		pdfdraft( Activation::class )->init();
		pdfdraft( Uninstall::class )->init();
		pdfdraft( Admin::class )->init();
		pdfdraft( EmbedPdf::class )->init();
		pdfdraft( DownloadPdf::class )->init();
		pdfdraft( ScriptStyle::class )->init();
		pdfdraft( PostsToPdf::class )->init();
		$this->addAction( 'init', array( $this, 'onInit' ), 0 );
		$this->addAction( 'rest_api_init', array( $this, 'onRestApiInit' ) );
	}

	/**
	 * Handle the WordPress init action.
	 *
	 * @return void
	 */
	public function onInit() {
		$this->checkVersion();
		$this->loadTextdomain();
		pdfdraft( StorageService::class )->protectDirectory();
		$this->registerPostTypes();
		$this->registerUserPreferencesMeta();
		$this->doAction( 'pdfdraft_init' );
	}

	/**
	 * Initialize assets.
	 *
	 * @return void
	 */
	private function initAssets() {}

	/**
	 * Check the plugin version and update if necessary.
	 *
	 * @return void
	 */
	private function checkVersion() {
		$settings   = pdfdraft( Settings::class );
		$oldVersion = $settings->get( 'version' );
		$newVersion = PDFDRAFT_VERSION;

		if ( $oldVersion && version_compare( $newVersion, $oldVersion, '<=' ) ) {
			return;
		}

		$data = array(
			'version' => $newVersion,
		);

		if ( ! $oldVersion ) {
			$data['install_time'] = current_time( 'mysql', true );
			$this->doAction( 'pdfdraft_installed' );
		}

		if ( ! empty( $data ) ) {
			$settings->bulkSet( $data )->save();
		}

		if ( $oldVersion && version_compare( $newVersion, $oldVersion, '>' ) ) {
			$this->doAction( 'pdfdraft_version_updated', $newVersion, $oldVersion );
		}
	}

	/**
	 * Load plugin text domain.
	 *
	 * @return void
	 */
	private function loadTextdomain() {
		// phpcs:ignore -- Explicit textdomain path; Plugin Check may flag load_plugin_textdomain — intentional here.
		load_plugin_textdomain( 'pdfdraft', false, PDFDRAFT_LANGUAGE_DIR );
	}

	/**
	 * Register post types.
	 *
	 * @return void
	 */
	private function registerPostTypes() {
		/* @var array<PostType> $postTypeClasses */
		$postTypeClasses = $this->applyFilters(
			'pdfdraft_post_type_classes',
			array(
				PDFDesign::class,
			)
		);
		foreach ( $postTypeClasses as $postTypeClass ) {
			( new $postTypeClass() )->register();
		}
	}

	/**
	 * Register REST API controllers.
	 *
	 * @return void
	 */
	public function onRestApiInit() {
		/* @var array<string> $restClasses */
		$restClasses = $this->applyFilters(
			'pdfdraft_rest_api_classes',
			array(
				\PDFDraft\Controllers\V1\SettingsController::class,
				\PDFDraft\Controllers\V1\FontFamiliesController::class,
				\PDFDraft\Controllers\V1\ImagesController::class,
			)
		);

		foreach ( $restClasses as $restClass ) {
			$controller = pdfdraft( $restClass );
			if ( $controller instanceof \WP_REST_Controller ) {
				$controller->register_routes();
			}
		}

		$this->doAction( 'pdfdraft_rest_api_init' );
	}

	/**
	 * Register user preferences meta field.
	 *
	 * @return void
	 */
	public function registerUserPreferencesMeta() {
		register_meta(
			'user',
			'_pdfdraft_persisted_preferences',
			array(
				'show_in_rest'  => true,
				'type'          => 'string',
				'single'        => true,
				'auth_callback' => function () {
					return current_user_can( 'edit_posts' );
				},
			)
		);
	}
}
