<?php

/**
 * Plugin Name: Live Gold and Silver Price Sync for WooCommerce
 * Description: Automatically syncs WooCommerce product prices with real-time gold and silver market values, based on each product's weight and purity. Prices in EUR, USD, GBP and other major currencies.
 * Version: 1.1.0
 * Author: Stefano Martella
 * Text Domain: gold-silver-price-sync
 * License: GPLv2 or later
 * License URI: http://www.gnu.org/licenses/gpl-2.0.html
 * Requires at least: 5.0
 * Requires PHP: 7.4
 *
 */
defined( 'ABSPATH' ) || exit;
// Composer autoloader
require_once dirname( __FILE__ ) . '/vendor/autoload.php';
// --- Freemius SDK Integration ---
if ( !function_exists( 'gspsync_fs' ) ) {
    // Create a helper function for easy SDK access.
    function gspsync_fs() {
        global $gspsync_fs;
        if ( !isset( $gspsync_fs ) ) {
            // Include Freemius SDK.
            // SDK is auto-loaded through Composer
            $gspsync_fs = fs_dynamic_init( array(
                'id'               => '23858',
                'slug'             => 'gold-silver-price-sync',
                'type'             => 'plugin',
                'public_key'       => 'pk_49623ec70a1401d204a24f664c34c',
                'is_premium'       => false,
                'premium_suffix'   => 'Premium',
                'has_addons'       => false,
                'has_paid_plans'   => true,
                'is_org_compliant' => true,
                'menu'             => array(
                    'slug'    => 'gold-silver-price-sync',
                    'support' => false,
                ),
                'is_live'          => true,
            ) );
        }
        return $gspsync_fs;
    }

    // Init Freemius.
    gspsync_fs();
    // Signal that SDK was initiated.
    do_action( 'gspsync_fs_loaded' );
}
// Plugin constants
define( 'GSPSYNC_VERSION', '1.1.0' );
define( 'GSPSYNC_DIR', plugin_dir_path( __FILE__ ) );
define( 'GSPSYNC_URL', plugin_dir_url( __FILE__ ) );
// Bumped whenever stored options need reshaping; see gspsync_maybe_upgrade().
define( 'GSPSYNC_DB_VERSION', 2 );
/**
 * Debug logger: writes to the PHP error log only when WP_DEBUG is enabled,
 * so production sites are not flooded with plugin messages.
 *
 * @param string $message Message to log.
 */
function gspsync_log(  $message  ) {
    if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
        // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Intentional: gated behind WP_DEBUG for local debugging only.
        error_log( $message );
    }
}

// API endpoint. Include /api in the base URL since Laravel routes are in routes/api.php.
// Can be overridden from wp-config.php (e.g. for production) without editing the plugin:
//   define('GSPSYNC_API_BASE_URL', 'https://crm.example.com/api');
// It can also be filtered at runtime via the 'gspsync_api_base_url' filter.
if ( !defined( 'GSPSYNC_API_BASE_URL' ) ) {
    define( 'GSPSYNC_API_BASE_URL', 'https://crm-dynamic-bullion.it/api' );
}
/**
 * Update frequencies available on this installation, as schedule => seconds.
 *
 * The 10 and 30 minute intervals are premium-only: they match the premium
 * price feed (refreshed every 10 minutes server-side, vs hourly for free)
 * and are stripped from the free build by the Freemius deployment processor.
 */
function gspsync_get_allowed_frequencies() {
    $frequencies = array(
        'hourly'     => 3600,
        'twicedaily' => 43200,
        'daily'      => 86400,
    );
    return $frequencies;
}

/**
 * Get the configured update frequency, normalized against the allowed list
 * (falls back to hourly, e.g. after a premium license expires).
 */
function gspsync_get_update_frequency() {
    $frequency = get_option( 'gspsync_update_frequency', 'hourly' );
    $allowed = gspsync_get_allowed_frequencies();
    return ( isset( $allowed[$frequency] ) ? $frequency : 'hourly' );
}

/**
 * Reshape stored options after an update.
 *
 * Version 2 (multi-currency support) renamed the price options from `_eur_` to a
 * currency-neutral name, since the figures are no longer necessarily euro.
 */
function gspsync_maybe_upgrade() {
    $db_version = (int) get_option( 'gspsync_db_version', 0 );
    if ( $db_version >= GSPSYNC_DB_VERSION ) {
        return;
    }
    if ( $db_version < 2 ) {
        foreach ( array('gold', 'silver') as $metal ) {
            foreach ( array('per_gram', 'per_ounce', 'per_pound') as $unit ) {
                $legacy_value = get_option( "gspsync_{$metal}_eur_{$unit}", null );
                if ( $legacy_value !== null ) {
                    update_option( "gspsync_{$metal}_price_{$unit}", $legacy_value );
                    delete_option( "gspsync_{$metal}_eur_{$unit}" );
                }
            }
        }
        // Shops installed before this release were priced in euro. Pin them there
        // rather than adopting the store currency, which would silently reprice
        // the catalogue on a shop that had been running fine.
        if ( get_option( 'gspsync_currency', '' ) === '' ) {
            update_option( 'gspsync_currency', 'EUR' );
        }
        update_option( 'gspsync_prices_currency', 'EUR' );
        delete_option( 'gspsync_usd_eur_rate' );
        delete_transient( 'gspsync_usd_eur_rate' );
    }
    update_option( 'gspsync_db_version', GSPSYNC_DB_VERSION );
}

add_action( 'plugins_loaded', 'gspsync_maybe_upgrade', 5 );
// Include required classes
require_once GSPSYNC_DIR . 'includes/class-currency.php';
require_once GSPSYNC_DIR . 'includes/class-metal-price-updater.php';
require_once GSPSYNC_DIR . 'admin/class-admin-settings.php';
// Initialize plugin
function gspsync_init() {
    // Requires WooCommerce (checked at plugins_loaded so network-activated
    // installs are detected too)
    if ( !class_exists( 'WooCommerce' ) ) {
        return;
    }
    $updater = new GSPSYNC_Metal_Price_Updater();
    $updater->init();
    if ( is_admin() ) {
        $admin = new GSPSYNC_Admin();
        $admin->init();
    }
    // Force price update if stale
    add_action( 'init', 'gspsync_check_and_update', 5 );
}

add_action( 'plugins_loaded', 'gspsync_init' );
/**
 * Check and update prices if stale, based on the configured update interval.
 */
function gspsync_check_and_update() {
    // Never block a storefront visitor with a remote fetch:
    // updates run via WP-Cron ('gspsync_price_update') or admin page loads.
    if ( !is_admin() && !wp_doing_cron() ) {
        return;
    }
    $last_update = (int) get_option( 'gspsync_last_update', 0 );
    $now = current_time( 'timestamp' );
    $intervals = gspsync_get_allowed_frequencies();
    $interval = $intervals[gspsync_get_update_frequency()];
    if ( $now - $last_update >= $interval ) {
        $updater = new GSPSYNC_Metal_Price_Updater();
        $updater->clear_api_transients();
        $result = $updater->fetch_all_metal_prices();
        if ( $result ) {
            gspsync_log( "GSPSYNC: Metal prices auto-updated at " . gmdate( 'Y-m-d H:i:s', $now ) );
        }
    }
}

// Plugin activation
register_activation_hook( __FILE__, 'gspsync_activate' );
function gspsync_activate() {
    // Remove existing cron
    wp_clear_scheduled_hook( 'gspsync_price_update' );
    // Schedule price updates at the configured frequency
    $update_frequency = gspsync_get_update_frequency();
    if ( !wp_next_scheduled( 'gspsync_price_update' ) ) {
        wp_schedule_event( time(), $update_frequency, 'gspsync_price_update' );
    }
    // Fetch initial prices
    $updater = new GSPSYNC_Metal_Price_Updater();
    $updater->fetch_all_metal_prices();
    // Default settings
    add_option( 'gspsync_cart_lock_time', 10 );
    add_option( 'gspsync_profit_margin', 20 );
    add_option( 'gspsync_update_frequency', 'hourly' );
    // A fresh install prices in the store currency and has nothing to migrate:
    // stamping the schema version keeps gspsync_maybe_upgrade() from pinning it
    // to euro as it does for shops upgrading from 1.0.x.
    add_option( 'gspsync_currency', GSPSYNC_Currency::get_store_currency() );
    update_option( 'gspsync_db_version', GSPSYNC_DB_VERSION );
}

// Plugin deactivation
register_deactivation_hook( __FILE__, 'gspsync_deactivate' );
function gspsync_deactivate() {
    wp_clear_scheduled_hook( 'gspsync_price_update' );
}

// Custom cron schedules (premium only: fast intervals)
function gspsync_custom_cron_schedules(  $schedules  ) {
    return $schedules;
}

add_filter( 'cron_schedules', 'gspsync_custom_cron_schedules' );
// Update cron schedule when frequency changes
function gspsync_update_cron_schedule() {
    $update_frequency = gspsync_get_update_frequency();
    // Interval (seconds) for the selected frequency
    $intervals = gspsync_get_allowed_frequencies();
    $interval = $intervals[$update_frequency];
    // Schedule the next run relative to the LAST update, never "now": changing the
    // frequency must not force an immediate fetch (prevents abuse / wasted API calls).
    $last_update = (int) get_option( 'gspsync_last_update', 0 );
    $first_run = ( $last_update > 0 ? $last_update + $interval : time() );
    if ( $first_run < time() ) {
        $first_run = time();
    }
    wp_clear_scheduled_hook( 'gspsync_price_update' );
    wp_schedule_event( $first_run, $update_frequency, 'gspsync_price_update' );
    gspsync_log( "GSPSYNC: Cron updated with frequency: {$update_frequency}" );
}

add_action( 'update_option_gspsync_update_frequency', 'gspsync_update_cron_schedule' );
/**
 * Re-fetch prices when the currency changes.
 *
 * Every stored figure is denominated in the previous currency, so leaving them
 * in place would mis-price the whole catalogue by the exchange rate until the
 * next scheduled run.
 */
function gspsync_currency_changed() {
    $updater = new GSPSYNC_Metal_Price_Updater();
    $updater->clear_api_transients();
    $updater->fetch_all_metal_prices();
    if ( function_exists( 'wc_delete_product_transients' ) ) {
        wc_delete_product_transients();
    }
    gspsync_log( 'GSPSYNC: currency changed to ' . GSPSYNC_Currency::get() . ', prices refreshed' );
}

add_action( 'update_option_gspsync_currency', 'gspsync_currency_changed' );
// Cron price update handler
add_action( 'gspsync_price_update', 'gspsync_update_products' );
function gspsync_update_products() {
    $updater = new GSPSYNC_Metal_Price_Updater();
    $updater->clear_api_transients();
    $result = $updater->fetch_all_metal_prices();
    if ( $result ) {
        // Cached variation prices regenerate automatically: the metal price is
        // part of the WooCommerce variation price hash (see gspsync_add_to_hash).
        gspsync_log( 'GSPSYNC: Cron update completed successfully' );
    }
}

// Manual update via URL parameter (nonce-protected, admin only)
add_action( 'init', function () {
    if ( isset( $_GET['gspsync_update_prices'] ) && current_user_can( 'manage_options' ) ) {
        // CSRF protection: require a valid nonce on the refresh link
        $nonce = ( isset( $_GET['_wpnonce'] ) ? sanitize_key( wp_unslash( $_GET['_wpnonce'] ) ) : '' );
        if ( !wp_verify_nonce( $nonce, 'gspsync_update_prices' ) ) {
            return;
        }
        $updater = new GSPSYNC_Metal_Price_Updater();
        $updater->clear_api_transients();
        $result = $updater->fetch_all_metal_prices();
        if ( $result ) {
            wc_delete_product_transients();
            wp_safe_redirect( add_query_arg( 'updated', '1', remove_query_arg( 'gspsync_update_prices' ) ) );
        } else {
            wp_safe_redirect( add_query_arg( 'error', '1', remove_query_arg( 'gspsync_update_prices' ) ) );
        }
        exit;
    }
} );
// Add metal prices to variation price hash for cache invalidation
add_filter(
    'woocommerce_get_variation_prices_hash',
    'gspsync_add_to_hash',
    10,
    3
);
function gspsync_add_to_hash(  $hash, $product, $for_display  ) {
    $gold_price = get_option( 'gspsync_gold_price_per_gram', 0 );
    $silver_price = get_option( 'gspsync_silver_price_per_gram', 0 );
    $last_update = get_option( 'gspsync_last_update', 0 );
    $hash[] = 'gspsync_' . $gold_price . '_' . $silver_price . '_' . $last_update;
    return $hash;
}

// Frontend scripts (cart timer is premium only)
function gspsync_enqueue_scripts() {
    if ( is_cart() || is_checkout() ) {
    }
}

add_action( 'wp_enqueue_scripts', 'gspsync_enqueue_scripts' );