<?php

/**
 * Freemius SDK integration: licensing, premium-build gating, and uninstall
 * cleanup (via the SDK's after_uninstall hook).
 *
 * Credentials come from the Freemius dashboard (product Settings -> API & Keys).
 * The public key is shippable by design; the secret key must never appear here.
 * Both constants can be overridden in wp-config.php (e.g. for a staging product).
 *
 * @package WooEquipmentRental
 */
declare (strict_types = 1);
if ( !defined( 'ABSPATH' ) ) {
    exit;
}
if ( !defined( 'WCRENT_FS_PRODUCT_ID' ) ) {
    define( 'WCRENT_FS_PRODUCT_ID', 35057 );
}
if ( !defined( 'WCRENT_FS_PUBLIC_KEY' ) ) {
    define( 'WCRENT_FS_PUBLIC_KEY', 'pk_3419d348dc41930cce041b12054a7' );
}
/**
 * Class WCRent_Freemius
 */
class WCRent_Freemius {
    /**
     * SDK instance, or null when the SDK is not configured/available.
     *
     * @var \Freemius|null
     */
    private static $instance = null;

    /**
     * Initialises the Freemius SDK and registers the uninstall cleanup.
     *
     * Degrades gracefully to free mode when the SDK is not configured (no
     * product keys yet) or vendor/ is missing (a git clone without
     * `composer install`); every shipped build includes vendor/.
     */
    public static function init() : void {
        if ( null !== self::$instance ) {
            return;
        }
        if ( !WCRENT_FS_PRODUCT_ID || '' === WCRENT_FS_PUBLIC_KEY ) {
            self::register_fallback_uninstall_hook();
            return;
        }
        if ( !function_exists( 'fs_dynamic_init' ) ) {
            // The SDK is bundled as a Composer dependency (vendor/), which
            // WordPress.org's uploader recognises as third-party code and exempts
            // from the plugin-updater check, unlike a top-level freemius/ directory.
            $sdk = WCRENT_PLUGIN_DIR . 'vendor/freemius/wordpress-sdk/start.php';
            if ( !file_exists( $sdk ) ) {
                self::register_fallback_uninstall_hook();
                return;
            }
            require_once $sdk;
        }
        // start.php returns without declaring fs_dynamic_init() on several paths
        // (another plugin's SDK copy already loaded, a newer SDK elsewhere takes
        // over, or it is loaded before WordPress is ready). Calling it blind would
        // be a fatal, so fall back to free mode instead.
        if ( !function_exists( 'fs_dynamic_init' ) ) {
            self::register_fallback_uninstall_hook();
            return;
        }
        self::$instance = fs_dynamic_init( array(
            'id'               => (string) WCRENT_FS_PRODUCT_ID,
            'slug'             => 'harbor-equipment-rental-for-woocommerce',
            'premium_slug'     => 'harbor-equipment-rental-for-woocommerce-premium',
            'type'             => 'plugin',
            'public_key'       => WCRENT_FS_PUBLIC_KEY,
            'is_premium'       => false,
            'premium_suffix'   => 'Pro',
            'has_paid_plans'   => true,
            'has_addons'       => false,
            'is_live'          => true,
            'menu'             => array(
                'first-path' => 'plugins.php',
                'support'    => false,
            ),
            'is_org_compliant' => true,
        ) );
        // WP runs uninstall.php INSTEAD of registered uninstall hooks when that
        // file exists, which would skip the SDK's own cleanup — so uninstall
        // lives here on the SDK hook, not in an uninstall.php.
        self::$instance->add_action( 'after_uninstall', array(self::class, 'uninstall_cleanup') );
        do_action( 'wcrent_fs_loaded' );
    }

    /**
     * Returns the SDK instance, or null when running without Freemius.
     *
     * @return \Freemius|null
     */
    public static function instance() {
        return self::$instance;
    }

    /**
     * Registers the plain WordPress uninstall hook for installs running
     * without the SDK, so plugin data is still cleaned up on delete.
     */
    private static function register_fallback_uninstall_hook() : void {
        register_uninstall_hook( WCRENT_PLUGIN_FILE, array(self::class, 'uninstall_cleanup') );
    }

    // -----------------------------------------------------------------------
    // Uninstall cleanup
    // -----------------------------------------------------------------------
    /**
     * Removes all plugin data when the plugin is deleted.
     *
     * Runs via the SDK's after_uninstall hook (or the fallback uninstall hook).
     * WordPress invokes this exactly once for the whole network, so on
     * multisite every site is cleaned.
     */
    public static function uninstall_cleanup() : void {
        if ( is_multisite() ) {
            $wcrent_site_ids = get_sites( array(
                'fields' => 'ids',
                'number' => 0,
            ) );
            foreach ( $wcrent_site_ids as $wcrent_site_id ) {
                switch_to_blog( (int) $wcrent_site_id );
                self::uninstall_site();
                restore_current_blog();
            }
        } else {
            self::uninstall_site();
        }
    }

    /**
     * Removes all plugin data for the current site.
     */
    private static function uninstall_site() : void {
        global $wpdb;
        $wcrent_options = array(
            // General settings.
            'wcrent_default_buffer_hours',
            'wcrent_default_inventory_qty',
            'wcrent_date_format',
            'wcrent_enable_availability_check',
            'wcrent_billing_method',
            // Deposit settings.
            'wcrent_enable_deposit',
            'wcrent_default_deposit',
            'wcrent_deposit_label',
            // Email settings.
            'wcrent_enable_return_reminder',
            'wcrent_reminder_days_before',
            'wcrent_support_url',
            // Advanced settings.
            'wcrent_cache_ttl',
            'wcrent_flush_cache',
            // Booking sequence counter (concurrency backstop).
            'wcrent_booking_seq',
            // iCal Pro feature.
            'wcrent_ical_secret_key',
            'wcrent_ical_display_url',
        );
        foreach ( $wcrent_options as $wcrent_option ) {
            delete_option( $wcrent_option );
        }
        // WooCommerce stores email class settings under its own key (enabled/disabled,
        // subject, heading). Created when the Pro email class is registered.
        delete_option( 'woocommerce_wcrent_return_reminder_settings' );
        // Transients (availability cache, keyed by product ID).
        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
        // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", $wpdb->esc_like( '_transient_wcrent_avail_' ) . '%', $wpdb->esc_like( '_transient_timeout_wcrent_avail_' ) . '%' ) );
        // phpcs:enable
        // Product post meta (_rental_* fields).
        $wcrent_product_meta_keys = array(
            '_rental_enabled',
            '_rental_price_day',
            '_rental_price_hour',
            '_rental_price_week',
            '_rental_deposit',
            '_rental_min_days',
            '_rental_max_days',
            '_rental_buffer_hours',
            '_rental_inventory_qty'
        );
        foreach ( $wcrent_product_meta_keys as $wcrent_meta_key ) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.SlowDBQuery.slow_db_query_meta_key
            $wpdb->delete( $wpdb->postmeta, array(
                'meta_key' => $wcrent_meta_key,
            ), array('%s') );
        }
        // Order line item meta (_rental_* and _wcrent_* fields).
        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.SlowDBQuery.slow_db_query_meta_key
        $wcrent_item_meta_keys = array(
            '_rental_start',
            '_rental_end',
            '_rental_days',
            '_rental_start_time',
            '_rental_end_time',
            '_rental_hours',
            '_wcrent_deposit_fee'
        );
        foreach ( $wcrent_item_meta_keys as $wcrent_item_meta_key ) {
            $wpdb->delete( $wpdb->prefix . 'woocommerce_order_itemmeta', array(
                'meta_key' => $wcrent_item_meta_key,
            ), array('%s') );
        }
        // Order-level meta (deposit totals, booking sequence, reminder-sent flags).
        // These are stored on the order (not line items), so they live in:
        // - wp_postmeta for legacy (CPT-based) orders
        // - wp_wc_orders_meta for HPOS orders
        $wcrent_order_meta_keys = array('_rental_deposit_total', '_rental_deposit_refunded', '_wcrent_booking_seq');
        $wcrent_order_meta_like_keys = array($wpdb->esc_like( '_wcrent_reminder_sent_' ) . '%');
        foreach ( $wcrent_order_meta_keys as $wcrent_order_meta_key ) {
            $wpdb->delete( $wpdb->postmeta, array(
                'meta_key' => $wcrent_order_meta_key,
            ), array('%s') );
        }
        $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->postmeta} WHERE meta_key LIKE %s", $wcrent_order_meta_like_keys[0] ) );
        // HPOS: same keys in the dedicated orders meta table (if it exists).
        // Identifiers go through %i (WP 6.2+) and values through %s so nothing is
        // interpolated. Trailing phpcs:ignore comments are NOT usable here: the
        // Freemius build rewriter relocates them onto the following line, which
        // silently re-exposes the suppressed sniff in the shipped free build.
        $wcrent_hpos_meta_table = $wpdb->prefix . 'wc_orders_meta';
        if ( $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wcrent_hpos_meta_table ) ) ) {
            foreach ( $wcrent_order_meta_keys as $wcrent_order_meta_key ) {
                $wpdb->delete( $wcrent_hpos_meta_table, array(
                    'meta_key' => $wcrent_order_meta_key,
                ), array('%s') );
            }
            $wpdb->query( $wpdb->prepare( 'DELETE FROM %i WHERE meta_key LIKE %s', $wcrent_hpos_meta_table, $wcrent_order_meta_like_keys[0] ) );
        }
        // phpcs:enable
        // Scheduled events.
        wp_clear_scheduled_hook( 'wcrent_send_return_reminders' );
    }

}
