<?php
/**
 * Vendor Namespace Resolver
 *
 * This class provides a bridge between scoped (production) and non-scoped (development)
 * vendor namespaces, allowing the plugin to work in both environments.
 *
 * @package Freefactu
 * @since   0.5.0
 */

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

/**
 * Freefactu Vendor Loader Class
 *
 * Resolves vendor class namespaces for both scoped (production) and non-scoped (development) environments.
 * This ensures the plugin works whether dependencies are prefixed with Freefactu_Vendor or not.
 *
 * @since 0.5.0
 */
class Freefactu_Vendor_Loader {

	/**
	 * The prefix used for scoped vendor dependencies.
	 *
	 * @var string
	 */
	const SCOPED_PREFIX = 'Freefactu_Vendor\\';

	/**
	 * Whether we're running with scoped dependencies.
	 *
	 * @var bool|null
	 */
	private static $is_scoped = null;

	/**
	 * Cached class mappings.
	 *
	 * @var array
	 */
	private static $class_cache = array();

	/**
	 * Check if we're running with scoped dependencies.
	 *
	 * @return bool True if using scoped vendor directory.
	 */
	public static function is_scoped() {
		if ( self::$is_scoped === null ) {
			// Check if the scoped Dompdf class exists (as a canary)
			self::$is_scoped = class_exists( self::SCOPED_PREFIX . 'Dompdf\\Dompdf' );
		}
		return self::$is_scoped;
	}

	/**
	 * Get the fully qualified class name, resolving scoped/non-scoped automatically.
	 *
	 * @param string $class_name The class name without scoped prefix (e.g., 'Dompdf\\Dompdf').
	 * @return string The fully qualified class name for the current environment.
	 */
	public static function get_class( $class_name ) {
		if ( ! isset( self::$class_cache[ $class_name ] ) ) {
			if ( self::is_scoped() ) {
				self::$class_cache[ $class_name ] = self::SCOPED_PREFIX . $class_name;
			} else {
				self::$class_cache[ $class_name ] = $class_name;
			}
		}
		return self::$class_cache[ $class_name ];
	}

	/**
	 * Check if a vendor class exists (in either scoped or non-scoped form).
	 *
	 * @param string $class_name The class name without scoped prefix.
	 * @return bool True if the class exists.
	 */
	public static function class_exists( $class_name ) {
		return class_exists( self::get_class( $class_name ) );
	}

	/**
	 * Create a new instance of a vendor class.
	 *
	 * @param string $class_name The class name without scoped prefix.
	 * @param array  $args       Constructor arguments.
	 * @return object|null The new instance or null if class doesn't exist.
	 */
	public static function create( $class_name, ...$args ) {
		$fqcn = self::get_class( $class_name );
		if ( ! class_exists( $fqcn ) ) {
			return null;
		}
		return new $fqcn( ...$args );
	}

	/**
	 * Get the Dompdf class instance.
	 *
	 * @param mixed ...$args Constructor arguments.
	 * @return \Dompdf\Dompdf|object|null The Dompdf instance.
	 */
	public static function dompdf( ...$args ) {
		return self::create( 'Dompdf\\Dompdf', ...$args );
	}

	/**
	 * Get Dompdf Options instance.
	 *
	 * @return \Dompdf\Options|object|null The Options instance.
	 */
	public static function dompdf_options() {
		return self::create( 'Dompdf\\Options' );
	}

	/**
	 * Check if Dompdf is available.
	 *
	 * @return bool True if Dompdf is available.
	 */
	public static function dompdf_available() {
		return self::class_exists( 'Dompdf\\Dompdf' );
	}

	/**
	 * Get the QR Code Builder class.
	 *
	 * @return string The fully qualified class name.
	 */
	public static function qr_builder_class() {
		return self::get_class( 'Endroid\\QrCode\\Builder\\Builder' );
	}

	/**
	 * Check if QR Code library is available.
	 *
	 * @return bool True if QR Code is available.
	 */
	public static function qr_available() {
		return self::class_exists( 'Endroid\\QrCode\\Builder\\Builder' );
	}

	/**
	 * Get QR Code related class names.
	 *
	 * @return array Array of fully qualified QR code class names.
	 */
	public static function qr_classes() {
		return array(
			'Builder'              => self::get_class( 'Endroid\\QrCode\\Builder\\Builder' ),
			'Encoding'             => self::get_class( 'Endroid\\QrCode\\Encoding\\Encoding' ),
			'ErrorCorrectionLevel' => self::get_class( 'Endroid\\QrCode\\ErrorCorrectionLevel' ),
			'RoundBlockSizeMode'   => self::get_class( 'Endroid\\QrCode\\RoundBlockSizeMode' ),
			'PngWriter'            => self::get_class( 'Endroid\\QrCode\\Writer\\PngWriter' ),
		);
	}

	/**
	 * Check if verifactu-php library is available.
	 *
	 * @return bool True if verifactu-php is available.
	 */
	public static function verifactu_available() {
		return self::class_exists( 'Josemmo\\Facturae\\Facturae' ) 
			|| class_exists( 'Josemmo\\Facturae\\Facturae' );
	}
}
