<?php
/**
 * Dependency injection container builder.
 *
 * @package Awesomemotive\Rewardswp\DependencyInjection
 * @since 1.0.0
 */

namespace Awesomemotive\Rewardswp\DependencyInjection;

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

use Awesomemotive\Rewardswp\DevTools\DependencyInjection\DevToolsDefinitions;
use Awesomemotive\Rewardswp\Interfaces\ContainerDefinitionsInterface;
use DI\Container;
use DI\ContainerBuilder;
use Exception;

class DIContainerBuilder {
	/**
	 * The container object.
	 *
	 * @since 1.0.0
	 * @var Container
	 */
	private Container $container;

	/**
	 * The class responsible for the container definitions.
	 *
	 * @since 1.0.0
	 *
	 * @var ContainerDefinitionsInterface|LiteDefinitions
	 */
	private ContainerDefinitionsInterface $container_definitions;

	/**
	 * Constructor.
	 *
	 * @since 1.0.0
	 * @throws Exception In case the container can't be built.
	 */
	public function __construct() {
		$definition_class            = $this->get_definition_class();
		$this->container_definitions = new $definition_class();

		$this->build_container();
	}

	/**
	 * Check if pro resources should be loaded.
	 *
	 * @since 1.0.0
	 *
	 * @return bool
	 */
	private function should_load_pro_resources(): bool {
		// If Pro folder doesn't exist, always return false (Lite install).
		if ( ! is_dir( AM_REWARDSWP_PLUGIN_DIR . '/src/Pro' ) ) {
			return false;
		}

		// In debug mode, allow override to simulate Lite behavior during development.
		if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
			// DevTools override via wp_option.
			$devtools_override = get_option( 'rewardswp_devtools_plan_override', '' );
			if ( 'lite' === $devtools_override ) {
				return false; // Force Lite behavior.
			}
		}

		// Default: Pro folder exists and no Lite override, load Pro resources.
		return true;
	}

	/**
	 * Get the class name for the container definitions.
	 *
	 * Priority: Pro > Lite
	 * DevTools is now handled via DevToolsTrait mixed into both classes.
	 *
	 * @since 1.0.0
	 *
	 * @return string The fully qualified class name.
	 * @throws Exception If no valid class is found.
	 */
	private function get_definition_class(): string {
		$should_load_pro = $this->should_load_pro_resources();

		if ( class_exists( ProDefinitions::class ) && $should_load_pro ) {
			return ProDefinitions::class;
		}

		if ( class_exists( LiteDefinitions::class ) && ! $should_load_pro ) {
			return LiteDefinitions::class;
		}

		throw new Exception(
			esc_html__( 'No valid definitions class found.', 'rewardswp' )
		);
	}

	/**
	 * Retrieve the built container.
	 *
	 * @since 1.0.0
	 * @return Container The DI container.
	 */
	public function get_container(): Container {
		return $this->container;
	}

	/**
	 * Check if DevTools should be loaded.
	 *
	 * @since 1.0.6
	 *
	 * @return bool
	 */
	private function should_load_devtools(): bool {
		// Only in debug mode.
		if ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) {
			return false;
		}

		// Check if DevTools folder exists.
		if ( ! is_dir( AM_REWARDSWP_PLUGIN_DIR . '/src/DevTools' ) ) {
			return false;
		}

		// Check if DevToolsDefinitions class exists.
		return class_exists( DevToolsDefinitions::class );
	}

	/**
	 * Build our container with our definitions.
	 *
	 * @since 1.0.0
	 * @return void
	 * @throws Exception If the container can't be built.
	 */
	private function build_container(): void {
		$builder = new ContainerBuilder();

		// Start with base definitions (Lite or Pro).
		$definitions = $this->container_definitions->get_definitions();

		// Merge DevTools definitions if available.
		if ( $this->should_load_devtools() ) {
			$devtools_definitions = new DevToolsDefinitions();
			$definitions          = array_merge_recursive( $definitions, $devtools_definitions->get_definitions() );
		}

		$builder->addDefinitions( $definitions );

		$this->container = $builder->build();
	}
}
