<?php
/**
 * Factory Class
 *
 * Centralizes instantiation logic for generator and environment implementations.
 *
 * @package Freefactu
 * @since 0.5.0
 */

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

/**
 * Class Freefactu_Factory
 *
 * Factory for creating Generator and Environment implementations.
 */
class Freefactu_Factory {

	/**
	 * Cached environment instance.
	 *
	 * @var Freefactu_Environment_Interface|null
	 */
	private static $environment_instance = null;

	/**
	 * Create the Generator implementation.
	 *
	 * What this function does:
	 * - Creates a Standalone_Generator instance using DOMPDF
	 * - Injects environment dependency into generator
	 *
	 * Where it's called from:
	 * - freefactu.php: __construct() method to create generator instance
	 * - class-freefactu-client.php: save_pdf_snapshot_by_id() for deleted orders
	 * - class-freefactu-snapshot-utility.php: create_snapshot_for_order() method
	 * - class-freefactu-snapshot-utility.php: verify_snapshot() method
	 *
	 * @param WC_Order|int|null $order Optional order.
	 * @return Freefactu_Generator_Interface Generator instance.
	 */
	public static function create_generator( $order = null ) {
		// Load base generator class if not already loaded
		if ( ! class_exists( 'Freefactu_Base_Generator' ) ) {
			require_once FREEFACTU_PLUGIN_DIR . 'includes/abstracts/abstract-base-generator.php';
		}

		// Get environment instance to inject into generator
		$environment = self::create_environment();

		// Standalone mode: Use DOMPDF for PDF generation
		if ( ! class_exists( 'Freefactu_Standalone_Generator' ) ) {
			require_once FREEFACTU_PLUGIN_DIR . 'includes/generators/standalone/class-standalone-generator.php';
		}

		return new Freefactu_Standalone_Generator( $order, $environment );
	}

	/**
	 * Create the appropriate Environment implementation.
	 *
	 * What this function does:
	 * - Reads environment setting from plugin options (production or test)
	 * - Creates appropriate environment instance (Production_Environment or Test_Environment)
	 * - Caches the instance to avoid repeated instantiation (singleton pattern)
	 *
	 * Where it's called from:
	 * - freefactu.php: __construct() method to create environment instance
	 * - class-freefactu-factory.php: create_generator() method to inject into generator
	 * - class-freefactu-client.php: save_pdf_snapshot_by_id() for deleted orders
	 *
	 * @return Freefactu_Environment_Interface Environment instance.
	 */
	public static function create_environment() {
		// Return cached instance if available (singleton pattern)
		if ( null !== self::$environment_instance ) {
			return self::$environment_instance;
		}

		// Read environment setting from plugin options
		$environment = self::get_environment();

		if ( $environment === 'production' ) {
			// Production environment: Use live AEAT endpoints
			if ( ! class_exists( 'Freefactu_Production_Environment' ) ) {
				require_once FREEFACTU_PLUGIN_DIR . 'includes/api/environments/class-production-environment.php';
			}

			self::$environment_instance = new Freefactu_Production_Environment();
		} else {
			// Test environment (default): Use AEAT test endpoints
			if ( ! class_exists( 'Freefactu_Test_Environment' ) ) {
				require_once FREEFACTU_PLUGIN_DIR . 'includes/api/environments/class-test-environment.php';
			}

			self::$environment_instance = new Freefactu_Test_Environment();
		}

		return self::$environment_instance;
	}

	/**
	 * Get the current environment.
	 *
	 * What this function does:
	 * - Reads environment setting from plugin options
	 * - Validates the value (must be 'production' or 'test')
	 * - Defaults to 'test' if not set or invalid
	 *
	 * Where it's called from:
	 * - class-freefactu-factory.php: create_environment() method
	 *
	 * @return string 'production' or 'test'.
	 */
	public static function get_environment() {
		$options = get_option( 'freefactu_settings', array() );
		$environment = isset( $options['environment'] ) ? $options['environment'] : 'test';

		// Validate environment value
		if ( ! in_array( $environment, array( 'production', 'test' ), true ) ) {
			$environment = 'test';
		}

		return $environment;
	}

	/**
	 * Reset cached instances.
	 *
	 * What this function does:
	 * - Clears cached environment instance
	 * - Forces re-instantiation on next create_environment() call
	 * - Useful for testing purposes
	 *
	 * Where it's called from:
	 * - Testing code (not used in production)
	 *
	 * @return void
	 */
	public static function reset() {
		self::$environment_instance = null;
	}
}
