<?php
/**
 * GoogleApi - Google API Entegrasyonları
 * Aegean Dominance Admin Panel
 * 
 * Indexing API, Search Console, Analytics entegrasyonu
 */

declare(strict_types=1);

class GoogleApi
{
    private Database $db;
    private ?string $serviceAccountJson = null;
    private ?string $accessToken = null;
    
    private const INDEXING_API_URL = 'https://indexing.googleapis.com/v3/urlNotifications:publish';
    private const TOKEN_URL = 'https://oauth2.googleapis.com/token';
    
    public function __construct()
    {
        $this->db = Database::getInstance();
        $this->loadCredentials();
    }
    
    /**
     * API kimlik bilgilerini yükle
     */
    private function loadCredentials(): void
    {
        try {
            // api_settings tablosu var mı kontrol et
            $tableExists = $this->db->fetchColumn(
                "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'api_settings'"
            );
            
            if (!$tableExists) {
                return;
            }
            
            $json = $this->db->fetchColumn(
                "SELECT setting_value FROM api_settings WHERE setting_key = 'google_service_account'"
            );
            
            if ($json) {
                $decrypted = $this->decrypt($json);
                if ($decrypted) {
                    $this->serviceAccountJson = $decrypted;
                }
            }
        } catch (Exception $e) {
            error_log("GoogleApi::loadCredentials error: " . $e->getMessage());
        }
    }
    
    // =========================================================================
    // INDEXING API
    // =========================================================================
    
    /**
     * URL'i Google'a bildir (Indexing API)
     */
    public function requestIndexing(string $url, string $type = 'URL_UPDATED'): array
    {
        try {
            if (!$this->serviceAccountJson) {
                return ['success' => false, 'error' => 'Google API yapılandırılmamış.'];
            }
            
            $accessToken = $this->getAccessToken();
            if (!$accessToken) {
                return ['success' => false, 'error' => 'Access token alınamadı.'];
            }
            
            $data = [
                'url' => $url,
                'type' => $type // URL_UPDATED veya URL_DELETED
            ];
            
            $response = $this->curlRequest(self::INDEXING_API_URL, [
                'method' => 'POST',
                'headers' => [
                    'Authorization: Bearer ' . $accessToken,
                    'Content-Type: application/json'
                ],
                'body' => json_encode($data)
            ]);
            
            if ($response['http_code'] === 200) {
                // Log kaydı
                $this->logApiCall('indexing', $url, true, $response['body']);
                
                return [
                    'success' => true,
                    'message' => 'URL başarıyla Google\'a bildirildi.',
                    'response' => json_decode($response['body'], true)
                ];
            }
            
            $this->logApiCall('indexing', $url, false, $response['body']);
            
            return [
                'success' => false,
                'error' => 'İndeksleme isteği başarısız.',
                'details' => json_decode($response['body'], true)
            ];
            
        } catch (Exception $e) {
            error_log("GoogleApi::requestIndexing error: " . $e->getMessage());
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
    
    /**
     * Toplu indeksleme
     */
    public function batchIndexing(array $urls): array
    {
        $results = [];
        
        foreach ($urls as $url) {
            $results[$url] = $this->requestIndexing($url);
            usleep(100000); // 100ms bekle (rate limit)
        }
        
        return $results;
    }
    
    // =========================================================================
    // ACCESS TOKEN
    // =========================================================================
    
    /**
     * Service Account ile access token al
     */
    private function getAccessToken(): ?string
    {
        if ($this->accessToken) {
            return $this->accessToken;
        }
        
        try {
            $credentials = json_decode($this->serviceAccountJson, true);
            
            if (!$credentials) {
                throw new Exception('Geçersiz service account JSON');
            }
            
            // JWT oluştur
            $jwt = $this->createJwt($credentials);
            
            // Token al
            $response = $this->curlRequest(self::TOKEN_URL, [
                'method' => 'POST',
                'headers' => ['Content-Type: application/x-www-form-urlencoded'],
                'body' => http_build_query([
                    'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
                    'assertion' => $jwt
                ])
            ]);
            
            if ($response['http_code'] === 200) {
                $data = json_decode($response['body'], true);
                $this->accessToken = $data['access_token'] ?? null;
                return $this->accessToken;
            }
            
            throw new Exception('Token alınamadı: ' . $response['body']);
            
        } catch (Exception $e) {
            error_log("GoogleApi::getAccessToken error: " . $e->getMessage());
            return null;
        }
    }
    
    /**
     * JWT token oluştur
     */
    private function createJwt(array $credentials): string
    {
        $header = [
            'alg' => 'RS256',
            'typ' => 'JWT'
        ];
        
        $now = time();
        $payload = [
            'iss' => $credentials['client_email'],
            'scope' => 'https://www.googleapis.com/auth/indexing',
            'aud' => self::TOKEN_URL,
            'iat' => $now,
            'exp' => $now + 3600
        ];
        
        $headerEncoded = $this->base64UrlEncode(json_encode($header));
        $payloadEncoded = $this->base64UrlEncode(json_encode($payload));
        
        $signatureInput = $headerEncoded . '.' . $payloadEncoded;
        
        // RSA imza
        $privateKey = openssl_pkey_get_private($credentials['private_key']);
        openssl_sign($signatureInput, $signature, $privateKey, OPENSSL_ALGO_SHA256);
        
        $signatureEncoded = $this->base64UrlEncode($signature);
        
        return $signatureInput . '.' . $signatureEncoded;
    }
    
    /**
     * Base64 URL encode
     */
    private function base64UrlEncode(string $data): string
    {
        return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
    }
    
    // =========================================================================
    // AYAR YÖNETİMİ
    // =========================================================================
    
    /**
     * API ayarı kaydet
     */
    public function saveSetting(string $key, string $value, bool $encrypt = false): bool
    {
        try {
            $storedValue = $encrypt ? $this->encrypt($value) : $value;
            
            $this->db->execute(
                "INSERT INTO api_settings (setting_key, setting_value, is_encrypted) 
                 VALUES (?, ?, ?)
                 ON DUPLICATE KEY UPDATE setting_value = ?, is_encrypted = ?",
                [$key, $storedValue, $encrypt, $storedValue, $encrypt]
            );
            
            return true;
        } catch (Exception $e) {
            error_log("GoogleApi::saveSetting error: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * API ayarı al
     */
    public function getSetting(string $key): ?string
    {
        try {
            $result = $this->db->fetchOne(
                "SELECT setting_value, is_encrypted FROM api_settings WHERE setting_key = ?",
                [$key]
            );
            
            if (!$result) return null;
            
            return $result['is_encrypted'] 
                ? $this->decrypt($result['setting_value']) 
                : $result['setting_value'];
                
        } catch (Exception $e) {
            error_log("GoogleApi::getSetting error: " . $e->getMessage());
            return null;
        }
    }
    
    /**
     * Service Account JSON kaydet
     */
    public function saveServiceAccount(string $json): array
    {
        try {
            // JSON doğrula
            $data = json_decode($json, true);
            if (!$data || !isset($data['client_email']) || !isset($data['private_key'])) {
                return ['success' => false, 'error' => 'Geçersiz Service Account JSON formatı.'];
            }
            
            $this->saveSetting('google_service_account', $json, true);
            
            return [
                'success' => true,
                'message' => 'Service Account başarıyla kaydedildi.',
                'email' => $data['client_email']
            ];
            
        } catch (Exception $e) {
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
    
    // =========================================================================
    // ŞİFRELEME
    // =========================================================================
    
    private function getEncryptionKey(): string
    {
        // Sabit bir encryption key (production'da .env'den alınmalı)
        return hash('sha256', 'AegeanDominance2025SecretKey!');
    }
    
    private function encrypt(string $data): string
    {
        $key = $this->getEncryptionKey();
        $iv = random_bytes(16);
        $encrypted = openssl_encrypt($data, 'AES-256-CBC', $key, 0, $iv);
        return base64_encode($iv . $encrypted);
    }
    
    private function decrypt(string $data): ?string
    {
        try {
            if (empty($data)) {
                return null;
            }
            $key = $this->getEncryptionKey();
            $decoded = base64_decode($data);
            if ($decoded === false || strlen($decoded) < 16) {
                return null;
            }
            $iv = substr($decoded, 0, 16);
            $encrypted = substr($decoded, 16);
            $result = openssl_decrypt($encrypted, 'AES-256-CBC', $key, 0, $iv);
            return $result !== false ? $result : null;
        } catch (Exception $e) {
            error_log("GoogleApi::decrypt error: " . $e->getMessage());
            return null;
        }
    }
    
    // =========================================================================
    // CURL HELPER
    // =========================================================================
    
    private function curlRequest(string $url, array $options = []): array
    {
        $ch = curl_init();
        
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_SSL_VERIFYPEER => true
        ]);
        
        if (($options['method'] ?? 'GET') === 'POST') {
            curl_setopt($ch, CURLOPT_POST, true);
            if (isset($options['body'])) {
                curl_setopt($ch, CURLOPT_POSTFIELDS, $options['body']);
            }
        }
        
        if (isset($options['headers'])) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $options['headers']);
        }
        
        $body = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        
        curl_close($ch);
        
        if ($error) {
            throw new Exception("cURL Error: {$error}");
        }
        
        return [
            'http_code' => $httpCode,
            'body' => $body
        ];
    }
    
    // =========================================================================
    // LOGLAMA
    // =========================================================================
    
    private function logApiCall(string $type, string $url, bool $success, string $response): void
    {
        try {
            // Basit dosya log
            $logFile = ROOT_PATH . '/logs/google_api.log';
            $logDir = dirname($logFile);
            
            if (!is_dir($logDir)) {
                mkdir($logDir, 0755, true);
            }
            
            $logEntry = sprintf(
                "[%s] %s | %s | %s | %s\n",
                date('Y-m-d H:i:s'),
                $type,
                $url,
                $success ? 'SUCCESS' : 'FAILED',
                substr($response, 0, 200)
            );
            
            file_put_contents($logFile, $logEntry, FILE_APPEND | LOCK_EX);
            
        } catch (Exception $e) {
            error_log("GoogleApi::logApiCall error: " . $e->getMessage());
        }
    }
    
    /**
     * API yapılandırılmış mı kontrol
     */
    public function isConfigured(): bool
    {
        return $this->serviceAccountJson !== null;
    }
}

/**
 * GoogleApi helper
 */
function googleApi(): GoogleApi
{
    static $instance = null;
    if ($instance === null) {
        $instance = new GoogleApi();
    }
    return $instance;
}
