<?php
/**
 * Sifency AI — Dynamic Loader
 *
 * Hooks into the existing Sifency Addons filter system to load
 * AI-generated widgets, CPTs, and other items at runtime.
 *
 * @package Sifency_Addons
 * @since   1.0.5
 */

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

class Sifency_Addons_AI_Loader {

	/*
	 ------------------------------------------------------------------ */
	/*
	  Singleton                                                           */
	/* ------------------------------------------------------------------ */

	private static ?self $instance = null;

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

	/*
	 ------------------------------------------------------------------ */
	/*
	  Bootstrap                                                           */
	/* ------------------------------------------------------------------ */

	private function __construct() {
		// Register the Sifency AI Elementor widget category.
		add_action( 'elementor/elements/categories_registered', array( $this, 'register_ai_category' ) );

		// Register AI widgets directly with Elementor (more reliable than filter injection).
		add_action( 'elementor/widgets/register', array( $this, 'register_ai_widgets' ), 15 );

		// Load CPTs as early as possible so post types are available.
		add_action( 'init', array( $this, 'load_cpts' ), 5 );

		// Load any other AI-generated items (builder items, metaboxes…)
		add_action( 'init', array( $this, 'load_misc_items' ), 10 );
	}

	/*
	 ------------------------------------------------------------------ */
	/*
	  Elementor Category                                                  */
	/* ------------------------------------------------------------------ */

	/**
	 * Register the "Sifency AI" category in Elementor's widget panel.
	 *
	 * @param \Elementor\Elements_Manager $elements_manager
	 */
	public function register_ai_category( $elements_manager ): void {
		$elements_manager->add_category(
			'sifency-ai-widgets',
			array(
				'title' => esc_html__( '✨ Sifency AI', 'sifency-addons' ),
				'icon'  => 'eicon-ai',
			)
		);
	}

	/*
	 ------------------------------------------------------------------ */
	/*
	  Direct Elementor Widget Registration                                */
	/* ------------------------------------------------------------------ */

	/**
	 * Directly register all enabled AI-generated widgets with Elementor.
	 *
	 * Bypasses the sifency_addons_widget_list filter to avoid dependency on
	 * the plugin's registry format and atomic widget system.
	 *
	 * @param \Elementor\Widgets_Manager $widgets_manager
	 */
	public function register_ai_widgets( $widgets_manager ): void {
		$items = Sifency_Addons_AI_File_Writer::list_items( 'widgets' );

		foreach ( $items as $item ) {
			if ( ! $item['enabled'] ) {
				continue;
			}

			$filepath = Sifency_Addons_AI_Module::base_dir() . 'widgets/' . $item['filename'];

			if ( ! file_exists( $filepath ) ) {
				continue;
			}

			// Derive the class name from the slug.
			$class_name = $this->slug_to_widget_class( $item['slug'] );

			// Only require & register if the class doesn't exist yet.
			// Only require & register if the class doesn't exist yet.
			if ( ! class_exists( $class_name ) ) {
				try {
					// phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingVariable
					require_once $filepath;
				} catch ( \Throwable $e ) {
					if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
						// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
						error_log( 'Sifency AI: Failed to load widget file ' . $filepath . ': ' . $e->getMessage() );
					}
					continue;
				}
			}

			if ( class_exists( $class_name ) ) {
				try {
					$widgets_manager->register( new $class_name() );
				} catch ( \Throwable $e ) {
					// Silently skip broken AI-generated widgets rather than crashing.
					if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
						// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
						error_log( 'Sifency AI: Failed to register widget ' . $class_name . ': ' . $e->getMessage() );
					}
				}
			}
		}
	}

	/*
	 ------------------------------------------------------------------ */
	/*
	  CPT Loading                                                         */
	/* ------------------------------------------------------------------ */

	public function load_cpts(): void {
		$this->load_type( 'cpts' );
	}

	/*
	 ------------------------------------------------------------------ */
	/*
	  Misc (builder items, metaboxes, menus, pages)                      */
	/* ------------------------------------------------------------------ */

	public function load_misc_items(): void {
		foreach ( array( 'builder-items', 'metaboxes', 'menus', 'pages' ) as $type ) {
			$this->load_type( $type );
		}
	}

	/*
	 ------------------------------------------------------------------ */
	/*
	  Generic File Loader                                                 */
	/* ------------------------------------------------------------------ */

	/**
	 * Require all enabled PHP files for a given type.
	 */
	private function load_type( string $type ): void {
		$items = Sifency_Addons_AI_File_Writer::list_items( $type );

		foreach ( $items as $item ) {
			if ( ! $item['enabled'] ) {
				continue;
			}

			$filepath = Sifency_Addons_AI_Module::base_dir() . $type . '/' . $item['filename'];

			if ( file_exists( $filepath ) ) {
				try {
					// phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingVariable
					require_once $filepath;
				} catch ( \Throwable $e ) {
					// Silently catch and log parse/runtime errors to avoid white screens
					if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
						// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
						error_log( 'Sifency AI: Failed to load ' . $type . ' file ' . $filepath . ': ' . $e->getMessage() );
					}
				}
			}
		}
	}

	/*
	 ------------------------------------------------------------------ */
	/*
	  Helpers                                                             */
	/* ------------------------------------------------------------------ */

	/**
	 * Convert a kebab-case slug to the expected widget class name.
	 *
	 * Examples:
	 *   "my-card-widget"  → "Sifency_Addons_AI_My_Card_Widget_Widget"
	 *   "sifency-ai-hero" → "Sifency_Addons_AI_Hero_Widget"
	 */
	private function slug_to_widget_class( string $slug ): string {
		// Strip the leading "sifency-ai-" prefix that the generator may add.
		$slug = preg_replace( '/^sifency-ai-/', '', $slug );

		$parts  = explode( '-', $slug );
		$pascal = implode( '_', array_map( 'ucfirst', $parts ) );

		return 'Sifency_Addons_AI_' . $pascal . '_Widget';
	}
}

// Self-boot: the loader is registered as soon as this file is included
// (which happens inside Sifency_Addons_AI_Module::load_dependencies()).
Sifency_Addons_AI_Loader::instance();
