<?php
/**
 * Privacy-aware conversion event delivery for opted-in Freemius installs.
 */
if ( !defined( 'ABSPATH' ) ) {
    exit;
}

final class YATOON_Conversion_Telemetry {
    const QUEUE_OPTION  = 'yatoon_conversion_event_queue';
    const SENT_OPTION   = 'yatoon_conversion_events_sent';
    const FAILED_OPTION = 'yatoon_conversion_events_failed';
    const CRON_HOOK     = 'yatoon_flush_conversion_events';

    private static $allowed_milestones = array(
        'activated',
        'wizard_completed',
        'booking_page_opened',
        'first_test_booking',
        'first_real_booking',
    );

    public static function init() {
        add_action( 'yatoon_onboarding_milestone_recorded', array( __CLASS__, 'queue_event' ), 10, 2 );
        add_action( 'yatoon_fs_loaded', array( __CLASS__, 'backfill_and_schedule' ), 20 );
        add_action( self::CRON_HOOK, array( __CLASS__, 'flush' ) );
    }

    public static function queue_event( $milestone, $recorded_at ) {
        $milestone = sanitize_key( $milestone );
        if ( !in_array( $milestone, self::$allowed_milestones, true ) ) {
            return;
        }

        $queue = get_option( self::QUEUE_OPTION, array() );
        $sent  = get_option( self::SENT_OPTION, array() );
        $queue = is_array( $queue ) ? $queue : array();
        $sent  = is_array( $sent ) ? $sent : array();
        if ( isset( $queue[ $milestone ] ) || isset( $sent[ $milestone ] ) ) {
            return;
        }

        $queue[ $milestone ] = array(
            'recorded_at' => sanitize_text_field( (string) $recorded_at ),
            'attempts'    => 0,
        );
        update_option( self::QUEUE_OPTION, $queue, false );
        self::schedule_flush();
    }

    public static function backfill_and_schedule() {
        $milestones = get_option( 'yatoon_onboarding_milestones', array() );
        if ( is_array( $milestones ) ) {
            foreach ( self::$allowed_milestones as $milestone ) {
                if ( isset( $milestones[ $milestone ] ) ) {
                    self::queue_event( $milestone, $milestones[ $milestone ] );
                }
            }
        }
        self::schedule_flush();
    }

    private static function schedule_flush( $delay = 60 ) {
        $queue = get_option( self::QUEUE_OPTION, array() );
        if ( empty( $queue ) || !function_exists( 'yatoon_fs' ) || !self::can_send( yatoon_fs() ) || wp_next_scheduled( self::CRON_HOOK ) ) {
            return;
        }
        wp_schedule_single_event( current_time( 'timestamp', true ) + max( 60, absint( $delay ) ), self::CRON_HOOK );
    }

    private static function can_send( $freemius ) {
        if ( !is_object( $freemius )
            || !method_exists( $freemius, 'is_registered' )
            || !method_exists( $freemius, 'is_tracking_allowed' )
            || !method_exists( $freemius, 'track_event_once' )
        ) {
            return false;
        }

        $allowed = $freemius->is_registered() && $freemius->is_tracking_allowed();
        return (bool) apply_filters( 'yatoon_allow_conversion_telemetry', $allowed );
    }

    public static function flush() {
        $queue = get_option( self::QUEUE_OPTION, array() );
        if ( !is_array( $queue ) || empty( $queue ) || !function_exists( 'yatoon_fs' ) ) {
            return;
        }

        $freemius = yatoon_fs();
        if ( !self::can_send( $freemius ) ) {
            return;
        }

        $sent   = get_option( self::SENT_OPTION, array() );
        $failed = get_option( self::FAILED_OPTION, array() );
        $sent   = is_array( $sent ) ? $sent : array();
        $failed = is_array( $failed ) ? $failed : array();

        foreach ( $queue as $milestone => $event ) {
            if ( !in_array( $milestone, self::$allowed_milestones, true ) ) {
                unset( $queue[ $milestone ] );
                continue;
            }

            $attempts = isset( $event['attempts'] ) ? absint( $event['attempts'] ) : 0;
            try {
                $result = $freemius->track_event_once(
                    'yatoon_funnel_' . $milestone,
                    array(
                        'plugin_version' => defined( 'YATOON_VERSION' ) ? YATOON_VERSION : '',
                        'package_tier'   => defined( 'YATOON_PACKAGE_TIER' ) ? YATOON_PACKAGE_TIER : 'free',
                        'booking_mode'   => sanitize_key( (string) get_option( 'yatoon_active_platform', 'local' ) ),
                        'recorded_at'    => sanitize_text_field( (string) ( $event['recorded_at'] ?? '' ) ),
                    )
                );
            } catch ( Throwable $exception ) {
                unset( $exception );
                $result = false;
            }

            if ( false !== $result ) {
                $sent[ $milestone ] = current_time( 'mysql' );
                unset( $queue[ $milestone ], $failed[ $milestone ] );
                continue;
            }

            $attempts++;
            if ( $attempts >= 3 ) {
                $failed[ $milestone ] = current_time( 'mysql' );
                unset( $queue[ $milestone ] );
            } else {
                $queue[ $milestone ]['attempts'] = $attempts;
            }
        }

        update_option( self::QUEUE_OPTION, $queue, false );
        update_option( self::SENT_OPTION, $sent, false );
        update_option( self::FAILED_OPTION, $failed, false );
        if ( !empty( $queue ) ) {
            self::schedule_flush( 6 * HOUR_IN_SECONDS );
        }
    }
}

YATOON_Conversion_Telemetry::init();
