<?php

/**
 * The plugin bootstrap file
 *
 * This file is read by WordPress to generate the plugin information in the plugin
 * admin area. This file also includes all of the dependencies used by the plugin,
 * registers the activation and deactivation functions, and defines a function
 * that starts the plugin.
 *
 * @link              garidium.com
 * @since             1.0.0
 * @package           G_ffl_Cockpit
 *
 * @wordpress-plugin
 * Plugin Name:       g-FFL Cockpit
 * Plugin URI:        https://garidium.com/g-ffl-cockpit
 * Description:       g-FFL Cockpit
 * Version:           2.0.25
 * WC requires at least: 3.0.0
 * WC tested up to:   4.0
 * Author:            Garidium LLC
 * Author URI:        https://garidium.com
 * License:           GPL-3.0+
 * License URI:       http://www.gnu.org/licenses/gpl-2.0.txt
 * Text Domain:       g-ffl-cockpit
 * Domain Path:       /languages
 */

// If this file is called directly, abort.
if (!defined('WPINC')) {
    die;
}

if ( ! defined('ABSPATH')) exit;  // if direct access


// --- Dependency check (WooCommerce) ---
// Never die() in plugin bootstrap; it breaks multisite activation and wp-cli.
function g_ffl_cockpit_is_woocommerce_active(): bool {
    // If WooCommerce classes are already loaded, we're good
    if (class_exists('WooCommerce')) {
        return true;
    }

    // Fallback checks
    if (!function_exists('is_plugin_active')) {
        require_once ABSPATH . 'wp-admin/includes/plugin.php';
    }

    if (function_exists('is_plugin_active') && is_plugin_active('woocommerce/woocommerce.php')) {
        return true;
    }

    if (is_multisite() && function_exists('is_plugin_active_for_network')
        && is_plugin_active_for_network('woocommerce/woocommerce.php')) {
        return true;
    }

    return false;
}

if (!g_ffl_cockpit_is_woocommerce_active()) {
    add_action('admin_notices', function () {
        if (!current_user_can('activate_plugins')) return;
        echo '<div class="notice notice-error"><p><strong>g-FFL Cockpit</strong> requires WooCommerce to be installed and activated.</p></div>';
    });
    return; // important: do not load the rest of the plugin
}


/**
 * Currently plugin version.
 * Start at version 1.0.0 and use SemVer - https://semver.org
 * Rename this for your plugin and update it as you release new versions.
 */
define('G_FFL_COCKPIT_VERSION', '2.0.25');

/**
 * Conditional debug logging function
 * Only logs when WP_DEBUG is enabled
 */
if (!function_exists('g_ffl_debug_log')) {
    function g_ffl_debug_log($message, $level = 'info') {
        // Only log if debugging is enabled
        if (!defined('WP_DEBUG') || !WP_DEBUG) {
            return;
        }
        
        $prefix = '[G-FFL Cockpit]';
        $formatted_message = $prefix . ' [' . strtoupper($level) . '] ' . $message;
        
        if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) {
            // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Intentional debug logging when WP_DEBUG is enabled
            error_log($formatted_message);
        }
    }
}




/**
 * The code that runs during plugin activation.
 * This action is documented in includes/class-g-ffl-cockpit-activator.php
 */
function g_ffl_cockpit_activate($network_wide)
{
    require_once plugin_dir_path(__FILE__) . 'includes/class-g-ffl-cockpit-activator.php';

    if (is_multisite() && $network_wide) {
        foreach (get_sites(['fields' => 'ids']) as $blog_id) {
            switch_to_blog($blog_id);
            G_ffl_Cockpit_Activator::activate();
            restore_current_blog();
        }
    } else {
        G_ffl_Cockpit_Activator::activate();
    }
}


/**
 * The code that runs during plugin deactivation.
 * This action is documented in includes/class-g-ffl-cockpit-deactivator.php
 */
function g_ffl_cockpit_deactivate()
{
    require_once plugin_dir_path(__FILE__) . 'includes/class-g-ffl-cockpit-deactivator.php';
    G_ffl_Cockpit_Deactivator::deactivate();
}

register_activation_hook(__FILE__, 'g_ffl_cockpit_activate');
register_deactivation_hook(__FILE__, 'g_ffl_cockpit_deactivate');

/**
 * The core plugin class that is used to define internationalization,
 * admin-specific hooks, and public-facing site hooks.
 */
require plugin_dir_path(__FILE__) . 'includes/class-g-ffl-cockpit.php';
require plugin_dir_path(__FILE__) . 'includes/fulfillment_options.php';

// Get stuff setup for Onsite Synchronization
define('FFLC_PATH', plugin_dir_path(__FILE__));
require_once plugin_dir_path(__FILE__) . 'includes/class-sync-endpoint.php';
require_once plugin_dir_path(__FILE__) . 'includes/class-update-processor.php';
require_once plugin_dir_path(__FILE__) . 'includes/class-g-ffl-cockpit-cart.php';
add_action('rest_api_init', [ 'FFLCockpit_Sync_Endpoint', 'register_routes' ]);
add_action('rest_api_init', [ 'GFFLCockpit_Cart', 'register_routes' ]);

// Product deletion notification functionality
add_action('init', function() {
    static $deleted_products = [];
    
    // Capture product deletions
    add_action('before_delete_post', function($post_id) use (&$deleted_products) {
        if (get_post_type($post_id) !== 'product') return;
        
        // Only manual user actions - not API/scripts
        if (defined('REST_REQUEST') || wp_doing_cron() || defined('WP_CLI') || 
            (wp_doing_ajax() && !is_admin()) || !is_admin() || 
            (defined('G_FFL_COCKPIT_DOING_SYNC') && G_FFL_COCKPIT_DOING_SYNC)) {
            return;
        }
        
        // Check if product ID already exists in array
        $existing = array_filter($deleted_products, function($item) use ($post_id) {
            return $item['id'] === $post_id;
        });
        
        if (empty($existing)) {
            $deleted_products[] = ['id' => $post_id];
        }
    });
    
    add_action('wp_trash_post', function($post_id) use (&$deleted_products) {
        if (get_post_type($post_id) !== 'product') return;
        
        // Only manual user actions - not API/scripts  
        if (defined('REST_REQUEST') || wp_doing_cron() || defined('WP_CLI') || 
            (wp_doing_ajax() && !is_admin()) || !is_admin() || 
            (defined('G_FFL_COCKPIT_DOING_SYNC') && G_FFL_COCKPIT_DOING_SYNC)) {
            return;
        }
        
        // Check if product ID already exists in array
        $existing = array_filter($deleted_products, function($item) use ($post_id) {
            return $item['id'] === $post_id;
        });
        
        if (empty($existing)) {
            $deleted_products[] = ['id' => $post_id];
        }
    });
    
    // Send notification at end of request
    add_action('shutdown', function() use (&$deleted_products) {
        if (empty($deleted_products)) return;
        
        $api_key = get_option('g_ffl_cockpit_key');
        if (empty($api_key)) return;
      
        wp_remote_post('https://ffl-api.garidium.com', [
            'body' => json_encode([
                'action' => 'remove_products_from_mapping',
                'data' => [
                    'api_key' => $api_key,
                    'product_ids' => $deleted_products
                ]
            ]),
            'headers' => [
                'Content-Type' => 'application/json',
                'x-api-key' => $api_key,
                'Origin' => home_url()
            ],
            'timeout' => 15,
            'blocking' => false
        ]);
        
        $deleted_products = [];
    });
});


add_action( 'before_woocommerce_init', function() {
	if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
		\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true );
	}
} );

function g_ffl_cockpit_custom_seo_meta_tags() {

    if (is_admin() || is_network_admin()) {
        return;
    }

    // Early exit if not a product page
    if (!is_product()) {
        return;
    }
    
    // Check for other SEO plugins and exit if found
    $seo_plugins_active = array();
    
    // Check for popular SEO plugins
    if (defined('WPSEO_VERSION') || class_exists('WPSEO_Frontend')) {
        $seo_plugins_active[] = 'Yoast SEO';
    }
    
    if (defined('AIOSEO_VERSION') || class_exists('AIOSEO\\Plugin\\AIOSEO')) {
        $seo_plugins_active[] = 'All in One SEO';
    }
    
    if (defined('RANK_MATH_VERSION') || class_exists('RankMath')) {
        $seo_plugins_active[] = 'Rank Math';
    }
    
    if (class_exists('The_SEO_Framework_Load') || defined('THE_SEO_FRAMEWORK_VERSION')) {
        $seo_plugins_active[] = 'The SEO Framework';
    }
    
    if (class_exists('SEOPress_Options') || defined('SEOPRESS_VERSION')) {
        $seo_plugins_active[] = 'SEOPress';
    }
    
    if (defined('SEODASH_VERSION') || class_exists('SEODash')) {
        $seo_plugins_active[] = 'SEODash';
    }
    
    if (class_exists('WP_Schema_Pro') || defined('BSF_AIOSRS_VER')) {
        $seo_plugins_active[] = 'WP Schema Pro';
    }
    
    // If any SEO plugins are active, don't add our SEO data
    if (!empty($seo_plugins_active)) {
        echo "\n" . '<!-- Garidium FFL Cockpit SEO: Deferred to ' . esc_html(implode(', ', $seo_plugins_active)) . ' -->' . "\n";
        return;
    }
    
    try {
        global $post, $woocommerce;
        
        // Safety check for post object
        if (!$post || !isset($post->ID)) {
            return;
        }
        
        // Safety check for WooCommerce and product
        if (!function_exists('wc_get_product')) {
            return;
        }
        
        $product = wc_get_product($post->ID);
        if (!$product || !is_object($product)) {
            return;
        }
        
        // Meta Description - with error handling
        try {
            $meta_description = get_post_meta($post->ID, '_garidium_wpseo_metadesc', true);
            if ($meta_description && is_string($meta_description)) {
                echo "\n\n\n" . '<!-- Garidium FFL Cockpit SEO Start -->' . "\n";
                echo '<meta name="description" content="' . esc_attr($meta_description) . '">' . "\n";
            }else{
                return;
            }
        } catch (Exception $e) {
            g_ffl_debug_log('Meta Description Error: ' . $e->getMessage(), 'error');
        }
        
        // Open Graph Meta Tags - with error handling
        try {
            $product_title = method_exists($product, 'get_name') ? $product->get_name() : '';
            $product_description = '';
            if (method_exists($product, 'get_description')) {
                $product_description = wp_strip_all_tags($product->get_description() ?: $product->get_short_description());
            }
            $product_image = method_exists($product, 'get_image_id') ? wp_get_attachment_image_url($product->get_image_id(), 'large') : '';
            $product_price = method_exists($product, 'get_price') ? $product->get_price() : '';
            $product_url = get_permalink($product->get_id());
            
            if ($product_title) {
                // Open Graph Tags
                echo '<meta property="og:type" content="product">' . "\n";
                echo '<meta property="og:title" content="' . esc_attr($product_title) . '">' . "\n";
                if ($product_description) {
                    echo '<meta property="og:description" content="' . esc_attr(wp_trim_words($product_description, 30)) . '">' . "\n";
                }
                if ($product_url) {
                    echo '<meta property="og:url" content="' . esc_url($product_url) . '">' . "\n";
                }
                
                if ($product_image) {
                    echo '<meta property="og:image" content="' . esc_url($product_image) . '">' . "\n";
                    echo '<meta property="og:image:width" content="800">' . "\n";
                    echo '<meta property="og:image:height" content="600">' . "\n";
                }
                
                if ($product_price && function_exists('get_woocommerce_currency')) {
                    echo '<meta property="product:price:amount" content="' . esc_attr($product_price) . '">' . "\n";
                    echo '<meta property="product:price:currency" content="' . esc_attr(get_woocommerce_currency()) . '">' . "\n";
                }
                
                // Twitter Card
                echo '<meta name="twitter:card" content="summary_large_image">' . "\n";
                echo '<meta name="twitter:title" content="' . esc_attr($product_title) . '">' . "\n";
                if ($product_description) {
                    echo '<meta name="twitter:description" content="' . esc_attr(wp_trim_words($product_description, 30)) . '">' . "\n";
                }
                if ($product_image) {
                    echo '<meta name="twitter:image" content="' . esc_url($product_image) . '">' . "\n";
                }
            }
        } catch (Exception $e) {
            g_ffl_debug_log('Open Graph/Twitter Error: ' . $e->getMessage(), 'error');
        }
        
        // Product attributes and meta - with error handling
        try {
            $sku = method_exists($product, 'get_sku') ? $product->get_sku() : '';
            $upc = '';
            $manufacturer = '';
            $mpn = '';
            $brand = '';
            
            // Safely get product attributes
            if (method_exists($product, 'get_attribute')) {
                $upc = $product->get_attribute('upc') ?: $product->get_attribute('UPC') ?: get_post_meta($post->ID, '_upc', true);
                $manufacturer = $product->get_attribute('manufacturer') ?: $product->get_attribute('Manufacturer') ?: get_post_meta($post->ID, '_manufacturer', true);
                $mpn = $product->get_attribute('manufacturer-part-number') ?: $product->get_attribute('mpn') ?: $product->get_attribute('MPN') ?: get_post_meta($post->ID, '_mpn', true);
            }
            
            $brand = $manufacturer ?: (get_post_meta($post->ID, '_garidium_brand', true) ?: get_post_meta($post->ID, 'brand', true));
            $categories = function_exists('wp_get_post_terms') ? wp_get_post_terms($post->ID, 'product_cat', array('fields' => 'names')) : array();
            
            // Use UPC as primary identifier, fallback to SKU
            $primary_id = $upc ?: $sku;
            if ($primary_id) {
                echo '<meta name="product:retailer_item_id" content="' . esc_attr($primary_id) . '">' . "\n";
            }
            
            // Add UPC specifically for e-commerce
            if ($upc) {
                echo '<meta name="product:upc" content="' . esc_attr($upc) . '">' . "\n";
                echo '<meta name="product:gtin" content="' . esc_attr($upc) . '">' . "\n"; // Global Trade Item Number
            }
            
            // Add Manufacturer Part Number
            if ($mpn) {
                echo '<meta name="product:mpn" content="' . esc_attr($mpn) . '">' . "\n";
            }
            
            // Add Manufacturer/Brand
            if ($manufacturer) {
                echo '<meta name="product:brand" content="' . esc_attr($manufacturer) . '">' . "\n";
                echo '<meta name="product:manufacturer" content="' . esc_attr($manufacturer) . '">' . "\n";
            } elseif ($brand) {
                echo '<meta name="product:brand" content="' . esc_attr($brand) . '">' . "\n";
            }
            
            if (!empty($categories) && is_array($categories)) {
                echo '<meta name="product:category" content="' . esc_attr(implode(', ', $categories)) . '">' . "\n";
            }
            
            // Availability
            if (method_exists($product, 'is_in_stock')) {
                $availability = $product->is_in_stock() ? 'in stock' : 'out of stock';
                echo '<meta name="product:availability" content="' . esc_attr($availability) . '">' . "\n";
            }
        } catch (Exception $e) {
            g_ffl_debug_log('Product Attributes Error: ' . $e->getMessage(), 'error');
        }
        
        // JSON-LD Schema - with error handling
        try {
            $json_ld = get_post_meta($post->ID, '_garidium_wpseo_json_ld', true);
            if (is_string($json_ld) && !empty($json_ld)) {
                echo '<script type="application/ld+json" class="garidium-seo-schema">' . wp_kses_post(html_entity_decode($json_ld)) . '</script>' . "\n";
            } elseif (is_array($json_ld) && !empty($json_ld)) {
                $json_ld_string = implode('', $json_ld);
                if (!empty($json_ld_string)) {
                    echo '<script type="application/ld+json" class="garidium-seo-schema">' . wp_kses_post(html_entity_decode($json_ld_string)) . '</script>' . "\n";
                }
            } else {
                // Generate basic Product schema if none exists
                $schema = array(
                    '@context' => 'https://schema.org/',
                    '@type' => 'Product',
                    'name' => $product_title ?: 'Product',
                    'url' => $product_url ?: ''
                );
                
                if (!empty($product_description)) {
                    $schema['description'] = wp_trim_words($product_description, 50);
                }
                
                // Add identifiers in order of preference
                if (!empty($upc)) {
                    $schema['gtin'] = $upc;
                    $schema['gtin12'] = $upc; // UPC is typically GTIN-12
                }
                
                if (!empty($mpn)) {
                    $schema['mpn'] = $mpn;
                }
                
                if (!empty($sku)) {
                    $schema['sku'] = $sku;
                }
                
                if (!empty($product_image)) {
                    $schema['image'] = $product_image;
                }
                
                if (!empty($manufacturer)) {
                    $schema['brand'] = array('@type' => 'Brand', 'name' => $manufacturer);
                    $schema['manufacturer'] = array('@type' => 'Organization', 'name' => $manufacturer);
                } elseif (!empty($brand)) {
                    $schema['brand'] = array('@type' => 'Brand', 'name' => $brand);
                }
                
                if (!empty($categories) && is_array($categories)) {
                    $schema['category'] = implode(', ', $categories);
                }
                
                if (!empty($product_price) && method_exists($product, 'is_in_stock') && $product->is_in_stock() && function_exists('get_woocommerce_currency')) {
                    $schema['offers'] = array(
                        '@type' => 'Offer',
                        'price' => $product_price,
                        'priceCurrency' => get_woocommerce_currency(),
                        'availability' => 'https://schema.org/InStock',
                        'url' => $product_url ?: ''
                    );
                }
                
                if (function_exists('wp_json_encode')) {
                    echo '<script type="application/ld+json" class="garidium-seo-schema-generated">' . wp_json_encode($schema, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . '</script>' . "\n";
                }
            }
        } catch (Exception $e) {
            g_ffl_debug_log('JSON-LD Schema Error: ' . $e->getMessage(), 'error');
        }
        
        echo '<!-- Garidium FFL Cockpit SEO End -->' . "\n\n\n";
        
    } catch (Exception $e) {
        // Log the error but don't break the page
        g_ffl_debug_log('SEO Critical Error: ' . $e->getMessage(), 'error');
        echo '<!-- Garidium FFL Cockpit SEO Error: See error log -->' . "\n";
    }
}

// add the SEO section
add_action('wp_head', 'g_ffl_cockpit_custom_seo_meta_tags');


// Allow extra HTML ONLY for product content (admin product screens,
// front-end single product, and WooCommerce product REST updates).
add_filter('wp_kses_allowed_html', function ($tags, $context) {
    // Only care about post content contexts
    if ($context !== 'post') {
        return $tags;
    }

    $apply = false;

    // 1) Admin: only when editing/creating PRODUCTS
    if (is_admin() && function_exists('get_current_screen')) {
        $s = get_current_screen();
        if ($s && ($s->post_type === 'product' || $s->id === 'product' || $s->id === 'edit-product')) {
            $apply = true;
        }
    }

    // 2) Front-end: only on single PRODUCT
    if (!$apply && function_exists('is_singular') && is_singular('product')) {
        $apply = true;
    }

    // 3) REST: only for WooCommerce/WP product endpoints
    if (!$apply && defined('REST_REQUEST') && REST_REQUEST) {
        $uri = isset($_SERVER['REQUEST_URI']) ? esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'])) : '';
        // WooCommerce products endpoints (e.g., /wp-json/wc/v3/products/...)
        if (strpos($uri, '/wp-json/wc/') !== false && strpos($uri, '/products') !== false) {
            $apply = true;
        }
        // WP core products endpoint (some setups expose wp/v2/product)
        if (strpos($uri, '/wp-json/wp/v2/product') !== false) {
            $apply = true;
        }
    }

    if (!$apply) {
        return $tags; // do nothing outside product contexts
    }

    // Allow the bits you need for product descriptions
    $tags['iframe'] = array_merge($tags['iframe'] ?? [], [
        'src'             => true,
        'height'          => true,
        'width'           => true,
        'frameborder'     => true,
        'allowfullscreen' => true,
        'allow'           => true,
        'style'           => true,
        'title'           => true,
        'referrerpolicy'  => true,
        // optional but common:
        'loading'         => true,
        'sandbox'         => true,
    ]);

    $tags['div'] = array_merge($tags['div'] ?? [], [
        'id'    => true,
        'class' => true,
        'style' => true,
    ]);

    // These just need to exist to be permitted
    $tags['b']  = $tags['b']  ?? [];
    $tags['br'] = $tags['br'] ?? [];

    return $tags;
}, 10, 2);
// Make Caliber/Gauge attribute taxonomy public and add URL rewriting
/*
add_filter('woocommerce_taxonomy_args_pa_caliber-gauge', function($args) {
    $args['public'] = true;
    $args['publicly_queryable'] = true;
    $args['show_ui'] = true;
    $args['show_admin_column'] = true;
    $args['show_in_nav_menus'] = true;
    $args['show_in_rest'] = true;
    $args['query_var'] = 'caliber';
    $args['rewrite'] = [
        'slug' => 'caliber',
        'with_front' => false,
        'hierarchical' => true,
        'ep_mask' => EP_NONE,
    ];
    
    return $args;
}, 10, 1);
*/

// Add CSS for YouTube video grid
add_action('wp_head', 'g_ffl_cockpit_youtube_video_grid_styles');
function g_ffl_cockpit_youtube_video_grid_styles() {
    if (is_product()) {
        echo '<style>
        .youtube-video-grid {
            display: flex !important;
            flex-wrap: wrap !important;
            justify-content: center !important;
            gap: 20px !important;
            max-width: 100% !important;
            margin: 20px 0 !important;
        }
        .youtube-video-item {
            flex: 0 0 calc(50% - 10px) !important;
            min-width: 398px !important;
            max-width: 224px !important;
            margin-bottom: 20px !important;
        }
        .youtube-video-item iframe {
            width: 100% !important;
            height: 224px !important; 
            border: none !important;
            display: block !important;
        }
        @media (max-width: 768px) {
            .youtube-video-grid {
                justify-content: center !important;
            }
            .youtube-video-item {
                flex: 0 0 100% !important;
                max-width: 400px !important;
            }
        }
        </style>';
    }
}

/**
 * Determine if the current site is an fflcockpit.com multisite subdomain
 */
function g_ffl_is_fflcockpit_multisite_domain(): bool {

    if (!is_multisite()) {
        return false;
    }

    $host = wp_parse_url(home_url(), PHP_URL_HOST);
    if (!$host) {
        return false;
    }

    // Normalize
    $host = strtolower($host);

    // Exact match OR subdomain of fflcockpit.com
    return (
        $host === 'fflcockpit.com' ||
        str_ends_with($host, '.fflcockpit.com')
    );
}

add_filter('login_redirect', function ($redirect_to, $requested_redirect_to, $user) {

    if (!($user instanceof WP_User)) {
        return $redirect_to;
    }

    // HARD SAFETY GATES
    if (!g_ffl_is_fflcockpit_multisite_domain()) {
        return $redirect_to;
    }

    if (is_super_admin($user->ID)) {
        return $redirect_to;
    }

    if (!user_can($user, 'manage_woocommerce')) {
        return $redirect_to;
    }

    return admin_url();

}, 10, 3);

/**
 * Force Cockpit as the landing page for multisite subdomains
 * when users hit the site root or front-end.
 */
add_action('template_redirect', function () {

    // Only on multisite + fflcockpit domains
    if (!g_ffl_is_fflcockpit_multisite_domain()) {
        return;
    }

    // Never interfere with admin, network admin, REST, cron, CLI
    if (
        is_admin() ||
        is_network_admin() ||
        defined('REST_REQUEST') ||
        wp_doing_cron() ||
        defined('WP_CLI')
    ) {
        return;
    }

    // Not logged in → send to login
    if (!is_user_logged_in()) {
        wp_safe_redirect(wp_login_url());
        exit;
    }

    $user = wp_get_current_user();

    // Super admins keep normal behavior
    if (is_super_admin($user->ID)) {
        return;
    }

    // Only redirect dealers / cockpit users
    if (!user_can($user, 'manage_woocommerce')) {
        return;
    }

    // If already on Cockpit page, do nothing
    if (
        isset($_GET['page']) &&
        $_GET['page'] === 'ffl-cockpit'
    ) {
        return;
    }

    // Redirect EVERYTHING else to Cockpit
    wp_safe_redirect(admin_url());
    exit;
});


/**
 * Begins execution of the plugin.
 *
 * Since everything within the plugin is registered via hooks,
 * then kicking off the plugin from this point in the file does
 * not affect the page life cycle.
 *
 * @since    1.0.0
 */
function g_ffl_cockpit_run()
{
    $plugin = new G_Ffl_Cockpit();
    $plugin->run();
}

add_action('plugins_loaded', function () {
    // Only run after all plugins are loaded (esp WooCommerce)
    if (!g_ffl_cockpit_is_woocommerce_active()) {
        return;
    }
    g_ffl_cockpit_run();
});

