<?php
/**
 * Freefactu Extension Loader
 *
 * Handles automatic loading of active extensions from the extensions directory.
 *
 * @package Freefactu
 * @since 1.2.0
 */

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

/**
 * Class Freefactu_Extension_Loader
 *
 * Responsible for:
 * - Discovering extensions in the extensions directory
 * - Loading active extensions
 * - Providing hooks for extension initialization
 *
 * @since 1.2.0
 */
class Freefactu_Extension_Loader {

    /**
     * The single instance of this class.
     *
     * @var Freefactu_Extension_Loader|null
     */
    private static $instance = null;

    /**
     * Extension directory path.
     *
     * @var string
     */
    private $extensions_dir;

    /**
     * Loaded extensions.
     *
     * @var array
     */
    private $loaded_extensions = array();

    /**
     * Get the singleton instance.
     *
     * @return Freefactu_Extension_Loader
     */
    public static function instance() {
        if ( null === self::$instance ) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Constructor.
     */
    private function __construct() {
        $this->extensions_dir = FREEFACTU_PLUGIN_DIR . 'extensions/';
        $this->init();
    }

    /**
     * Initialize the loader.
     */
    private function init() {
        // Load extensions after plugins_loaded to ensure all dependencies are available
        add_action( 'plugins_loaded', array( $this, 'load_active_extensions' ), 15 );
        
        // Hook for extension activation/deactivation
        add_action( 'freefactu_extension_activated', array( $this, 'on_extension_activated' ), 10, 2 );
        add_action( 'freefactu_extension_deactivated', array( $this, 'on_extension_deactivated' ), 10, 2 );
    }

    /**
     * Load all active extensions.
     */
    public function load_active_extensions() {
        // Get list of active extensions from options
        $active_extensions = get_option( 'freefactu_active_extensions', array() );

        if ( empty( $active_extensions ) || ! is_array( $active_extensions ) ) {
            return;
        }

        // Get extension definitions
        $extensions = $this->get_extension_definitions();

        foreach ( $active_extensions as $extension_id ) {
            if ( isset( $extensions[ $extension_id ] ) ) {
                $this->load_extension( $extension_id, $extensions[ $extension_id ] );
            }
        }

        /**
         * Fires after all active extensions have been loaded.
         *
         * @since 1.2.0
         * @param array $loaded_extensions Array of loaded extension IDs.
         */
        do_action( 'freefactu_extensions_loaded', $this->loaded_extensions );
    }

    /**
     * Get extension definitions with file paths.
     *
     * @return array Extension definitions keyed by ID.
     */
    private function get_extension_definitions() {
        // Map of extension IDs to their main file
        $extensions = array(
            'adjuntar-factura-correo' => array(
                'folder' => 'adjuntar-factura-correo',
                'file'   => 'class-freefactu-email-attachment.php',
                'class'  => 'Freefactu_Email_Attachment',
            ),
            'presupuestos' => array(
                'folder' => 'presupuestos',
                'file'   => 'class-freefactu-presupuestos.php',
                'class'  => 'Freefactu_Presupuestos',
            ),
        );

        /**
         * Filter extension definitions.
         *
         * Allows third-party extensions to register themselves.
         *
         * @since 1.2.0
         * @param array $extensions Extension definitions.
         */
        return apply_filters( 'freefactu_extension_definitions', $extensions );
    }

    /**
     * Load a single extension.
     *
     * @param string $extension_id Extension identifier.
     * @param array  $definition   Extension definition with folder, file, and class.
     * @return bool True if loaded successfully.
     */
    private function load_extension( $extension_id, $definition ) {
        $file_path = $this->extensions_dir . $definition['folder'] . '/' . $definition['file'];

        if ( ! file_exists( $file_path ) ) {
            return false;
        }

        // Check if extension folder exists (for standalone detection)
        $folder_path = $this->extensions_dir . $definition['folder'];
        if ( ! is_dir( $folder_path ) ) {
            return false;
        }

        // Load the extension file
        require_once $file_path;

        $this->loaded_extensions[] = $extension_id;

        /**
         * Fires after a specific extension is loaded.
         *
         * @since 1.2.0
         * @param string $extension_id Extension identifier.
         * @param array  $definition   Extension definition.
         */
        do_action( "freefactu_extension_loaded_{$extension_id}", $definition );

        return true;
    }

    /**
     * Callback when an extension is activated.
     *
     * @param string $extension_id Extension identifier.
     * @param array  $extension    Extension data.
     */
    public function on_extension_activated( $extension_id, $extension ) {
        // Attempt to load the extension immediately if not already loaded
        if ( ! in_array( $extension_id, $this->loaded_extensions, true ) ) {
            $definitions = $this->get_extension_definitions();
            if ( isset( $definitions[ $extension_id ] ) ) {
                $this->load_extension( $extension_id, $definitions[ $extension_id ] );
            }
        }

        /**
         * Fires when an extension is being initialized after activation.
         *
         * @since 1.2.0
         * @param string $extension_id Extension identifier.
         */
        do_action( "freefactu_extension_init_{$extension_id}" );
    }

    /**
     * Callback when an extension is deactivated.
     *
     * @param string $extension_id Extension identifier.
     * @param array  $extension    Extension data.
     */
    public function on_extension_deactivated( $extension_id, $extension ) {
        // Remove from loaded extensions
        $key = array_search( $extension_id, $this->loaded_extensions, true );
        if ( false !== $key ) {
            unset( $this->loaded_extensions[ $key ] );
            $this->loaded_extensions = array_values( $this->loaded_extensions );
        }

        /**
         * Fires when an extension is being cleaned up after deactivation.
         *
         * Extensions can use this hook to clean up options, transients, etc.
         *
         * @since 1.2.0
         * @param string $extension_id Extension identifier.
         */
        do_action( "freefactu_extension_cleanup_{$extension_id}" );
    }

    /**
     * Check if an extension is loaded.
     *
     * @param string $extension_id Extension identifier.
     * @return bool True if extension is loaded.
     */
    public function is_extension_loaded( $extension_id ) {
        return in_array( $extension_id, $this->loaded_extensions, true );
    }

    /**
     * Get list of loaded extensions.
     *
     * @return array Array of loaded extension IDs.
     */
    public function get_loaded_extensions() {
        return $this->loaded_extensions;
    }

    /**
     * Check if extension folder exists (standalone check).
     *
     * If the folder doesn't exist, the extension is considered removed.
     *
     * @param string $extension_id Extension identifier.
     * @return bool True if extension folder exists.
     */
    public function extension_folder_exists( $extension_id ) {
        $definitions = $this->get_extension_definitions();
        
        if ( ! isset( $definitions[ $extension_id ] ) ) {
            return false;
        }

        $folder_path = $this->extensions_dir . $definitions[ $extension_id ]['folder'];
        return is_dir( $folder_path );
    }
}

// Initialize the extension loader
Freefactu_Extension_Loader::instance();
