<?php

require_once __DIR__ . '/../../vendor/autoload.php';

// GeoIP2 will be loaded conditionally when available

class MQTTTracker
{
    private ?CMSAPI $api = null;
    private array $config;
    private string $sessionId;
    private $geoipReader = null;
    
    public function __construct()
    {
        $this->loadConfig();
        $this->sessionId = $this->generateSessionId();
        $this->initializeGeoIP();
    }
    
    public function setAPI(CMSAPI $api): void
    {
        $this->api = $api;
        
        // Track page visit after API is available
        $this->trackPageVisit();
    }
    
    private function loadConfig(): void
    {
        $configFile = __DIR__ . '/config.json';
        $this->config = [
            'enabled' => true,
            'viewable' => false,
            'broker_host' => 'localhost',
            'broker_port' => 1883,
            'client_id' => 'codepress_cms',
            'username' => '',
            'password' => '',
            'topic_prefix' => 'codepress',
            'track_visitors' => true,
            'track_pages' => true,
            'track_performance' => true,
            'track_user_flows' => true,
            'session_timeout' => 1800,
            'geoip_database_path' => __DIR__ . '/GeoLite2-Country.mmdb'
        ];
        
        if (file_exists($configFile)) {
            $jsonConfig = json_decode(file_get_contents($configFile), true);
            $this->config = array_merge($this->config, $jsonConfig);
        }
    }
    
    private function initializeGeoIP(): void
    {
        $geoipPath = $this->config['geoip_database_path'] ?? __DIR__ . '/GeoLite2-Country.mmdb';
        
        // For now, disable GeoIP2 until properly configured
        $this->logMessage('info', 'GeoIP2 temporarily disabled - will be enabled when database is available');
        $this->geoipReader = null;
    }
    
    private function generateSessionId(): string
    {
        if (isset($_COOKIE['cms_session_id'])) {
            return $_COOKIE['cms_session_id'];
        }
        
        $sessionId = uniqid('cms_', true);
        setcookie('cms_session_id', $sessionId, [
            'expires' => time() + $this->config['session_timeout'],
            'path' => '/',
            'secure' => isset($_SERVER['HTTPS']),
            'httponly' => true,
            'samesite' => 'Lax'
        ]);
        return $sessionId;
    }
    
    private function trackPageVisit(): void
    {
        if (!$this->config['enabled'] || !$this->config['track_pages']) {
            return;
        }
        
        // Track user flow before updating current page
        $this->trackUserFlow();
        
        // Format URL nicely: ?page=foo/bar -> /page/foo/bar
        $pageUrl = $_SERVER['REQUEST_URI'] ?? '';
        if (isset($_GET['page'])) {
            $pageUrl = '/page/' . $_GET['page'];
            // Append other relevant params if needed, e.g., language
            if (isset($_GET['lang'])) {
                $pageUrl .= '?lang=' . $_GET['lang'];
            }
        }
        
        $clientIp = $this->getClientIp();
        $geoData = $this->getGeoData($clientIp);
        
        $pageData = [
            'timestamp' => date('c'),
            'session_id' => $this->sessionId,
            'page_url' => $pageUrl,
            'page_title' => $this->api ? $this->api->getCurrentPageTitle() : '',
            'referrer' => $_SERVER['HTTP_REFERER'] ?? '',
            'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
            'ip_address' => $clientIp,
            'country' => $geoData['country'],
            'country_code' => $geoData['country_code'],
            'city' => $geoData['city'],
            'language' => $this->api ? $this->api->getCurrentLanguage() : 'nl',
            'layout' => $this->api ? $this->getPageLayout() : 'unknown',
            'device_type' => $this->getDeviceType(),
            'browser' => $this->getBrowser(),
            'os' => $this->getOS()
        ];
        
        // Update tracking cookies
        setcookie('cms_previous_page', $pageUrl, [
            'expires' => time() + $this->config['session_timeout'],
            'path' => '/',
            'secure' => isset($_SERVER['HTTPS']),
            'httponly' => true,
            'samesite' => 'Lax'
        ]);
        setcookie('cms_page_timestamp', (string) time(), [
            'expires' => time() + $this->config['session_timeout'],
            'path' => '/',
            'secure' => isset($_SERVER['HTTPS']),
            'httponly' => true,
            'samesite' => 'Lax'
        ]);
        
        $this->publishMessage('page_visit', $pageData);
    }
    
    private function getPageLayout(): string
    {
        if (!$this->api) return 'unknown';
        
        $page = $this->api->getCurrentPage();
        return $page['layout'] ?? 'sidebar-content';
    }
    
    private function trackUserFlow(): void
    {
        if (!($this->config['track_user_flows'] ?? true)) {
            return;
        }
        
        $previousPage = $_COOKIE['cms_previous_page'] ?? null;
        $currentPage = $this->getCurrentPageUrl();
        $previousTimestamp = $_COOKIE['cms_page_timestamp'] ?? time();
        
        if ($previousPage && $previousPage !== $currentPage) {
            $flowData = [
                'timestamp' => date('c'),
                'session_id' => $this->sessionId,
                'from_page' => $previousPage,
                'to_page' => $currentPage,
                'flow_duration' => time() - $previousTimestamp,
                'ip_address' => $this->getClientIp()
            ];
            $this->publishMessage('user_flow', $flowData);
        }
    }
    
    private function getCurrentPageUrl(): string
    {
        $pageUrl = $_SERVER['REQUEST_URI'] ?? '';
        if (isset($_GET['page'])) {
            $pageUrl = '/page/' . $_GET['page'];
            if (isset($_GET['lang'])) {
                $pageUrl .= '?lang=' . $_GET['lang'];
            }
        }
        return $pageUrl;
    }
    
    private function getGeoData(string $ip): array
    {
        // Simplified geolocation - will be enhanced later
        return [
            'country' => 'Unknown',
            'country_code' => 'XX', 
            'city' => 'Unknown'
        ];
    }
    
    private function getDeviceType(): string
    {
        $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
        
        if (preg_match('/Mobile|Android|iPhone|iPad|iPod/', $userAgent)) {
            return preg_match('/iPad/', $userAgent) ? 'tablet' : 'mobile';
        }
        
        return 'desktop';
    }
    
    private function getBrowser(): string
    {
        $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
        
        if (preg_match('/Chrome/', $userAgent)) return 'Chrome';
        if (preg_match('/Firefox/', $userAgent)) return 'Firefox';
        if (preg_match('/Safari/', $userAgent)) return 'Safari';
        if (preg_match('/Edge/', $userAgent)) return 'Edge';
        if (preg_match('/Opera/', $userAgent)) return 'Opera';
        
        return 'Unknown';
    }
    
    private function getOS(): string
    {
        $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
        
        if (preg_match('/Windows/', $userAgent)) return 'Windows';
        if (preg_match('/Mac/', $userAgent)) return 'macOS';
        if (preg_match('/Linux/', $userAgent)) return 'Linux';
        if (preg_match('/Android/', $userAgent)) return 'Android';
        if (preg_match('/iOS|iPhone|iPad/', $userAgent)) return 'iOS';
        
        return 'Unknown';
    }
    
    private function getClientIp(): string
    {
        // Only trust REMOTE_ADDR by default - proxy headers can be spoofed
        // Configure trusted_proxies in config to enable proxy header support
        $remoteAddr = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
        $trustedProxies = $this->config['trusted_proxies'] ?? [];
        
        if (!empty($trustedProxies) && in_array($remoteAddr, $trustedProxies)) {
            // Only trust proxy headers when request comes from a known proxy
            if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
                return $_SERVER['HTTP_CF_CONNECTING_IP'];
            }
            
            $ipKeys = ['HTTP_X_FORWARDED_FOR', 'HTTP_X_REAL_IP', 'HTTP_CLIENT_IP'];
            foreach ($ipKeys as $key) {
                if (!empty($_SERVER[$key])) {
                    $ips = explode(',', $_SERVER[$key]);
                    $ip = trim($ips[0]);
                    if (filter_var($ip, FILTER_VALIDATE_IP)) {
                        return $ip;
                    }
                }
            }
        }
        
        return $remoteAddr;
    }
    
    private function publishMessage(string $topic, array $data): void
    {
        if (!class_exists('PhpMqtt\Client\MqttClient')) {
            $this->logMessage('error', 'MQTT client library not installed. Run: composer require php-mqtt/client');
            return;
        }
        
        try {
            $server = new \PhpMqtt\Client\MqttClient(
                $this->config['broker_host'],
                $this->config['broker_port'],
                $this->config['client_id']
            );
            
            $connectionSettings = new \PhpMqtt\Client\ConnectionSettings();
            
            if (!empty($this->config['username'])) {
                $connectionSettings->setUsername($this->config['username'])
                                 ->setPassword($this->config['password']);
            }
            
            $server->connect($connectionSettings, true);
            
            // Topic format: prefix/action
            $topic = $this->config['topic_prefix'] . '/' . $topic;
            $payload = json_encode($data);
            
            $server->publish($topic, $payload, 0);
            $server->disconnect();
            
            $this->logMessage('published', $topic . ' - ' . $payload);
        } catch (Exception $e) {
            $this->logMessage('error', 'MQTT publish failed: ' . $e->getMessage());
        }
    }
    
    private function logMessage(string $topic, string $payload): void
    {
        $logFile = __DIR__ . '/mqtt_tracker.log';
        $logEntry = date('Y-m-d H:i:s') . " [{$topic}] {$payload}\n";
        file_put_contents($logFile, $logEntry, FILE_APPEND | LOCK_EX);
    }
    
    public function getSidebarContent(): string
    {
        // MQTT Tracker is een functionele plugin zonder UI
        return '';
    }
    
    
    
    public function getConfig(): array
    {
        return $this->config;
    }
    
    public function updateConfig(array $newConfig): void
    {
        $this->config = array_merge($this->config, $newConfig);
        
        $configFile = __DIR__ . '/config.json';
        file_put_contents($configFile, json_encode($this->config, JSON_PRETTY_PRINT));
    }
}