<?php
namespace App\Models;
use CodeIgniter\Model;

class ApiLogModel extends Model
{
    // Ayrı veritabanı bağlantısını kullan
    protected $DBGroup = 'api_logs';
    
    protected $table      = 'api_logs';
    protected $primaryKey = 'id';
    
    protected $useAutoIncrement = true;
    protected $returnType     = 'array';
    
    protected $allowedFields = [
        'request_time', 'ip_address', 'uri', 'method', 
        'request_headers', 'request_body', 'response_code', 
        'response_body', 'execution_time', 'user_id', 
        'user_agent', 'device_info', 'error_type', 
        'error_severity', 'error_message'
    ];
    
    protected $useTimestamps = false;
    
    /**
     * Gerçek client IP adresini al - CloudFlare, proxy, load balancer desteği ile
     */
       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';
    }
    
    
    /**
     * Yanıt gövdesinden hata bilgilerini çıkarıp kaydetme
     */
    public function extractErrorInfo($responseBody)
    {
        $data = [];
        
        // JSON yanıt kontrolü
        if (!empty($responseBody)) {
            $jsonResponse = json_decode($responseBody, true);
            
            if (json_last_error() === JSON_ERROR_NONE) {
                // API yanıtında hata mesajı kontrolü
                if (isset($jsonResponse['error']) || isset($jsonResponse['message'])) {
                    $data['error_type'] = 'API_ERROR';
                    $data['error_severity'] = 'WARNING';
                    $data['error_message'] = isset($jsonResponse['error']) ? $jsonResponse['error'] : $jsonResponse['message'];
                }
            }
        }
        
        return $data;
    }
    
    /**
     * Temel API isteği kaydetme
     */
   public function logRequest($data)
    {
        // ✅ HER ZAMAN gerçek IP'yi al - gelen IP'yi OVERRIDE et
        $data['ip_address'] = $this->getRealClientIP();
        
        // Debug log ekle
        log_message('debug', '📝 API Log kaydediliyor - IP: ' . $data['ip_address'] . 
                            ', URI: ' . ($data['uri'] ?? 'N/A') . 
                            ', Method: ' . ($data['method'] ?? 'N/A'));
        
        // Yanıt gövdesinden hata bilgilerini çıkar
        $errorInfo = $this->extractErrorInfo($data['response_body'] ?? '');
        
        // Hata bilgisi varsa ekle
        if (!empty($errorInfo)) {
            $data = array_merge($data, $errorInfo);
        }
        
        try {
            $result = $this->insert($data);
            
            if ($result) {
                log_message('debug', '✅ API Log başarıyla kaydedildi - ID: ' . $this->insertID() . ', IP: ' . $data['ip_address']);
            } else {
                log_message('error', '❌ API Log kaydedilemedi - IP: ' . $data['ip_address']);
            }
            
            return $result;
        } catch (\Exception $e) {
            log_message('error', '❌ API Log kayıt hatası: ' . $e->getMessage() . ', IP: ' . $data['ip_address']);
            return false;
        }
    }
    
    /**
     * PHP hatası kaydetme
     */
    public function logPhpError($errorType, $severity, $message, $requestData)
    {
        // ✅ HER ZAMAN gerçek IP'yi al - gelen IP'yi OVERRIDE et
        $requestData['ip_address'] = $this->getRealClientIP();
        
        $data = array_merge($requestData, [
            'error_type' => $errorType,
            'error_severity' => $severity,
            'error_message' => $message
        ]);
        
        log_message('debug', '📝 PHP Error Log kaydediliyor - IP: ' . $data['ip_address'] . 
                            ', Type: ' . $errorType . 
                            ', Severity: ' . $severity);
        
        try {
            $result = $this->insert($data);
            
            if ($result) {
                log_message('debug', '✅ PHP Error Log başarıyla kaydedildi - ID: ' . $this->insertID() . ', IP: ' . $data['ip_address']);
            } else {
                log_message('error', '❌ PHP Error Log kaydedilemedi - IP: ' . $data['ip_address']);
            }
            
            return $result;
        } catch (\Exception $e) {
            log_message('error', '❌ PHP Error Log kayıt hatası: ' . $e->getMessage() . ', IP: ' . $data['ip_address']);
            return false;
        }
    }
    
    /**
     * Tarih aralığına göre logları getir
     */
    public function getLogsByDateRange($startDate, $endDate, $limit = 50, $offset = 0)
    {
        return $this->where('request_time >=', $startDate)
                    ->where('request_time <=', $endDate)
                    ->orderBy('request_time', 'DESC')
                    ->findAll($limit, $offset);
    }
    
    /**
     * URI'ye göre logları getir
     */
    public function getLogsByUri($uri, $limit = 50, $offset = 0)
    {
        return $this->like('uri', $uri)
                    ->orderBy('request_time', 'DESC')
                    ->findAll($limit, $offset);
    }
    
    /**
     * Kullanıcı ID'sine göre logları getir
     */
    public function getLogsByUser($userId, $limit = 50, $offset = 0)
    {
        return $this->where('user_id', $userId)
                    ->orderBy('request_time', 'DESC')
                    ->findAll($limit, $offset);
    }
    
    /**
     * Hata loglarını getir
     */
    public function getErrorLogs($limit = 50, $offset = 0)
    {
        return $this->where('response_code >=', 400)
                    ->orWhere('error_type IS NOT NULL')
                    ->orderBy('request_time', 'DESC')
                    ->findAll($limit, $offset);
    }
    
    /**
     * Hata tipine göre logları getir
     */
    public function getLogsByErrorType($errorType, $limit = 50, $offset = 0)
    {
        return $this->where('error_type', $errorType)
                    ->orderBy('request_time', 'DESC')
                    ->findAll($limit, $offset);
    }
    
    /**
     * Hata ciddiyetine göre logları getir
     */
    public function getLogsByErrorSeverity($severity, $limit = 50, $offset = 0)
    {
        return $this->where('error_severity', $severity)
                    ->orderBy('request_time', 'DESC')
                    ->findAll($limit, $offset);
    }
    
    /**
     * Özet hata raporu al
     */
    public function getErrorSummary($days = 7)
    {
        $db = \Config\Database::connect();
        
        $fromDate = date('Y-m-d H:i:s', strtotime("-$days days"));
        
        $query = $db->query("
            SELECT 
                error_type, 
                error_severity, 
                COUNT(*) as count,
                MAX(request_time) as last_occurrence
            FROM 
                {$this->table}
            WHERE 
                error_type IS NOT NULL 
                AND request_time >= ?
            GROUP BY 
                error_type, error_severity
            ORDER BY 
                count DESC, last_occurrence DESC
        ", [$fromDate]);
        
        return $query->getResultArray();
    }
    
     /**
     * IP adresine göre istek sayısı
     */
    public function getRequestCountByIP($hours = 24)
    {
        $db = \Config\Database::connect();
        
        $fromTime = date('Y-m-d H:i:s', strtotime("-$hours hours"));
        
        $query = $db->query("
            SELECT 
                ip_address,
                COUNT(*) as request_count,
                MAX(request_time) as last_request,
                MIN(request_time) as first_request
            FROM 
                {$this->table}
            WHERE 
                request_time >= ?
            GROUP BY 
                ip_address
            ORDER BY 
                request_count DESC
            LIMIT 100
        ", [$fromTime]);
        
        return $query->getResultArray();
    }
    
    /**
     * En çok kullanılan endpoint'ler
     */
    public function getTopEndpoints($hours = 24, $limit = 20)
    {
        $db = \Config\Database::connect();
        
        $fromTime = date('Y-m-d H:i:s', strtotime("-$hours hours"));
        
        $query = $db->query("
            SELECT 
                uri,
                method,
                COUNT(*) as request_count,
                AVG(execution_time) as avg_execution_time,
                MAX(execution_time) as max_execution_time,
                MIN(execution_time) as min_execution_time
            FROM 
                {$this->table}
            WHERE 
                request_time >= ?
            GROUP BY 
                uri, method
            ORDER BY 
                request_count DESC
            LIMIT ?
        ", [$fromTime, $limit]);
        
        return $query->getResultArray();
    }
    
    /**
     * IP bazlı istatistikler
     */
    public function getIPStatistics($ipAddress, $hours = 24)
    {
        $fromTime = date('Y-m-d H:i:s', strtotime("-$hours hours"));
        
        $stats = [
            'total_requests' => $this->where('ip_address', $ipAddress)
                                    ->where('request_time >=', $fromTime)
                                    ->countAllResults(),
            
            'error_count' => $this->where('ip_address', $ipAddress)
                                 ->where('request_time >=', $fromTime)
                                 ->where('response_code >=', 400)
                                 ->countAllResults(),
            
            'last_request' => $this->where('ip_address', $ipAddress)
                                  ->orderBy('request_time', 'DESC')
                                  ->first(),
            
            'endpoints' => $this->select('uri, method, COUNT(*) as count')
                               ->where('ip_address', $ipAddress)
                               ->where('request_time >=', $fromTime)
                               ->groupBy('uri, method')
                               ->orderBy('count', 'DESC')
                               ->limit(10)
                               ->findAll()
        ];
        
        return $stats;
    }

}