<?php
// tracker.php — Activity Tracking Engine

class ActivityTracker {
    private $db;
    private $db_path = __DIR__ . '/data/activity.db';
    
    public function __construct() {
        $dir = dirname($this->db_path);
        if (!is_dir($dir)) {
            mkdir($dir, 0755, true);
        }
        
        $this->db = new SQLite3($this->db_path);
        $this->db->busyTimeout(5000);
        $this->db->exec('PRAGMA journal_mode=WAL');
        $this->createTables();
    }
    
    private function createTables() {
        $this->db->exec("
            CREATE TABLE IF NOT EXISTS sessions (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                session_id TEXT NOT NULL,
                username TEXT NOT NULL,
                user_role TEXT DEFAULT '',
                login_time DATETIME NOT NULL,
                last_activity DATETIME,
                logout_time DATETIME,
                duration_seconds INTEGER DEFAULT 0,
                ip_address TEXT,
                user_agent TEXT,
                is_active INTEGER DEFAULT 1
            );
            
            CREATE TABLE IF NOT EXISTS page_views (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                session_id TEXT NOT NULL,
                username TEXT NOT NULL,
                page_url TEXT,
                timestamp DATETIME DEFAULT (datetime('now','localtime')),
                time_on_page INTEGER DEFAULT 0
            );
            
            CREATE TABLE IF NOT EXISTS user_actions (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                session_id TEXT NOT NULL,
                username TEXT NOT NULL,
                action_type TEXT NOT NULL,
                action_detail TEXT,
                timestamp DATETIME DEFAULT (datetime('now','localtime'))
            );
            
            CREATE TABLE IF NOT EXISTS heartbeats (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                session_id TEXT NOT NULL,
                username TEXT NOT NULL,
                timestamp DATETIME DEFAULT (datetime('now','localtime')),
                zoom_level REAL,
                center_lat REAL,
                center_lng REAL,
                visible_stores INTEGER DEFAULT 0
            );
            
            CREATE INDEX IF NOT EXISTS idx_sessions_username ON sessions(username);
            CREATE INDEX IF NOT EXISTS idx_sessions_login ON sessions(login_time);
            CREATE INDEX IF NOT EXISTS idx_actions_username ON user_actions(username);
            CREATE INDEX IF NOT EXISTS idx_actions_timestamp ON user_actions(timestamp);
            CREATE INDEX IF NOT EXISTS idx_heartbeats_session ON heartbeats(session_id);
        ");
    }
    
    // ثبت شروع سشن (هنگام لاگین)
    public function startSession($username, $role) {
        $stmt = $this->db->prepare("
            INSERT INTO sessions (session_id, username, user_role, login_time, last_activity, ip_address, user_agent)
            VALUES (:sid, :user, :role, datetime('now','localtime'), datetime('now','localtime'), :ip, :ua)
        ");
        $stmt->bindValue(':sid', session_id(), SQLITE3_TEXT);
        $stmt->bindValue(':user', $username, SQLITE3_TEXT);
        $stmt->bindValue(':role', $role, SQLITE3_TEXT);
        $stmt->bindValue(':ip', $_SERVER['REMOTE_ADDR'] ?? '', SQLITE3_TEXT);
        $stmt->bindValue(':ua', $_SERVER['HTTP_USER_AGENT'] ?? '', SQLITE3_TEXT);
        $stmt->execute();
    }
    
    // ثبت پایان سشن (هنگام لاگ‌اوت یا تایم‌اوت)
    public function endSession($sessionId = null) {
        $sid = $sessionId ?: session_id();
        $stmt = $this->db->prepare("
            UPDATE sessions 
            SET logout_time = datetime('now','localtime'),
                is_active = 0,
                duration_seconds = CAST((julianday(datetime('now','localtime')) - julianday(login_time)) * 86400 AS INTEGER)
            WHERE session_id = :sid AND is_active = 1
        ");
        $stmt->bindValue(':sid', $sid, SQLITE3_TEXT);
        $stmt->execute();
    }
    
    // هارت‌بیت — هر ۳۰ ثانیه از جاوااسکریپت فراخوانی میشه
    public function heartbeat($username, $data = []) {
        $sid = session_id();
        
        // آپدیت آخرین فعالیت سشن
        $stmt = $this->db->prepare("
            UPDATE sessions 
            SET last_activity = datetime('now','localtime'),
                duration_seconds = CAST((julianday(datetime('now','localtime')) - julianday(login_time)) * 86400 AS INTEGER)
            WHERE session_id = :sid AND is_active = 1
        ");
        $stmt->bindValue(':sid', $sid, SQLITE3_TEXT);
        $stmt->execute();
        
        // ثبت هارت‌بیت
        $stmt = $this->db->prepare("
            INSERT INTO heartbeats (session_id, username, zoom_level, center_lat, center_lng, visible_stores)
            VALUES (:sid, :user, :zoom, :lat, :lng, :stores)
        ");
        $stmt->bindValue(':sid', $sid, SQLITE3_TEXT);
        $stmt->bindValue(':user', $username, SQLITE3_TEXT);
        $stmt->bindValue(':zoom', $data['zoom'] ?? 0, SQLITE3_FLOAT);
        $stmt->bindValue(':lat', $data['lat'] ?? 0, SQLITE3_FLOAT);
        $stmt->bindValue(':lng', $data['lng'] ?? 0, SQLITE3_FLOAT);
        $stmt->bindValue(':stores', $data['visible_stores'] ?? 0, SQLITE3_INTEGER);
        $stmt->execute();
    }
    
    // ثبت اکشن کاربر
    public function logAction($username, $actionType, $detail = '') {
        $stmt = $this->db->prepare("
            INSERT INTO user_actions (session_id, username, action_type, action_detail)
            VALUES (:sid, :user, :type, :detail)
        ");
        $stmt->bindValue(':sid', session_id(), SQLITE3_TEXT);
        $stmt->bindValue(':user', $username, SQLITE3_TEXT);
        $stmt->bindValue(':type', $actionType, SQLITE3_TEXT);
        $stmt->bindValue(':detail', $detail, SQLITE3_TEXT);
        $stmt->execute();
    }
    
    // غیرفعال کردن سشن‌های قدیمی (بیش از ۱۵ دقیقه بدون هارت‌بیت)
    public function cleanStaleSessions() {
        $this->db->exec("
            UPDATE sessions 
            SET is_active = 0,
                logout_time = last_activity,
                duration_seconds = CAST((julianday(last_activity) - julianday(login_time)) * 86400 AS INTEGER)
            WHERE is_active = 1 
            AND julianday(datetime('now','localtime')) - julianday(last_activity) > (15.0/1440.0)
        ");
    }
    
    // ===== متدهای داشبورد =====
    
    // کاربران آنلاین
    public function getOnlineUsers() {
        $this->cleanStaleSessions();
        $results = $this->db->query("
            SELECT username, user_role, login_time, last_activity, ip_address,
                   CAST((julianday(datetime('now','localtime')) - julianday(login_time)) * 86400 AS INTEGER) as duration
            FROM sessions 
            WHERE is_active = 1
            ORDER BY last_activity DESC
        ");
        $users = [];
        while ($row = $results->fetchArray(SQLITE3_ASSOC)) {
            $users[] = $row;
        }
        return $users;
    }
    
    // آمار روزانه
    public function getDailyStats($days = 30) {
        $stmt = $this->db->prepare("
            SELECT 
                DATE(login_time) as date,
                COUNT(DISTINCT username) as unique_users,
                COUNT(*) as total_sessions,
                SUM(duration_seconds) as total_duration,
                AVG(duration_seconds) as avg_duration
            FROM sessions 
            WHERE login_time >= datetime('now', :days || ' days', 'localtime')
            GROUP BY DATE(login_time)
            ORDER BY date DESC
        ");
        $stmt->bindValue(':days', -$days, SQLITE3_INTEGER);
        $results = $stmt->execute();
        $stats = [];
        while ($row = $results->fetchArray(SQLITE3_ASSOC)) {
            $stats[] = $row;
        }
        return $stats;
    }
    
    // آمار هر کاربر
    public function getUserStats($days = 30) {
        $stmt = $this->db->prepare("
            SELECT 
                s.username,
                s.user_role,
                COUNT(*) as total_sessions,
                SUM(s.duration_seconds) as total_duration,
                AVG(s.duration_seconds) as avg_duration,
                MAX(s.login_time) as last_login,
                COUNT(DISTINCT DATE(s.login_time)) as active_days,
                (SELECT COUNT(*) FROM user_actions ua WHERE ua.username = s.username 
                 AND ua.timestamp >= datetime('now', :days2 || ' days', 'localtime')) as total_actions
            FROM sessions s
            WHERE s.login_time >= datetime('now', :days || ' days', 'localtime')
            GROUP BY s.username
            ORDER BY total_duration DESC
        ");
        $stmt->bindValue(':days', -$days, SQLITE3_INTEGER);
        $stmt->bindValue(':days2', -$days, SQLITE3_INTEGER);
        $results = $stmt->execute();
        $stats = [];
        while ($row = $results->fetchArray(SQLITE3_ASSOC)) {
            $stats[] = $row;
        }
        return $stats;
    }
    
    // جزئیات سشن‌های یک کاربر
    public function getUserSessions($username, $days = 30) {
        $stmt = $this->db->prepare("
            SELECT *,
                   CAST((julianday(COALESCE(logout_time, last_activity)) - julianday(login_time)) * 86400 AS INTEGER) as calc_duration
            FROM sessions 
            WHERE username = :user 
            AND login_time >= datetime('now', :days || ' days', 'localtime')
            ORDER BY login_time DESC
        ");
        $stmt->bindValue(':user', $username, SQLITE3_TEXT);
        $stmt->bindValue(':days', -$days, SQLITE3_INTEGER);
        $results = $stmt->execute();
        $sessions = [];
        while ($row = $results->fetchArray(SQLITE3_ASSOC)) {
            $sessions[] = $row;
        }
        return $sessions;
    }
    
    // اکشن‌های یک کاربر
    public function getUserActions($username, $days = 7) {
        $stmt = $this->db->prepare("
            SELECT * FROM user_actions 
            WHERE username = :user 
            AND timestamp >= datetime('now', :days || ' days', 'localtime')
            ORDER BY timestamp DESC
            LIMIT 500
        ");
        $stmt->bindValue(':user', $username, SQLITE3_TEXT);
        $stmt->bindValue(':days', -$days, SQLITE3_INTEGER);
        $results = $stmt->execute();
        $actions = [];
        while ($row = $results->fetchArray(SQLITE3_ASSOC)) {
            $actions[] = $row;
        }
        return $actions;
    }
    
    // آمار ساعتی (چه ساعت‌هایی فعال بودن)
    public function getHourlyActivity($days = 30) {
        $stmt = $this->db->prepare("
            SELECT 
                CAST(strftime('%H', timestamp) AS INTEGER) as hour,
                COUNT(*) as count
            FROM heartbeats 
            WHERE timestamp >= datetime('now', :days || ' days', 'localtime')
            GROUP BY hour
            ORDER BY hour
        ");
        $stmt->bindValue(':days', -$days, SQLITE3_INTEGER);
        $results = $stmt->execute();
        $hours = array_fill(0, 24, 0);
        while ($row = $results->fetchArray(SQLITE3_ASSOC)) {
            $hours[(int)$row['hour']] = (int)$row['count'];
        }
        return $hours;
    }
    
    // پرکاربردترین اکشن‌ها
    public function getTopActions($days = 30) {
        $stmt = $this->db->prepare("
            SELECT action_type, action_detail, COUNT(*) as count
            FROM user_actions 
            WHERE timestamp >= datetime('now', :days || ' days', 'localtime')
            GROUP BY action_type, action_detail
            ORDER BY count DESC
            LIMIT 50
        ");
        $stmt->bindValue(':days', -$days, SQLITE3_INTEGER);
        $results = $stmt->execute();
        $actions = [];
        while ($row = $results->fetchArray(SQLITE3_ASSOC)) {
            $actions[] = $row;
        }
        return $actions;
    }
    
    public function __destruct() {
        if ($this->db) {
            $this->db->close();
        }
    }
}
?>
