<?php

namespace App\Filters;

use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Services;

class ApiLogger implements FilterInterface
{
    /**
     * Gerçek client IP adresini al - AnalyticsController, DeviceModel, ApiLogModel ile AYNI
     */
    private function getRealClientIP()
    {
        $ip_keys = array(
            'HTTP_CF_CONNECTING_IP',      // CloudFlare
            'HTTP_X_REAL_IP',              // Nginx proxy
            'HTTP_CLIENT_IP',              // Shared Internet
            'HTTP_X_FORWARDED_FOR',        // Proxy
            'HTTP_X_FORWARDED',
            'HTTP_X_CLUSTER_CLIENT_IP',
            'HTTP_FORWARDED_FOR',
            'HTTP_FORWARDED',
            'REMOTE_ADDR'                  // Direct connection
        );
        
        foreach ($ip_keys as $key) {
            if (array_key_exists($key, $_SERVER) === true) {
                foreach (explode(',', $_SERVER[$key]) as $ip) {
                    $ip = trim($ip);
                    
                    // Özel IP aralıklarını ve reserved IP'leri filtrele
                    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false) {
                        return $ip;
                    }
                }
            }
        }
        
        // Fallback - en son çare olarak REMOTE_ADDR
        return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
    }
    
    public function before(RequestInterface $request, $arguments = null)
    {
        // İstek başlangıç zamanını kaydet
        $request->apiLogStartTime = microtime(true);
        return $request;
    }

    public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
    {
        // Loglama dosyası
        $logFile = WRITEPATH . 'logs/apilogger_debug.log';
        
        // URI bilgisini kaydet
        $uri = $request->getUri()->getPath();
        
        // ✅ Gerçek IP'yi al
        $realIP = $this->getRealClientIP();
        
        file_put_contents($logFile, date('Y-m-d H:i:s') . " - URI: " . $uri . ", Real IP: " . $realIP . "\n", FILE_APPEND);
        
        // ÖNEMLİ: Belirli URI'leri filtreleyebilirsiniz (isteğe bağlı)
        // Örneğin: sadece /api/ ile başlayanları loglamak için:
        // if (strpos($uri, '/api/') !== 0) {
        //     return $response;
        // }
        
        file_put_contents($logFile, date('Y-m-d H:i:s') . " - API isteği tespit edildi, loglama yapılıyor.\n", FILE_APPEND);
        
        try {
            // İstek gövdesini al - ✅ null kontrolü ekle
            $requestBody = $request->getBody();
            $requestBody = is_string($requestBody) ? $requestBody : '';
            
            // Yanıt gövdesini al - ✅ null kontrolü ekle
            $responseBody = $response->getBody();
            $responseBody = is_string($responseBody) ? $responseBody : '';
            
            // Çok büyükse kısalt (max 10KB)
            if (strlen($responseBody) > 10240) {
                $responseBody = substr($responseBody, 0, 10240) . '... [truncated]';
            }
            
            if (strlen($requestBody) > 10240) {
                $requestBody = substr($requestBody, 0, 10240) . '... [truncated]';
            }
            
            // Kullanıcı ID'sini al
            $userId = null;
            $tokenParam = $request->getGet('token');
            
            if (!empty($tokenParam)) {
                try {
                    $tokenModel = model('App\Models\TokenModel');
                    $token = $tokenModel->where('token', $tokenParam)->first();
                    if ($token) {
                        $userId = $token['user_id'];
                    }
                } catch (\Exception $e) {
                    file_put_contents($logFile, date('Y-m-d H:i:s') . " - Token sorgusunda hata: " . $e->getMessage() . "\n", FILE_APPEND);
                }
            }
            
            // JSON request body'den token'ı kontrol et
            if ($userId === null && !empty($requestBody)) {
                $jsonBody = json_decode($requestBody, true);
                if (json_last_error() === JSON_ERROR_NONE) {
                    if (isset($jsonBody['token'])) {
                        try {
                            $tokenModel = model('App\Models\TokenModel');
                            $token = $tokenModel->where('token', $jsonBody['token'])->first();
                            if ($token) {
                                $userId = $token['user_id'];
                            }
                        } catch (\Exception $e) {
                            // Sessizce devam et
                        }
                    } elseif (isset($jsonBody['user_id'])) {
                        $userId = $jsonBody['user_id'];
                    }
                }
            }
            
            // İstek başlıklarını al, hassas bilgileri filtrele
            $headers = $request->getHeaders();
            $filteredHeaders = [];
            foreach ($headers as $name => $value) {
                if (strtolower($name) !== 'authorization' && strtolower($name) !== 'cookie') {
                    $filteredHeaders[$name] = $value->getValueLine();
                }
            }
            
            // Cihaz bilgilerini al
            $deviceInfo = [];
            if (!empty($requestBody)) {
                $jsonBody = json_decode($requestBody, true);
                if (json_last_error() === JSON_ERROR_NONE) {
                    $deviceFields = [
                        'platform', 'device_name', 'system_name', 'system_version',
                        'brand', 'device_brand', 'device_model', 'android_version',
                        'manufacturer', 'fcmToken', 'device_uuid'
                    ];
                    
                    foreach ($deviceFields as $field) {
                        if (isset($jsonBody[$field])) {
                            $deviceInfo[$field] = $jsonBody[$field];
                        }
                    }
                }
            }
            
            // Execution time hesapla
            $executionTime = 0;
            if (isset($request->apiLogStartTime)) {
                $executionTime = round((microtime(true) - $request->apiLogStartTime) * 1000, 2); // ms
            } else {
                $executionTime = round((microtime(true) - ($_SERVER['REQUEST_TIME_FLOAT'] ?? microtime(true))) * 1000, 2);
            }
            
            // ✅ ÖNEMLI: ip_address'i GÖNDERMEDEN log verilerini hazırla
            // ApiLogModel'in logRequest metodu IP'yi kendisi alacak
            $logData = [
                'request_time'    => date('Y-m-d H:i:s'),
                // 'ip_address' => GÖNDERMEDEN - Model içinde alınacak
                'uri'             => $uri,
                'method'          => $request->getMethod(),
                'request_headers' => json_encode($filteredHeaders, JSON_UNESCAPED_UNICODE),
                'request_body'    => $requestBody,
                'response_code'   => $response->getStatusCode(),
                'response_body'   => $responseBody,
                'execution_time'  => $executionTime,
                'user_id'         => $userId,
                'user_agent'      => $request->getUserAgent()->getAgentString(),
                'device_info'     => !empty($deviceInfo) ? json_encode($deviceInfo, JSON_UNESCAPED_UNICODE) : null
            ];
            
            // Hassas bilgileri maskeleme (isteğe bağlı - şu an yorumda)
            /*
            if (!empty($logData['request_body'])) {
                $jsonBody = json_decode($logData['request_body'], true);
                if (json_last_error() === JSON_ERROR_NONE) {
                    $sensitiveFields = ['password', 'password_repeat', 'token', 'fcmToken', 'auth_uid'];
                    foreach ($sensitiveFields as $field) {
                        if (isset($jsonBody[$field])) {
                            $jsonBody[$field] = '***GIZLENDI***';
                        }
                    }
                    $logData['request_body'] = json_encode($jsonBody);
                }
            }
            */
            
            // Log modelini yükle ve kaydı gerçekleştir
            try {
                $logModel = model('App\Models\ApiLogModel');
                
                // ✅ logRequest metodu IP'yi kendisi alacak
                $result = $logModel->logRequest($logData);
                
                file_put_contents($logFile, date('Y-m-d H:i:s') . " - Log kaydı sonucu: " . ($result ? "Başarılı" : "Başarısız") . ", Real IP: " . $realIP . "\n", FILE_APPEND);
            } catch (\Exception $e) {
                file_put_contents($logFile, date('Y-m-d H:i:s') . " - Model/DB hatası: " . $e->getMessage() . "\n", FILE_APPEND);
                file_put_contents($logFile, $e->getTraceAsString() . "\n", FILE_APPEND);
            }
            
        } catch (\Exception $e) {
            file_put_contents($logFile, date('Y-m-d H:i:s') . " - Genel hata: " . $e->getMessage() . "\n", FILE_APPEND);
            file_put_contents($logFile, $e->getTraceAsString() . "\n", FILE_APPEND);
        }
        
        return $response;
    }
}