<?php
/**
 * Post Engagement Tracker
 *
 * Records views and basic engagement for blog posts.
 *
 * @package InsightPress
 */

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

class InsightPress_Post_Tracker
{
    const TABLE_NAME = 'insightpress_post_events';
    private $current_view_id = 0;

    public function __construct()
    {
        add_action('init', array($this, 'maybe_create_table'));
        add_action('wp_enqueue_scripts', array($this, 'enqueue_tracker_script'));
        add_action('wp_ajax_insightpress_track_heartbeat', array($this, 'ajax_track_heartbeat'));
        add_action('wp_ajax_nopriv_insightpress_track_heartbeat', array($this, 'ajax_track_heartbeat'));
        
        add_action('wp_ajax_insightpress_track_event', array($this, 'ajax_track_event'));
        add_action('wp_ajax_nopriv_insightpress_track_event', array($this, 'ajax_track_event'));
        
        // Track Post View
        add_action('template_redirect', array($this, 'track_post_view'));
    }

    /**
     * Create DB table.
     */
    public function maybe_create_table()
    {
        global $wpdb;
        $table = $wpdb->prefix . self::TABLE_NAME;

        $charset_collate = $wpdb->get_charset_collate();
        $sql = "CREATE TABLE $table (
            id bigint(20) unsigned NOT NULL auto_increment,
            post_id bigint(20) NOT NULL,
            event_type varchar(50) NOT NULL,
            event_label varchar(255) DEFAULT NULL,
            session_id varchar(255) NOT NULL,
            time_spent int(11) DEFAULT 0,
            source varchar(100) DEFAULT 'Direct',
            country varchar(100) DEFAULT 'Unknown',
            device_type varchar(50) DEFAULT 'Desktop',
            browser varchar(100) DEFAULT 'Other',
            visitor_type varchar(50) DEFAULT 'New',
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY  (id),
            KEY post_event (post_id, event_type),
            KEY session_id (session_id),
            KEY created_at (created_at),
            KEY country (country),
            KEY device_type (device_type)
        ) $charset_collate;";

        require_once ABSPATH . 'wp-admin/includes/upgrade.php';
        dbDelta($sql);
    }

    /**
     * Get current session ID.
     */
    protected function get_session_id()
    {
        if (is_user_logged_in()) {
            return 'user_' . get_current_user_id();
        }
        if (!session_id()) {
            @session_start();
        }
        return 'php_post_' . session_id();
    }

    /**
     * Detect traffic source.
     */
    protected function detect_source()
    {
        $referrer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
        $host = $referrer ? parse_url($referrer, PHP_URL_HOST) : '';
        
        if (isset($_GET['gclid']) || (isset($_GET['utm_source']) && strpos($_GET['utm_source'], 'google') !== false && isset($_GET['utm_medium']) && $_GET['utm_medium'] === 'cpc')) {
            return 'Google Ads';
        }

        if (empty($referrer)) return 'Direct';

        if (strpos($host, 'facebook.com') !== false || strpos($host, 'fb.me') !== false) return 'Facebook';

        $search_engines = array('google.com', 'bing.com', 'yahoo.com', 'duckduckgo.com');
        foreach ($search_engines as $engine) {
            if (strpos($host, $engine) !== false) return 'Organic';
        }

        $site_url = parse_url(get_site_url(), PHP_URL_HOST);
        if ($host === $site_url) return 'Internal';

        return 'Referral';
    }

    /**
     * Detect device type and browser.
     */
    protected function detect_environment()
    {
        $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
        $data = array(
            'device'  => 'Desktop',
            'browser' => 'Other'
        );

        if (empty($user_agent)) return $data;

        // Device
        if (preg_match('/Tablet|iPad/i', $user_agent)) {
            $data['device'] = 'Tablet';
        } elseif (preg_match('/Mobi|Android|iPhone/i', $user_agent)) {
            $data['device'] = 'Mobile';
        }

        // Browser
        if (preg_match('/Opera/i', $user_agent) || preg_match('/OPR/i', $user_agent)) {
            $data['browser'] = 'Opera';
        } elseif (preg_match('/Edge/i', $user_agent) || preg_match('/Edg/i', $user_agent)) {
            $data['browser'] = 'Edge';
        } elseif (preg_match('/Chrome/i', $user_agent)) {
            $data['browser'] = 'Chrome';
        } elseif (preg_match('/Safari/i', $user_agent)) {
            $data['browser'] = 'Safari';
        } elseif (preg_match('/Firefox/i', $user_agent)) {
            $data['browser'] = 'Firefox';
        }

        return $data;
    }

    /**
     * Detect location.
     */
    protected function detect_location()
    {
        $data = array('country' => 'Unknown');
        if (!class_exists('WC_Geolocation')) return $data;
        
        $ip = WC_Geolocation::get_ip_address();
        if ($ip === '127.0.0.1' || $ip === '::1') return array('country' => 'Local');

        $geo = WC_Geolocation::geolocate_ip($ip);
        if (!empty($geo['country'])) {
            $data['country'] = $geo['country'];
        }
        return $data;
    }

    /**
     * Get visitor type.
     */
    protected function get_visitor_type()
    {
        global $wpdb;
        $table = $wpdb->prefix . self::TABLE_NAME;
        $session_id = $this->get_session_id();
        
        $count = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM $table WHERE session_id = %s AND event_type = 'view'",
            $session_id
        ));

        return $count > 0 ? 'Returning' : 'New';
    }

    public function record_event($post_id, $event_type, $extra = [])
    {
        global $wpdb;
        $table = $wpdb->prefix . self::TABLE_NAME;
        $session_id = $this->get_session_id();
        $source = $this->detect_source();
        $env = $this->detect_environment();
        $loc = $this->detect_location();
        $visitor_type = $this->get_visitor_type();
        
        $data = array(
            'post_id'      => $post_id,
            'event_type'   => $event_type,
            'session_id'   => $session_id,
            'source'       => $source,
            'country'      => $loc['country'],
            'device_type'  => $env['device'],
            'browser'      => $env['browser'],
            'visitor_type' => $visitor_type,
            'created_at'   => current_time('mysql'),
        );

        if (isset($extra['event_label'])) {
            $data['event_label'] = $extra['event_label'];
        }

        if (isset($extra['time_spent'])) {
            $data['time_spent'] = $extra['time_spent'];
        }

        $wpdb->insert($table, $data);
        return $wpdb->insert_id;
    }

    /**
     * Track single post view.
     */
    public function track_post_view()
    {
        if (is_singular('post')) {
            $post_id = get_the_ID();
            $this->current_view_id = $this->record_event($post_id, 'view');
        }
    }

    /**
     * Enqueue JS for heartbeat (time on page).
     */
    public function enqueue_tracker_script()
    {
        if (!is_singular('post')) return;

        $ajax_url = admin_url('admin-ajax.php');
        $script = "
            (function() {
                var postId = " . get_the_ID() . ";
                var viewId = " . (int)$this->current_view_id . ";
                var startTime = new Date().getTime();
                var heartbeatInterval = 10000;
                var scrolledPoints = [];

                function sendEvent(type, label) {
                    var data = new FormData();
                    data.append('action', 'insightpress_track_event');
                    data.append('post_id', postId);
                    data.append('view_id', viewId);
                    data.append('event_type', type);
                    if (label) data.append('event_label', label);
                    navigator.sendBeacon('" . $ajax_url . "', data);
                }

                function sendHeartbeat(isExit) {
                    var currentTime = new Date().getTime();
                    var timeSpent = Math.floor((currentTime - startTime) / 1000);
                    
                    var data = new FormData();
                    data.append('action', 'insightpress_track_heartbeat');
                    data.append('post_id', postId);
                    data.append('view_id', viewId);
                    data.append('time_spent', timeSpent);
                    data.append('is_exit', isExit ? 1 : 0);

                    navigator.sendBeacon('" . $ajax_url . "', data);
                }

                // Scroll Tracking
                window.addEventListener('scroll', function() {
                    var h = document.documentElement, 
                        b = document.body,
                        st = 'scrollTop',
                        sh = 'scrollHeight';
                    var percent = (h[st]||b[st]) / ((h[sh]||b[sh]) - h.clientHeight) * 100;
                    
                    [25, 50, 75, 100].forEach(function(point) {
                        if (percent >= point && scrolledPoints.indexOf(point) === -1) {
                            scrolledPoints.push(point);
                            sendEvent('scroll', point + '%');
                        }
                    });
                });

                // Click Tracking
                document.addEventListener('click', function(e) {
                    var link = e.target.closest('a');
                    if (!link) return;

                    var url = link.href;
                    var isExternal = url.indexOf(window.location.host) === -1;
                    var isCTA = link.classList.contains('button') || link.classList.contains('cta') || link.classList.contains('wp-block-button__link');

                    if (isCTA) {
                        sendEvent('click', 'CTA: ' + (link.textContent || url));
                    } else if (isExternal) {
                        sendEvent('click', 'External: ' + url);
                    } else {
                        sendEvent('click', 'Internal: ' + url);
                    }
                });

                // Periodic heartbeat
                setInterval(function() {
                    sendHeartbeat(false);
                }, heartbeatInterval);

                // Exit heartbeat
                window.addEventListener('beforeunload', function() {
                    sendHeartbeat(true);
                });
            })();
        ";
        wp_add_inline_script('jquery-core', $script);
    }

    /**
     * AJAX handler for heartbeat.
     */
    public function ajax_track_heartbeat()
    {
        $post_id    = isset($_POST['post_id']) ? (int)$_POST['post_id'] : 0;
        $view_id    = isset($_POST['view_id']) ? (int)$_POST['view_id'] : 0;
        $time_spent = isset($_POST['time_spent']) ? (int)$_POST['time_spent'] : 0;
        $is_exit    = isset($_POST['is_exit']) && $_POST['is_exit'] == 1;

        if (!$post_id) wp_die();

        global $wpdb;
        $table = $wpdb->prefix . self::TABLE_NAME;
        $session_id = $this->get_session_id();

        if ($view_id) {
            // Update specific view record
            $wpdb->update(
                $table,
                array('time_spent' => $time_spent),
                array('id' => $view_id)
            );
        } else {
            // Fallback: Update existing view record with time spent (legacy/unknown)
            $wpdb->query($wpdb->prepare(
                "UPDATE $table SET time_spent = %d WHERE post_id = %d AND session_id = %s AND event_type = 'view' ORDER BY created_at DESC LIMIT 1",
                $time_spent, $post_id, $session_id
            ));
        }

        if ($is_exit) {
            $this->record_event($post_id, 'exit');
        }

        wp_die();
    }

    /**
     * AJAX handler for generic events.
     */
    public function ajax_track_event()
    {
        $post_id    = isset($_POST['post_id']) ? (int)$_POST['post_id'] : 0;
        $event_type = isset($_POST['event_type']) ? sanitize_text_field($_POST['event_type']) : '';
        $label      = isset($_POST['event_label']) ? sanitize_text_field($_POST['event_label']) : '';

        if (!$post_id || !$event_type) wp_die();

        $this->record_event($post_id, $event_type, array('event_label' => $label));
        wp_die();
    }

    public static function get_table_name()
    {
        global $wpdb;
        return $wpdb->prefix . self::TABLE_NAME;
    }
}
