<?php
/**
 * BoostAffiliate SDK — Drop-in affiliate tracking for WordPress plugins.
 *
 * Usage (2 steps):
 *
 *   1. In your main plugin file, after the plugin header:
 *
 *        require_once __DIR__ . '/boostaffiliate.php';
 *        BoostAffiliate::init( __FILE__, MY_PLUGIN_VERSION );
 *
 *   2. Wherever a purchase completes (e.g., PayPal capture success):
 *
 *        BoostAffiliate::purchase( 29.99, 'USD', 'pro-monthly' );
 *
 * Everything else (registration, heartbeat, deactivation) is automatic.
 *
 * @version 1.0.0
 * @link    https://boostaffiliate.boostmedia.co.il
 */

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

if ( class_exists( 'BoostAffiliate' ) ) {
    return;
}

// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound -- Drop-in SDK class; namespace intentionally shared with other plugins for single-source install. Excluded from WP.org ZIP by the build scripts.
class BoostAffiliate {

    const API          = 'https://boostaffiliate.boostmedia.co.il/api';
    const OPT_KEY      = 'boostaffiliate_license_key';
    const CRON_HOOK    = 'boostaffiliate_heartbeat';
    const REG_HOOK     = 'boostaffiliate_deferred_register';

    private static $plugin_file    = '';
    private static $plugin_version = '0.0.0';

    /**
     * Initialize the SDK. Call once from your main plugin file.
     *
     * @param string $plugin_file    __FILE__ of the main plugin file.
     * @param string $plugin_version Your plugin's current version string.
     */
    public static function init( $plugin_file, $plugin_version = '1.0.0' ) {
        self::$plugin_file    = $plugin_file;
        self::$plugin_version = $plugin_version;

        register_activation_hook( $plugin_file, array( __CLASS__, '_on_activate' ) );
        register_deactivation_hook( $plugin_file, array( __CLASS__, '_on_deactivate' ) );

        add_action( self::CRON_HOOK, array( __CLASS__, '_heartbeat' ) );
        add_action( self::REG_HOOK, array( __CLASS__, '_deferred_register' ) );
    }

    /* ------------------------------------------------------------------ */
    /*  Public: report a purchase                                         */
    /* ------------------------------------------------------------------ */

    /**
     * Report a completed purchase to BoostAffiliate.
     *
     * @param float  $amount     Purchase total (e.g., 29.99).
     * @param string $currency   ISO 4217 currency code (e.g., 'USD', 'ILS').
     * @param string $package_id Optional package/product identifier.
     * @return bool True on success, false on failure.
     */
    public static function purchase( $amount, $currency, $package_id = '' ) {
        $license_key = get_option( self::OPT_KEY );
        if ( empty( $license_key ) ) {
            return false;
        }

        $body = array(
            'license_key'     => $license_key,
            'site_url'        => get_site_url(),
            'amount'          => (float) $amount,
            'currency'        => $currency,
            'idempotency_key' => self::_idempotency_key( $license_key, $amount, $currency, $package_id ),
        );
        if ( '' !== $package_id ) {
            $body['package_id'] = $package_id;
        }

        $data = self::_post( '/plugin/purchase', $body );
        return ( is_array( $data ) && ! empty( $data['success'] ) );
    }

    /* ------------------------------------------------------------------ */
    /*  Internal hooks (prefixed with _ to signal "do not call directly") */
    /* ------------------------------------------------------------------ */

    /** @internal */
    public static function _on_activate() {
        if ( ! wp_next_scheduled( self::CRON_HOOK ) ) {
            wp_schedule_event( time() + 600, 'daily', self::CRON_HOOK );
        }
        if ( ! wp_next_scheduled( self::REG_HOOK ) ) {
            wp_schedule_single_event( time() + 20, self::REG_HOOK );
        }
    }

    /** @internal */
    public static function _on_deactivate() {
        wp_clear_scheduled_hook( self::CRON_HOOK );
        wp_clear_scheduled_hook( self::REG_HOOK );

        $license_key = get_option( self::OPT_KEY );
        if ( ! empty( $license_key ) ) {
            wp_remote_post( self::API . '/plugin/deactivate', array(
                'body'     => wp_json_encode( array(
                    'license_key' => $license_key,
                    'site_url'    => get_site_url(),
                ) ),
                'headers'  => array( 'Content-Type' => 'application/json' ),
                'timeout'  => 10,
                'blocking' => false,
            ) );
        }
    }

    /** @internal Deferred registration (runs ~20 s after activation via cron). */
    public static function _deferred_register() {
        self::_register();
    }

    /** @internal Daily heartbeat — re-register to keep lastSeenAt fresh. */
    public static function _heartbeat() {
        self::_register();
    }

    /* ------------------------------------------------------------------ */
    /*  Core registration logic                                           */
    /* ------------------------------------------------------------------ */

    private static function _register() {
        $body = array(
            'site_url'       => get_site_url(),
            'plugin_version' => self::$plugin_version ? self::$plugin_version : '0.0.0',
            'wp_version'     => get_bloginfo( 'version' ),
        );

        $affiliate = self::_read_affiliate_json();
        if ( null !== $affiliate ) {
            $body['affiliate_code']      = $affiliate['affiliate_code'];
            $body['affiliate_signature'] = $affiliate['signature'];
            $body['affiliate_timestamp'] = $affiliate['timestamp'];
        }

        $data = self::_post( '/plugin/register', $body );

        if ( is_array( $data ) && ! empty( $data['success'] ) && ! empty( $data['license_key'] ) ) {
            update_option( self::OPT_KEY, sanitize_text_field( $data['license_key'] ) );
        }
    }

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

    private static function _read_affiliate_json() {
        $file = plugin_dir_path( self::$plugin_file ? self::$plugin_file : __FILE__ ) . 'affiliate.json';
        if ( ! file_exists( $file ) ) {
            return null;
        }
        $raw = @file_get_contents( $file );
        if ( false === $raw ) {
            return null;
        }
        $data = json_decode( $raw, true );
        if (
            ! is_array( $data )
            || empty( $data['affiliate_code'] )
            || empty( $data['signature'] )
            || empty( $data['timestamp'] )
        ) {
            return null;
        }
        return $data;
    }

    private static function _post( $path, $body ) {
        $response = wp_remote_post( self::API . $path, array(
            'body'    => wp_json_encode( $body ),
            'headers' => array( 'Content-Type' => 'application/json' ),
            'timeout' => 30,
        ) );
        if ( is_wp_error( $response ) ) {
            return null;
        }
        return json_decode( wp_remote_retrieve_body( $response ), true );
    }

    private static function _idempotency_key( $license_key, $amount, $currency, $package_id ) {
        $minute = gmdate( 'Y-m-d\TH:i' );
        return hash( 'sha256', "{$license_key}|{$amount}|{$currency}|{$package_id}|{$minute}" );
    }
}
