<?php
// includes/visitor-tracking.php

class VisitorTracking {
    private $db;
    
    public function __construct() {
        global $db;
        $this->db = $db;
    }
    
    /**
     * Gera um hash único para identificar o visitante
     */
    private function generateVisitorHash() {
        $ip = $this->getClientIP();
        $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'unknown';
        
        // Criar um hash baseado em IP + User Agent + alguns outros fatores
        $fingerprint = $ip . '-' . $userAgent;
        
        // Adicionar informações extras se disponíveis
        if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
            $fingerprint .= '-' . $_SERVER['HTTP_ACCEPT_LANGUAGE'];
        }
        
        return hash('sha256', $fingerprint);
    }
    
    /**
     * Obtém o IP real do cliente
     */
    private function getClientIP() {
        $ipKeys = [
            'HTTP_CF_CONNECTING_IP',     // Cloudflare
            'HTTP_CLIENT_IP',            // IP do cliente
            'HTTP_X_FORWARDED_FOR',      // IP do proxy
            'HTTP_X_FORWARDED',          // IP do proxy
            'HTTP_X_CLUSTER_CLIENT_IP',  // IP do cluster
            'HTTP_FORWARDED_FOR',        // IP encaminhado
            'HTTP_FORWARDED',            // IP encaminhado
            'REMOTE_ADDR'                // IP padrão
        ];
        
        foreach ($ipKeys as $key) {
            if (array_key_exists($key, $_SERVER) === true) {
                $ip = $_SERVER[$key];
                if (strpos($ip, ',') !== false) {
                    $ip = explode(',', $ip)[0];
                }
                $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';
    }
    
    /**
     * Registra uma visita única por página
     */
    public function trackUniquePageView($pageId) {
        try {
            $visitorHash = $this->generateVisitorHash();
            $currentDate = date('Y-m-d');
            $currentDateTime = date('Y-m-d H:i:s');
            $ip = $this->getClientIP();
            $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'unknown';
            
            // Verificar se já existe uma visita única hoje para esta combinação
            $this->db->query("SELECT id, visit_count FROM unique_page_visitors 
                             WHERE page_id = :page_id 
                             AND visitor_hash = :visitor_hash 
                             AND visit_date = :visit_date");
            
            $this->db->bind(':page_id', $pageId);
            $this->db->bind(':visitor_hash', $visitorHash);
            $this->db->bind(':visit_date', $currentDate);
            
            $existingVisit = $this->db->single();
            
            if ($existingVisit) {
                // Visitante já visitou esta página hoje - apenas atualizar last_visit_time e incrementar contador
                $this->db->query("UPDATE unique_page_visitors 
                                 SET last_visit_time = :last_visit_time, 
                                     visit_count = visit_count + 1 
                                 WHERE id = :id");
                
                $this->db->bind(':last_visit_time', $currentDateTime);
                $this->db->bind(':id', $existingVisit['id']);
                $this->db->execute();
                
                // Registrar na tabela page_views para manter histórico detalhado (opcional)
                $this->db->query("INSERT INTO page_views (page_id, visitor_ip, visitor_hash, session_date, user_agent, viewed_at) 
                                 VALUES (:page_id, :visitor_ip, :visitor_hash, :session_date, :user_agent, :viewed_at)");
                
                $this->db->bind(':page_id', $pageId);
                $this->db->bind(':visitor_ip', $ip);
                $this->db->bind(':visitor_hash', $visitorHash);
                $this->db->bind(':session_date', $currentDate);
                $this->db->bind(':user_agent', $userAgent);
                $this->db->bind(':viewed_at', $currentDateTime);
                $this->db->execute();
                
                return false; // Não é uma nova visita única
            } else {
                // Nova visita única - inserir registro
                $this->db->query("INSERT INTO unique_page_visitors 
                                 (page_id, visitor_hash, visit_date, first_visit_time, last_visit_time, visit_count) 
                                 VALUES (:page_id, :visitor_hash, :visit_date, :first_visit_time, :last_visit_time, 1)");
                
                $this->db->bind(':page_id', $pageId);
                $this->db->bind(':visitor_hash', $visitorHash);
                $this->db->bind(':visit_date', $currentDate);
                $this->db->bind(':first_visit_time', $currentDateTime);
                $this->db->bind(':last_visit_time', $currentDateTime);
                $this->db->execute();
                
                // Registrar também na tabela page_views
                $this->db->query("INSERT INTO page_views (page_id, visitor_ip, visitor_hash, session_date, user_agent, viewed_at) 
                                 VALUES (:page_id, :visitor_ip, :visitor_hash, :session_date, :user_agent, :viewed_at)");
                
                $this->db->bind(':page_id', $pageId);
                $this->db->bind(':visitor_ip', $ip);
                $this->db->bind(':visitor_hash', $visitorHash);
                $this->db->bind(':session_date', $currentDate);
                $this->db->bind(':user_agent', $userAgent);
                $this->db->bind(':viewed_at', $currentDateTime);
                $this->db->execute();
                
                return true; // Nova visita única registrada
            }
            
        } catch (Exception $e) {
            logError("Erro ao registrar visita única: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Obtém estatísticas de visitantes únicos para uma página
     */
    public function getUniquePageStats($pageId, $dateStart = null, $dateEnd = null) {
        try {
            $dateStart = $dateStart ?: date('Y-m-d', strtotime('-30 days'));
            $dateEnd = $dateEnd ?: date('Y-m-d');
            
            $this->db->query("SELECT 
                                visit_date,
                                COUNT(*) as unique_visitors,
                                SUM(visit_count) as total_visits
                             FROM unique_page_visitors 
                             WHERE page_id = :page_id 
                             AND visit_date BETWEEN :date_start AND :date_end
                             GROUP BY visit_date
                             ORDER BY visit_date");
            
            $this->db->bind(':page_id', $pageId);
            $this->db->bind(':date_start', $dateStart);
            $this->db->bind(':date_end', $dateEnd);
            
            return $this->db->resultSet();
            
        } catch (Exception $e) {
            logError("Erro ao obter estatísticas únicas: " . $e->getMessage());
            return [];
        }
    }
    
    /**
     * Obtém estatísticas de conversão baseadas em visitantes únicos
     */
    public function getUniqueConversionStats($landingPageId, $dateStart = null, $dateEnd = null) {
        try {
            $dateStart = $dateStart ?: date('Y-m-d', strtotime('-30 days'));
            $dateEnd = $dateEnd ?: date('Y-m-d');
            
            $stats = [
                'landing' => 0,
                'step1' => 0,
                'step2' => 0,
                'step3' => 0,
                'registration' => 0
            ];
            
            // Visitantes únicos da landing page
            $this->db->query("SELECT COUNT(DISTINCT visitor_hash) as unique_visitors
                             FROM unique_page_visitors 
                             WHERE page_id = :landing_page_id 
                             AND visit_date BETWEEN :date_start AND :date_end");
            
            $this->db->bind(':landing_page_id', $landingPageId);
            $this->db->bind(':date_start', $dateStart);
            $this->db->bind(':date_end', $dateEnd);
            
            $result = $this->db->single();
            $stats['landing'] = $result ? $result['unique_visitors'] : 0;
            
            // Visitantes únicos para cada etapa do funil
            foreach (['step1', 'step2', 'step3', 'registration'] as $step) {
                $this->db->query("SELECT COUNT(DISTINCT upv.visitor_hash) as unique_visitors
                                 FROM unique_page_visitors upv
                                 JOIN pages p ON upv.page_id = p.id
                                 WHERE p.type = :step_type 
                                 AND p.landing_page_id = :landing_page_id
                                 AND upv.visit_date BETWEEN :date_start AND :date_end");
                
                $this->db->bind(':step_type', $step);
                $this->db->bind(':landing_page_id', $landingPageId);
                $this->db->bind(':date_start', $dateStart);
                $this->db->bind(':date_end', $dateEnd);
                
                $result = $this->db->single();
                $stats[$step] = $result ? $result['unique_visitors'] : 0;
            }
            
            return $stats;
            
        } catch (Exception $e) {
            logError("Erro ao obter estatísticas de conversão únicas: " . $e->getMessage());
            return [];
        }
    }
    
    /**
     * Obtém a jornada de um visitante específico
     */
    public function getVisitorJourney($visitorHash, $dateStart = null, $dateEnd = null) {
        try {
            $dateStart = $dateStart ?: date('Y-m-d', strtotime('-7 days'));
            $dateEnd = $dateEnd ?: date('Y-m-d');
            
            $this->db->query("SELECT 
                                upv.page_id,
                                upv.visit_date,
                                upv.first_visit_time,
                                upv.last_visit_time,
                                upv.visit_count,
                                p.title,
                                p.type,
                                p.slug
                             FROM unique_page_visitors upv
                             JOIN pages p ON upv.page_id = p.id
                             WHERE upv.visitor_hash = :visitor_hash
                             AND upv.visit_date BETWEEN :date_start AND :date_end
                             ORDER BY upv.first_visit_time");
            
            $this->db->bind(':visitor_hash', $visitorHash);
            $this->db->bind(':date_start', $dateStart);
            $this->db->bind(':date_end', $dateEnd);
            
            return $this->db->resultSet();
            
        } catch (Exception $e) {
            logError("Erro ao obter jornada do visitante: " . $e->getMessage());
            return [];
        }
    }
    
    /**
     * Limpa dados antigos de visitantes (manutenção)
     */
    public function cleanOldVisitorData($daysToKeep = 90) {
        try {
            $cutoffDate = date('Y-m-d', strtotime("-{$daysToKeep} days"));
            
            // Limpar dados antigos da tabela unique_page_visitors
            $this->db->query("DELETE FROM unique_page_visitors WHERE visit_date < :cutoff_date");
            $this->db->bind(':cutoff_date', $cutoffDate);
            $deletedUnique = $this->db->execute() ? $this->db->rowCount() : 0;
            
            // Limpar dados antigos da tabela page_views
            $this->db->query("DELETE FROM page_views WHERE viewed_at < :cutoff_datetime");
            $this->db->bind(':cutoff_datetime', $cutoffDate . ' 00:00:00');
            $deletedViews = $this->db->execute() ? $this->db->rowCount() : 0;
            
            logInfo("Limpeza de dados: {$deletedUnique} registros únicos e {$deletedViews} page views removidos.");
            
            return [
                'unique_visitors_deleted' => $deletedUnique,
                'page_views_deleted' => $deletedViews
            ];
            
        } catch (Exception $e) {
            logError("Erro na limpeza de dados antigos: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Obtém estatísticas gerais de visitantes únicos
     */
    public function getGeneralUniqueStats($dateStart = null, $dateEnd = null) {
        try {
            $dateStart = $dateStart ?: date('Y-m-d', strtotime('-30 days'));
            $dateEnd = $dateEnd ?: date('Y-m-d');
            
            // Total de visitantes únicos no período
            $this->db->query("SELECT COUNT(DISTINCT visitor_hash) as total_unique_visitors
                             FROM unique_page_visitors 
                             WHERE visit_date BETWEEN :date_start AND :date_end");
            
            $this->db->bind(':date_start', $dateStart);
            $this->db->bind(':date_end', $dateEnd);
            
            $result = $this->db->single();
            $totalUniqueVisitors = $result ? $result['total_unique_visitors'] : 0;
            
            // Visitantes únicos por tipo de página
            $this->db->query("SELECT 
                                p.type,
                                COUNT(DISTINCT upv.visitor_hash) as unique_visitors
                             FROM unique_page_visitors upv
                             JOIN pages p ON upv.page_id = p.id
                             WHERE upv.visit_date BETWEEN :date_start AND :date_end
                             GROUP BY p.type");
            
            $this->db->bind(':date_start', $dateStart);
            $this->db->bind(':date_end', $dateEnd);
            
            $byType = $this->db->resultSet();
            
            return [
                'total_unique_visitors' => $totalUniqueVisitors,
                'by_type' => $byType
            ];
            
        } catch (Exception $e) {
            logError("Erro ao obter estatísticas gerais únicas: " . $e->getMessage());
            return [];
        }
    }
}

// Instanciar a classe globalmente
$visitorTracking = new VisitorTracking();