<?php
if ( ! defined( 'ABSPATH' ) ) exit;

/**
 * VMO Analytics Tracker
 * Self-hosted website analytics system - tracks visitor data without external dependencies
 * 
 * @package VMO_AI_Website_Builder
 * @version 8.0.1
 */

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

class VMO_Analytics_Tracker {
    
    private static $instance = null;
    
    /**
     * Singleton instance
     */
    public static function get_instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    /**
     * Constructor - Register hooks
     */
    public function __construct() {
        // AJAX endpoint for tracking (public - no authentication needed for visitor tracking)
        add_action('wp_ajax_nopriv_vmo_track_visit', array($this, 'track_visit'));
        add_action('wp_ajax_vmo_track_visit', array($this, 'track_visit'));
        
        // AJAX endpoint for tracking page views
        add_action('wp_ajax_nopriv_vmo_track_pageview', array($this, 'track_pageview'));
        add_action('wp_ajax_vmo_track_pageview', array($this, 'track_pageview'));
        
        // AJAX endpoint for tracking events
        add_action('wp_ajax_nopriv_vmo_track_event', array($this, 'track_event'));
        add_action('wp_ajax_vmo_track_event', array($this, 'track_event'));
        
        // ✅ NEW: AJAX endpoint for tracking page exit (duration update)
        add_action('wp_ajax_nopriv_vmo_track_exit', array($this, 'track_exit'));
        add_action('wp_ajax_vmo_track_exit', array($this, 'track_exit'));
    }
    
    /**
     * Track website visit
     * Called when visitor lands on any page
     */
    public function track_visit() {
        global $wpdb;
        
        // Get tracking data from request
        $data = $this->get_tracking_data();
        
        if (!$data) {
            wp_send_json_error(['message' => 'Invalid tracking data'], 400);
        }
        
        // Get or create contact ID (visitor fingerprint)
        $contact_id = $this->get_or_create_contact_id($data);
        
        // Check if this is a new session (last visit > 30 minutes ago)
        $is_new_session = $this->is_new_session($data['user_id'], $contact_id);
        
        // Record the interaction
        $interactions_table = $wpdb->prefix . 'vmo_contact_interactions';
        
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $result = $wpdb->insert(
            $interactions_table,
            array(
                'user_id' => $data['user_id'],
                'contact_id' => $contact_id,
                'interaction_type' => 'website_visit',
                'interaction_subtype' => $data['page_url'],
                'subject' => $data['page_title'],
                'summary' => 'Visitor from ' . $data['referrer'],
                'full_details' => json_encode(array(
                    'url' => $data['page_url'],
                    'title' => $data['page_title'],
                    'referrer' => $data['referrer'],
                    'utm_source' => $data['utm_source'],
                    'utm_medium' => $data['utm_medium'],
                    'utm_campaign' => $data['utm_campaign'],
                    'is_new_session' => $is_new_session
                )),
                'metadata' => json_encode(array(
                    'device' => $data['device'],
                    'browser' => $data['browser'],
                    'os' => $data['os'],
                    'screen_width' => $data['screen_width'],
                    'screen_height' => $data['screen_height'],
                    'language' => $data['language'],
                    'timezone' => $data['timezone'],
                    'ip_address' => $data['ip_address'],
                    'country' => $data['country'],
                    'city' => $data['city'],
                    'region' => $data['region']
                )),
                'created_at' => current_time('mysql')
            ),
            array('%d', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')
        );
        
        if ($result) {
            // Update or create contact record
            $this->update_contact_record($data['user_id'], $contact_id, $data);
            
            wp_send_json_success(array(
                'contact_id' => $contact_id,
                'is_new_session' => $is_new_session,
                'interaction_id' => $wpdb->insert_id
            ));
        } else {
            wp_send_json_error(['message' => 'Failed to track visit'], 500);
        }
    }
    
    /**
     * Track page view
     * Called when visitor navigates to a new page
     */
    public function track_pageview() {
        global $wpdb;
        
        $data = $this->get_tracking_data();
        
        if (!$data || empty($data['contact_id'])) {
            wp_send_json_error(['message' => 'Invalid tracking data'], 400);
        }
        
        $interactions_table = $wpdb->prefix . 'vmo_contact_interactions';
        
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $result = $wpdb->insert(
            $interactions_table,
            array(
                'user_id' => $data['user_id'],
                'contact_id' => $data['contact_id'],
                'interaction_type' => 'website_visit',
                'interaction_subtype' => $data['page_url'],
                'subject' => $data['page_title'],
                'full_details' => json_encode(array(
                    'url' => $data['page_url'],
                    'title' => $data['page_title'],
                    'time_on_previous_page' => $data['time_on_page'] ?? 0
                )),
                'duration_minutes' => intval($data['time_on_page'] ?? 0) / 60,
                'created_at' => current_time('mysql')
            ),
            array('%d', '%s', '%s', '%s', '%s', '%s', '%d', '%s')
        );
        
        if ($result) {
            wp_send_json_success(['pageview_id' => $wpdb->insert_id]);
        } else {
            wp_send_json_error(['message' => 'Failed to track pageview'], 500);
        }
    }
    
    /**
     * Track custom event
     * Called for button clicks, form submissions, etc.
     */
    public function track_event() {
        global $wpdb;
        
        $data = $this->get_tracking_data();
        $event_name = sanitize_text_field($_POST['event_name'] ?? 'custom_event');
        $event_data = json_decode(wp_unslash($_POST['event_data'] ?? '{}'), true);
        
        if (!$data || empty($data['contact_id'])) {
            wp_send_json_error(['message' => 'Invalid tracking data'], 400);
        }
        
        $interactions_table = $wpdb->prefix . 'vmo_contact_interactions';
        
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $result = $wpdb->insert(
            $interactions_table,
            array(
                'user_id' => $data['user_id'],
                'contact_id' => $data['contact_id'],
                'interaction_type' => 'automated_engagement',
                'interaction_subtype' => $event_name,
                'subject' => $event_name,
                'full_details' => json_encode($event_data),
                'created_at' => current_time('mysql')
            ),
            array('%d', '%s', '%s', '%s', '%s', '%s', '%s')
        );
        
        if ($result) {
            wp_send_json_success(['event_id' => $wpdb->insert_id]);
        } else {
            wp_send_json_error(['message' => 'Failed to track event'], 500);
        }
    }
    
    /**
     * Track page exit (duration tracking)
     * Updates the most recent visit record with session duration
     * Called via sendBeacon when user leaves the page
     */
    public function track_exit() {
        global $wpdb;
        
        // Get data from beacon request
        $site_owner_id = intval($_POST['site_owner_id'] ?? 0);
        $contact_id = sanitize_text_field($_POST['contact_id'] ?? '');
        $page_url = esc_url_raw($_POST['page_url'] ?? '');
        $duration_seconds = intval($_POST['duration_seconds'] ?? 0);
        $duration_minutes = intval($_POST['duration_minutes'] ?? 0);
        
        if (!$site_owner_id || !$contact_id || !$page_url) {
            // Silent fail for beacon requests (no response expected)
            exit;
        }
        
        // Find the most recent visit record for this contact/page (within last 5 minutes)
        $interactions_table = $wpdb->prefix . 'vmo_contact_interactions';
        
        $visit_id = $wpdb->get_var($wpdb->prepare(
            "SELECT id FROM {$interactions_table} 
             WHERE user_id = %d 
             AND contact_id = %s 
             AND interaction_type = 'website_visit' 
             AND interaction_subtype = %s 
             AND created_at >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)
             ORDER BY created_at DESC 
             LIMIT 1",
            $site_owner_id,
            $contact_id,
            $page_url
        ));
        
        if ($visit_id) {
            // Get current metadata
            $current_metadata = $wpdb->get_var($wpdb->prepare(
                "SELECT metadata FROM {$interactions_table} WHERE id = %d",
                $visit_id
            ));
            
            $metadata = json_decode($current_metadata, true) ?: array();
            $metadata['duration_seconds'] = $duration_seconds;
            
            // Update the visit with duration
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $wpdb->update(
                $interactions_table,
                array(
                    'duration_minutes' => $duration_minutes,
                    'metadata' => json_encode($metadata)
                ),
                array('id' => $visit_id),
                array('%d', '%s'),
                array('%d')
            );
        }
        
        // Silent exit (no JSON response for beacon)
        exit;
    }
    
    /**
     * Get tracking data from POST request
     */
    private function get_tracking_data() {
        // Get site owner ID (stored in tracking script)
        $user_id = intval($_POST['site_owner_id'] ?? 0);
        
        if (!$user_id) {
            return false;
        }
        
        // Get visitor data
        $contact_id = sanitize_text_field($_POST['contact_id'] ?? '');
        $page_url = esc_url_raw($_POST['page_url'] ?? '');
        $page_title = sanitize_text_field($_POST['page_title'] ?? '');
        $referrer = esc_url_raw($_POST['referrer'] ?? '');
        
        // UTM parameters
        $utm_source = sanitize_text_field($_POST['utm_source'] ?? '');
        $utm_medium = sanitize_text_field($_POST['utm_medium'] ?? '');
        $utm_campaign = sanitize_text_field($_POST['utm_campaign'] ?? '');
        
        // Device/Browser data
        $user_agent = $_SERVER['HTTP_USER_AGENT'] ?? '';
        $device_data = $this->parse_user_agent($user_agent);
        
        // Screen resolution
        $screen_width = intval($_POST['screen_width'] ?? 0);
        $screen_height = intval($_POST['screen_height'] ?? 0);
        
        // Language/Timezone
        $language = sanitize_text_field($_POST['language'] ?? '');
        $timezone = sanitize_text_field($_POST['timezone'] ?? '');
        
        // Get IP and geolocation
        $ip_address = $this->get_client_ip();
        $geo_data = $this->get_geolocation($ip_address);
        
        return array(
            'user_id' => $user_id,
            'contact_id' => $contact_id,
            'page_url' => $page_url,
            'page_title' => $page_title,
            'referrer' => $referrer,
            'utm_source' => $utm_source,
            'utm_medium' => $utm_medium,
            'utm_campaign' => $utm_campaign,
            'device' => $device_data['device'],
            'browser' => $device_data['browser'],
            'os' => $device_data['os'],
            'screen_width' => $screen_width,
            'screen_height' => $screen_height,
            'language' => $language,
            'timezone' => $timezone,
            'ip_address' => $ip_address,
            'country' => $geo_data['country'] ?? '',
            'city' => $geo_data['city'] ?? '',
            'region' => $geo_data['region'] ?? '',
            'time_on_page' => intval($_POST['time_on_page'] ?? 0)
        );
    }
    
    /**
     * Get or create contact ID for visitor
     */
    private function get_or_create_contact_id($data) {
        // Use existing contact ID if provided
        if (!empty($data['contact_id'])) {
            return $data['contact_id'];
        }
        
        // Generate unique contact ID based on IP + User Agent
        $fingerprint = $data['ip_address'] . '|' . $data['browser'] . '|' . $data['os'];
        return 'visitor_' . md5($fingerprint);
    }
    
    /**
     * Check if this is a new session
     * Session = gap of more than 30 minutes since last visit
     */
    private function is_new_session($user_id, $contact_id) {
        global $wpdb;
        
        $interactions_table = $wpdb->prefix . 'vmo_contact_interactions';
        $thirty_minutes_ago = date('Y-m-d H:i:s', strtotime('-30 minutes'));
        
        $recent_visit = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM {$interactions_table} 
             WHERE user_id = %d AND contact_id = %s 
             AND interaction_type = 'website_visit' 
             AND created_at > %s",
            $user_id, $contact_id, $thirty_minutes_ago
        ));
        
        return ($recent_visit == 0);
    }
    
    /**
     * Update or create contact record
     */
    private function update_contact_record($user_id, $contact_id, $data) {
        global $wpdb;
        
        $contacts_table = $wpdb->prefix . 'vmo_contacts';
        
        // Check if contact exists
        $exists = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM {$contacts_table} WHERE user_id = %d AND contact_id = %s",
            $user_id, $contact_id
        ));
        
        if ($exists) {
            // Update last contact time
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $wpdb->update(
                $contacts_table,
                array(
                    'last_contact' => current_time('mysql'),
                    'city' => $data['city'],
                    'state' => $data['region'],
                    'country' => $data['country']
                ),
                array(
                    'user_id' => $user_id,
                    'contact_id' => $contact_id
                ),
                array('%s', '%s', '%s', '%s'),
                array('%d', '%s')
            );
        } else {
            // Create new contact
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $wpdb->insert(
                $contacts_table,
                array(
                    'user_id' => $user_id,
                    'contact_id' => $contact_id,
                    'source' => 'website',
                    'primary_category' => 'website_visitor',
                    'lifecycle_stage' => 'visitor',
                    'city' => $data['city'],
                    'state' => $data['region'],
                    'country' => $data['country'],
                    'created_at' => current_time('mysql'),
                    'last_contact' => current_time('mysql')
                ),
                array('%d', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')
            );
        }
    }
    
    /**
     * Parse user agent to extract device, browser, OS
     */
    private function parse_user_agent($user_agent) {
        $device = 'Desktop';
        $browser = 'Unknown';
        $os = 'Unknown';
        
        // Detect device type
        if (preg_match('/(tablet|ipad|playbook)|(android(?!.*(mobi|opera mini)))/i', $user_agent)) {
            $device = 'Tablet';
        } elseif (preg_match('/(up.browser|up.link|mmp|symbian|smartphone|midp|wap|phone|android|iemobile|mobile|opera mini)/i', $user_agent)) {
            $device = 'Mobile';
        }
        
        // Detect browser
        if (preg_match('/MSIE|Trident/i', $user_agent)) {
            $browser = 'Internet Explorer';
        } elseif (preg_match('/Edge/i', $user_agent)) {
            $browser = 'Edge';
        } elseif (preg_match('/Chrome/i', $user_agent)) {
            $browser = 'Chrome';
        } elseif (preg_match('/Safari/i', $user_agent)) {
            $browser = 'Safari';
        } elseif (preg_match('/Firefox/i', $user_agent)) {
            $browser = 'Firefox';
        } elseif (preg_match('/Opera/i', $user_agent)) {
            $browser = 'Opera';
        }
        
        // Detect OS
        if (preg_match('/windows|win32/i', $user_agent)) {
            $os = 'Windows';
        } elseif (preg_match('/macintosh|mac os x/i', $user_agent)) {
            $os = 'macOS';
        } elseif (preg_match('/linux/i', $user_agent)) {
            $os = 'Linux';
        } elseif (preg_match('/ubuntu/i', $user_agent)) {
            $os = 'Ubuntu';
        } elseif (preg_match('/iphone/i', $user_agent)) {
            $os = 'iOS';
        } elseif (preg_match('/android/i', $user_agent)) {
            $os = 'Android';
        }
        
        return array(
            'device' => $device,
            'browser' => $browser,
            'os' => $os
        );
    }
    
    /**
     * Get client IP address
     */
    private function get_client_ip() {
        $ip_keys = array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR');
        
        foreach ($ip_keys as $key) {
            if (array_key_exists($key, $_SERVER) === true) {
                foreach (explode(',', $_SERVER[$key]) as $ip) {
                    $ip = trim($ip);
                    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false) {
                        return $ip;
                    }
                }
            }
        }
        
        return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
    }
    
    /**
     * Get geolocation from IP
     * Uses free ip-api.com service (no API key needed, 45 requests/minute limit)
     */
    private function get_geolocation($ip_address) {
        // Skip for local/private IPs
        if ($ip_address === '0.0.0.0' || $ip_address === '127.0.0.1' || strpos($ip_address, '192.168.') === 0) {
            return array('country' => 'Local', 'city' => 'Local', 'region' => 'Local');
        }
        
        // Check WordPress transient cache first (cache for 24 hours)
        $cache_key = 'vmo_geo_' . md5($ip_address);
        $cached = get_transient($cache_key);
        
        if ($cached !== false) {
            return $cached;
        }
        
        // Call free geolocation API
        $response = wp_remote_get("http://ip-api.com/json/{$ip_address}?fields=status,country,regionName,city", array(
            'timeout' => 2,
            'sslverify' => false
        ));
        
        if (is_wp_error($response)) {
            return array('country' => '', 'city' => '', 'region' => '');
        }
        
        $body = json_decode(wp_remote_retrieve_body($response), true);
        
        if ($body && $body['status'] === 'success') {
            $geo_data = array(
                'country' => $body['country'] ?? '',
                'city' => $body['city'] ?? '',
                'region' => $body['regionName'] ?? ''
            );
            
            // Cache for 24 hours
            set_transient($cache_key, $geo_data, 24 * HOUR_IN_SECONDS);
            
            return $geo_data;
        }
        
        return array('country' => '', 'city' => '', 'region' => '');
    }
    
    /**
     * Generate tracking JavaScript snippet
     * This will be injected into generated websites
     */
    public static function get_tracking_script($site_owner_id) {
        $ajax_url = admin_url('admin-ajax.php');
        
        return <<<JS
<!-- VMO Analytics Tracker -->
<script>
(function() {
    'use strict';
    
    // Configuration
    const VMO_TRACKER = {
        ajax_url: '{$ajax_url}',
        site_owner_id: {$site_owner_id},
        contact_id: localStorage.getItem('vmo_contact_id') || '',
        session_start: Date.now(),
        page_start: Date.now(),
        is_page_visible: true
    };
    
    // Get URL parameters
    function getUrlParam(name) {
        const params = new URLSearchParams(window.location.search);
        return params.get(name) || '';
    }
    
    // Track visit (initial page load)
    function trackVisit() {
        const data = new FormData();
        data.append('action', 'vmo_track_visit');
        data.append('site_owner_id', VMO_TRACKER.site_owner_id);
        data.append('contact_id', VMO_TRACKER.contact_id);
        data.append('page_url', window.location.href);
        data.append('page_title', document.title);
        data.append('referrer', document.referrer);
        data.append('utm_source', getUrlParam('utm_source'));
        data.append('utm_medium', getUrlParam('utm_medium'));
        data.append('utm_campaign', getUrlParam('utm_campaign'));
        data.append('screen_width', window.screen.width);
        data.append('screen_height', window.screen.height);
        data.append('language', navigator.language);
        data.append('timezone', Intl.DateTimeFormat().resolvedOptions().timeZone);
        
        fetch(VMO_TRACKER.ajax_url, {
            method: 'POST',
            body: data
        })
        .then(response => response.json())
        .then(result => {
            if (result.success && result.data.contact_id) {
                VMO_TRACKER.contact_id = result.data.contact_id;
                localStorage.setItem('vmo_contact_id', result.data.contact_id);
            }
        })
        .catch(error => console.log('VMO Tracker: Visit tracking failed'));
    }
    
    // ✅ NEW: Track page exit with duration (using sendBeacon for reliability)
    function trackExit() {
        if (!VMO_TRACKER.is_page_visible || !VMO_TRACKER.contact_id) {
            return; // Don't track if tab was hidden or no contact ID
        }
        
        const duration_seconds = Math.round((Date.now() - VMO_TRACKER.page_start) / 1000);
        const duration_minutes = Math.round(duration_seconds / 60);
        
        const data = new FormData();
        data.append('action', 'vmo_track_exit');
        data.append('site_owner_id', VMO_TRACKER.site_owner_id);
        data.append('contact_id', VMO_TRACKER.contact_id);
        data.append('page_url', window.location.href);
        data.append('duration_seconds', duration_seconds);
        data.append('duration_minutes', duration_minutes);
        
        // sendBeacon is more reliable during page unload
        navigator.sendBeacon(VMO_TRACKER.ajax_url, data);
    }
    
    // Track page view (when navigating between pages)
    function trackPageview() {
        const time_on_page = Math.floor((Date.now() - VMO_TRACKER.page_start) / 1000);
        VMO_TRACKER.page_start = Date.now();
        
        const data = new FormData();
        data.append('action', 'vmo_track_pageview');
        data.append('site_owner_id', VMO_TRACKER.site_owner_id);
        data.append('contact_id', VMO_TRACKER.contact_id);
        data.append('page_url', window.location.href);
        data.append('page_title', document.title);
        data.append('time_on_page', time_on_page);
        
        fetch(VMO_TRACKER.ajax_url, {
            method: 'POST',
            body: data
        })
        .catch(error => console.log('VMO Tracker: Pageview tracking failed'));
    }
    
    // Track custom event
    window.vmoTrackEvent = function(event_name, event_data) {
        const data = new FormData();
        data.append('action', 'vmo_track_event');
        data.append('site_owner_id', VMO_TRACKER.site_owner_id);
        data.append('contact_id', VMO_TRACKER.contact_id);
        data.append('event_name', event_name);
        data.append('event_data', JSON.stringify(event_data || {}));
        
        fetch(VMO_TRACKER.ajax_url, {
            method: 'POST',
            body: data
        })
        .catch(error => console.log('VMO Tracker: Event tracking failed'));
    };
    
    // ✅ NEW: Track page visibility (pause timer when tab hidden)
    document.addEventListener('visibilitychange', function() {
        VMO_TRACKER.is_page_visible = !document.hidden;
    });
    
    // Initialize tracking on page load
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', trackVisit);
    } else {
        trackVisit();
    }
    
    // ✅ UPDATED: Track page exit with duration
    window.addEventListener('beforeunload', trackExit);
    window.addEventListener('pagehide', trackExit);
    
    // Track clicks on links (navigation within site)
    document.addEventListener('click', function(e) {
        const link = e.target.closest('a');
        if (link && link.href && link.href.indexOf(window.location.origin) === 0) {
            trackPageview();
        }
    });
    
})();
</script>
JS;
    }
}

// Initialize tracker
VMO_Analytics_Tracker::get_instance();
