<?php
/**
 * iyzico Ödeme Entegrasyonu
 * Checkout Form (iframe) ile güvenli ödeme
 * Manuel Kurulum Versiyonu (Composer Gerektirmez)
 * 
 * @version 1.2.0
 */

// SDK yüklenmiş mi kontrol et
if (!defined('IYZICO_SDK_LOADED') || !IYZICO_SDK_LOADED) {
    // Bir kez daha dene
    $bootstrapPath = dirname(__DIR__) . '/iyzipay-php/IyzipayBootstrap.php';
    if (file_exists($bootstrapPath)) {
        require_once $bootstrapPath;
        \IyzipayBootstrap::init();
        define('IYZICO_SDK_LOADED', true);
    } else {
        if (!defined('IYZICO_SDK_LOADED')) {
            define('IYZICO_SDK_LOADED', false);
        }
    }
}

class IyzicoPayment
{
    private $apiKey;
    private $secretKey;
    private $baseUrl;
    private $options;
    private $db;
    private $settings;
    private $isSandbox;
    
    /**
     * Constructor
     */
    public function __construct($db, $settings)
    {
        $this->db = $db;
        $this->settings = $settings;
        
        $this->apiKey = $this->getSettingValue('iyzico_api_key', '');
        $this->secretKey = $this->getSettingValue('iyzico_secret_key', '');
        $this->isSandbox = $this->getSettingValue('iyzico_sandbox', '1') == '1';
        
        // Base URL belirleme
        $this->baseUrl = $this->isSandbox 
            ? 'https://sandbox-api.iyzipay.com' 
            : 'https://api.iyzipay.com';
        
        // iyzico options - SDK yüklüyse
        if (class_exists('\Iyzipay\Options')) {
            $this->options = new \Iyzipay\Options();
            $this->options->setApiKey($this->apiKey);
            $this->options->setSecretKey($this->secretKey);
            $this->options->setBaseUrl($this->baseUrl);
        }
    }
    
    /**
     * Ayar değerini al (Settings objesi veya array olabilir)
     */
    private function getSettingValue($key, $default = null)
    {
        if (is_object($this->settings) && method_exists($this->settings, 'get')) {
            return $this->settings->get($key, $default);
        } elseif (is_array($this->settings)) {
            return $this->settings[$key] ?? $default;
        }
        return $default;
    }
    
    /**
     * SDK yüklü mü kontrol et
     */
    public function isSDKLoaded(): bool
    {
        return class_exists('\Iyzipay\Options');
    }
    
    /**
     * iyzico aktif mi kontrol et
     */
    public function isEnabled(): bool
    {
        return $this->isSDKLoaded()
            && $this->getSettingValue('iyzico_enabled', '0') == '1' 
            && !empty($this->apiKey) 
            && !empty($this->secretKey);
    }
    
    /**
     * 3D Secure aktif mi
     */
    public function is3DEnabled(): bool
    {
        return $this->getSettingValue('iyzico_3d_enabled', '0') == '1';
    }
    
    /**
     * Taksit aktif mi
     */
    public function isInstallmentEnabled(): bool
    {
        return $this->getSettingValue('iyzico_installment_enabled', '1') == '1';
    }
    
    /**
     * Maksimum taksit sayısı
     */
    public function getMaxInstallment(): int
    {
        return (int)$this->getSettingValue('iyzico_max_installment', 12);
    }
    
    /**
     * Sandbox modu mu
     */
    public function isSandbox(): bool
    {
        return $this->isSandbox;
    }
    
    /**
     * API bağlantı testi
     * @return array
     */
    public function testConnection(): array
    {
        $result = [
            'success' => false,
            'error' => null,
            'message' => null
        ];
        
        // SDK kontrolü
        if (!$this->isSDKLoaded()) {
            $result['error'] = 'iyzico SDK yüklü değil. Lütfen iyzipay-php klasörünü kontrol edin.';
            return $result;
        }
        
        // API key kontrolü
        if (empty($this->apiKey) || empty($this->secretKey)) {
            $result['error'] = 'API Key ve Secret Key boş olamaz.';
            return $result;
        }
        
        try {
            // Basit bir BIN sorgulama ile test yap
            $request = new \Iyzipay\Request\RetrieveInstallmentInfoRequest();
            $request->setLocale(\Iyzipay\Model\Locale::TR);
            $request->setConversationId('test_' . time() . '_' . rand(1000, 9999));
            $request->setBinNumber('552879'); // Test BIN numarası (Mastercard)
            $request->setPrice('100');
            
            $installmentInfo = \Iyzipay\Model\InstallmentInfo::retrieve($request, $this->options);
            
            if ($installmentInfo->getStatus() === 'success') {
                $result['success'] = true;
                $result['message'] = 'API bağlantısı başarılı! ' . ($this->isSandbox ? '(Sandbox Modu)' : '(Production Modu)');
            } else {
                $errorMsg = $installmentInfo->getErrorMessage();
                $errorCode = $installmentInfo->getErrorCode();
                $result['error'] = $errorMsg ?: 'API yanıt vermedi. API anahtarlarınızı kontrol edin.';
                if ($errorCode) {
                    $result['error'] .= ' (Kod: ' . $errorCode . ')';
                }
            }
            
        } catch (\Exception $e) {
            $result['error'] = 'Bağlantı hatası: ' . $e->getMessage();
        }
        
        return $result;
    }
    
    /**
     * Checkout Form başlat
     * 
     * @param array $orderData Sipariş bilgileri
     * @param array $customerData Müşteri bilgileri
     * @param string $callbackUrl Callback URL
     * @return array
     */
    public function initCheckoutForm(array $orderData, array $customerData, string $callbackUrl): array
    {
        if (!$this->isSDKLoaded()) {
            return [
                'success' => false,
                'error_code' => 'SDK_NOT_LOADED',
                'error_message' => 'iyzico SDK yüklü değil. Lütfen iyzipay-php klasörünü kontrol edin.'
            ];
        }
        
        try {
            // Unique conversation ID oluştur
            $conversationId = 'IYZICO_' . $orderData['order_number'] . '_' . time();
            
            // Request oluştur
            $request = new \Iyzipay\Request\CreateCheckoutFormInitializeRequest();
            $request->setLocale(\Iyzipay\Model\Locale::TR);
            $request->setConversationId($conversationId);
            $request->setPrice(number_format($orderData['base_price'], 2, '.', ''));
            $request->setPaidPrice(number_format($orderData['total_price'], 2, '.', ''));
            $request->setCurrency(\Iyzipay\Model\Currency::TL);
            $request->setBasketId($orderData['order_number']);
            $request->setPaymentGroup(\Iyzipay\Model\PaymentGroup::PRODUCT);
            $request->setCallbackUrl($callbackUrl);
            
            // ==================== MOBİL İÇİN KRİTİK PARAMETRELER ====================
            // PaymentSource ile iyzico'ya platformu bildir
            // Bu sayede paymentPageUrl dönüşü garanti olur
            if ($this->isMobile()) {
                $request->setPaymentSource('MOBILE');
            }
            
            // 3D Secure zorunlu mu?
            if ($this->is3DEnabled()) {
                $request->setForceThreeDS(1);
            }
            
            // Taksit seçenekleri
            if ($this->isInstallmentEnabled()) {
                $maxInstallment = $this->getMaxInstallment();
                $installments = [];
                for ($i = 1; $i <= $maxInstallment; $i++) {
                    $installments[] = $i;
                }
                $request->setEnabledInstallments($installments);
            } else {
                $request->setEnabledInstallments([1]);
            }
            
            // Alıcı bilgileri
            $buyer = new \Iyzipay\Model\Buyer();
            $buyer->setId($customerData['user_id'] ?? 'GUEST_' . time());
            $buyer->setName($this->getFirstName($customerData['name']));
            $buyer->setSurname($this->getLastName($customerData['name']));
            $buyer->setGsmNumber($this->formatPhone($customerData['phone']));
            $buyer->setEmail($customerData['email']);
            $buyer->setIdentityNumber('11111111111'); // TC zorunlu değilse varsayılan
            $buyer->setRegistrationAddress($customerData['address'] ?? 'Türkiye');
            $buyer->setIp($customerData['ip'] ?? $this->getClientIP());
            $buyer->setCity($customerData['city'] ?? 'Istanbul');
            $buyer->setCountry('Turkey');
            $request->setBuyer($buyer);
            
            // Fatura adresi
            $billingAddress = new \Iyzipay\Model\Address();
            $billingAddress->setContactName($customerData['name']);
            $billingAddress->setCity($customerData['city'] ?? 'Istanbul');
            $billingAddress->setCountry('Turkey');
            $billingAddress->setAddress($customerData['address'] ?? 'Türkiye');
            $request->setBillingAddress($billingAddress);
            
            // Teslimat adresi (dijital ürün olduğu için fatura ile aynı)
            $request->setShippingAddress($billingAddress);
            
            // Sepet ürünleri
            $basketItems = [];
            
            $basketItem = new \Iyzipay\Model\BasketItem();
            $basketItem->setId('PKG_' . $orderData['package_id']);
            $basketItem->setName($this->sanitizeText($orderData['package_name']));
            $basketItem->setCategory1($this->sanitizeText($orderData['category_name'] ?? 'Sosyal Medya'));
            $basketItem->setItemType(\Iyzipay\Model\BasketItemType::VIRTUAL);
            $basketItem->setPrice(number_format($orderData['total_price'], 2, '.', ''));
            $basketItems[] = $basketItem;
            
            $request->setBasketItems($basketItems);
            
            // Log request
            $this->logRequest($orderData['order_id'] ?? null, $conversationId, 'init', $request);
            
            // API çağrısı
            $checkoutFormInitialize = \Iyzipay\Model\CheckoutFormInitialize::create($request, $this->options);
            
            // Log response
            $this->logResponse($orderData['order_id'] ?? null, $conversationId, 'init', $checkoutFormInitialize);
            
            // Sonuç kontrolü
            if ($checkoutFormInitialize->getStatus() == 'success') {
                // Siparişe token kaydet
                if (!empty($orderData['order_id'])) {
                    $this->updateOrderToken(
                        $orderData['order_id'],
                        $conversationId,
                        $checkoutFormInitialize->getToken()
                    );
                }
                
                return [
                    'success' => true,
                    'token' => $checkoutFormInitialize->getToken(),
                    'checkoutFormContent' => $checkoutFormInitialize->getCheckoutFormContent(),
                    'conversationId' => $conversationId,
                    'paymentPageUrl' => $checkoutFormInitialize->getPaymentPageUrl()
                ];
            } else {
                return [
                    'success' => false,
                    'error_code' => $checkoutFormInitialize->getErrorCode(),
                    'error_message' => $checkoutFormInitialize->getErrorMessage(),
                    'conversationId' => $conversationId
                ];
            }
            
        } catch (\Exception $e) {
            $this->logError(null, $conversationId ?? null, 'init', $e->getMessage());
            
            return [
                'success' => false,
                'error_code' => 'EXCEPTION',
                'error_message' => 'Ödeme başlatılırken bir hata oluştu: ' . $e->getMessage()
            ];
        }
    }
    
    /**
     * ==================== MOBİL CİHAZ TESPİTİ ====================
     * Basit User-Agent kontrolü ile mobil cihaz tespiti
     * 
     * @return bool
     */
    public function isMobile(): bool
    {
        if (!isset($_SERVER['HTTP_USER_AGENT'])) {
            return false;
        }
        
        $ua = strtolower($_SERVER['HTTP_USER_AGENT']);
        
        $mobileKeywords = [
            'mobile', 'android', 'iphone', 'ipod', 'ipad',
            'windows phone', 'opera mini', 'opera mobi',
            'blackberry', 'bb10', 'webos',
            'silk', 'kindle', 'fennec',
            'symbian', 'nokia', 'samsung',
            'ucbrowser', 'ucweb'
        ];
        
        foreach ($mobileKeywords as $keyword) {
            if (strpos($ua, $keyword) !== false) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * Checkout Form sonucunu al
     * 
     * @param string $token iyzico token
     * @return array
     */
    public function retrieveCheckoutForm(string $token): array
    {
        if (!$this->isSDKLoaded()) {
            return [
                'success' => false,
                'error_code' => 'SDK_NOT_LOADED',
                'error_message' => 'iyzico SDK yüklü değil.'
            ];
        }
        
        try {
            $request = new \Iyzipay\Request\RetrieveCheckoutFormRequest();
            $request->setLocale(\Iyzipay\Model\Locale::TR);
            $request->setToken($token);
            
            $checkoutForm = \Iyzipay\Model\CheckoutForm::retrieve($request, $this->options);
            
            // Log
            $conversationId = $checkoutForm->getConversationId();
            $this->logResponse(null, $conversationId, 'callback', $checkoutForm);
            
            if ($checkoutForm->getStatus() == 'success' && $checkoutForm->getPaymentStatus() == 'SUCCESS') {
                // Payment Transaction ID al
                $paymentTransactionId = null;
                $paymentItems = $checkoutForm->getPaymentItems();
                if (!empty($paymentItems) && is_array($paymentItems)) {
                    $paymentTransactionId = $paymentItems[0]->getPaymentTransactionId();
                }
                
                return [
                    'success' => true,
                    'payment_id' => $checkoutForm->getPaymentId(),
                    'payment_transaction_id' => $paymentTransactionId,
                    'conversation_id' => $conversationId,
                    'paid_price' => $checkoutForm->getPaidPrice(),
                    'price' => $checkoutForm->getPrice(),
                    'currency' => $checkoutForm->getCurrency(),
                    'installment' => $checkoutForm->getInstallment(),
                    'basket_id' => $checkoutForm->getBasketId(),
                    'bin_number' => $checkoutForm->getBinNumber(),
                    'last_four_digits' => $checkoutForm->getLastFourDigits(),
                    'card_type' => $checkoutForm->getCardType(),
                    'card_association' => $checkoutForm->getCardAssociation(),
                    'card_family' => $checkoutForm->getCardFamily(),
                    'fraud_status' => $checkoutForm->getFraudStatus(),
                    'payment_items' => $paymentItems,
                    'raw_result' => $checkoutForm->getRawResult()
                ];
            } else {
                return [
                    'success' => false,
                    'error_code' => $checkoutForm->getErrorCode(),
                    'error_message' => $checkoutForm->getErrorMessage(),
                    'payment_status' => $checkoutForm->getPaymentStatus(),
                    'conversation_id' => $conversationId
                ];
            }
            
        } catch (\Exception $e) {
            $this->logError(null, null, 'callback', $e->getMessage());
            
            return [
                'success' => false,
                'error_code' => 'EXCEPTION',
                'error_message' => 'Ödeme doğrulanırken bir hata oluştu: ' . $e->getMessage()
            ];
        }
    }
    
    /**
     * Ödeme iadesi
     * 
     * @param string $paymentTransactionId İşlem ID
     * @param float $price İade tutarı
     * @param string $ip IP adresi
     * @return array
     */
    public function refund(string $paymentTransactionId, float $price, string $ip = ''): array
    {
        if (!$this->isSDKLoaded()) {
            return [
                'success' => false,
                'error_code' => 'SDK_NOT_LOADED',
                'error_message' => 'iyzico SDK yüklü değil.'
            ];
        }
        
        try {
            $conversationId = 'REFUND_' . time() . '_' . rand(1000, 9999);
            
            $request = new \Iyzipay\Request\CreateRefundRequest();
            $request->setLocale(\Iyzipay\Model\Locale::TR);
            $request->setConversationId($conversationId);
            $request->setPaymentTransactionId($paymentTransactionId);
            $request->setPrice(number_format($price, 2, '.', ''));
            $request->setIp($ip ?: $this->getClientIP());
            $request->setCurrency(\Iyzipay\Model\Currency::TL);
            
            $refund = \Iyzipay\Model\Refund::create($request, $this->options);
            
            $this->logResponse(null, $conversationId, 'refund', $refund);
            
            if ($refund->getStatus() == 'success') {
                return [
                    'success' => true,
                    'payment_id' => $refund->getPaymentId(),
                    'payment_transaction_id' => $refund->getPaymentTransactionId(),
                    'price' => $refund->getPrice()
                ];
            } else {
                return [
                    'success' => false,
                    'error_code' => $refund->getErrorCode(),
                    'error_message' => $refund->getErrorMessage()
                ];
            }
            
        } catch (\Exception $e) {
            return [
                'success' => false,
                'error_code' => 'EXCEPTION',
                'error_message' => 'İade işlemi sırasında hata: ' . $e->getMessage()
            ];
        }
    }
    
    /**
     * Taksit bilgilerini al
     * 
     * @param string $binNumber Kart BIN numarası (ilk 6 hane)
     * @param float $price Ödeme tutarı
     * @return array
     */
    public function getInstallmentInfo(string $binNumber, float $price): array
    {
        if (!$this->isSDKLoaded()) {
            return [
                'success' => false,
                'error_message' => 'iyzico SDK yüklü değil.',
                'installments' => []
            ];
        }
        
        try {
            $request = new \Iyzipay\Request\RetrieveInstallmentInfoRequest();
            $request->setLocale(\Iyzipay\Model\Locale::TR);
            $request->setConversationId('installment_' . time());
            $request->setBinNumber($binNumber);
            $request->setPrice(number_format($price, 2, '.', ''));
            
            $installmentInfo = \Iyzipay\Model\InstallmentInfo::retrieve($request, $this->options);
            
            if ($installmentInfo->getStatus() === 'success') {
                $installments = [];
                $details = $installmentInfo->getInstallmentDetails();
                
                if (!empty($details)) {
                    foreach ($details as $detail) {
                        $bankName = $detail->getBankName();
                        $cardFamilyName = $detail->getCardFamilyName();
                        
                        foreach ($detail->getInstallmentPrices() as $installment) {
                            $installments[] = [
                                'installment_number' => $installment->getInstallmentNumber(),
                                'total_price' => $installment->getTotalPrice(),
                                'installment_price' => $installment->getInstallmentPrice(),
                                'bank_name' => $bankName,
                                'card_family' => $cardFamilyName
                            ];
                        }
                    }
                }
                
                return [
                    'success' => true,
                    'installments' => $installments
                ];
            } else {
                return [
                    'success' => false,
                    'error_message' => $installmentInfo->getErrorMessage(),
                    'installments' => []
                ];
            }
            
        } catch (\Exception $e) {
            return [
                'success' => false,
                'error_message' => 'Taksit bilgisi alınamadı: ' . $e->getMessage(),
                'installments' => []
            ];
        }
    }
    
    /**
     * Sipariş token güncelle
     */
    public function updateOrderToken(int $orderId, string $conversationId, string $token): bool
    {
        try {
            $stmt = $this->db->prepare("
                UPDATE orders SET 
                    iyzico_conversation_id = ?,
                    iyzico_token = ?,
                    updated_at = NOW()
                WHERE id = ?
            ");
            return $stmt->execute([$conversationId, $token, $orderId]);
        } catch (\PDOException $e) {
            error_log('iyzico updateOrderToken error: ' . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Sipariş ödeme bilgilerini güncelle
     */
    public function updateOrderPayment(int $orderId, array $paymentData): bool
    {
        try {
            $stmt = $this->db->prepare("
                UPDATE orders SET 
                    status = 'paid',
                    payment_method = 'iyzico',
                    iyzico_payment_id = ?,
                    iyzico_payment_transaction_id = ?,
                    iyzico_fraud_status = ?,
                    iyzico_installment = ?,
                    iyzico_card_family = ?,
                    iyzico_card_type = ?,
                    iyzico_card_association = ?,
                    iyzico_bin_number = ?,
                    iyzico_last_four = ?,
                    iyzico_raw_result = ?,
                    paid_at = NOW(),
                    updated_at = NOW()
                WHERE id = ?
            ");
            
            return $stmt->execute([
                $paymentData['payment_id'] ?? null,
                $paymentData['payment_transaction_id'] ?? null,
                $paymentData['fraud_status'] ?? null,
                $paymentData['installment'] ?? 1,
                $paymentData['card_family'] ?? null,
                $paymentData['card_type'] ?? null,
                $paymentData['card_association'] ?? null,
                $paymentData['bin_number'] ?? null,
                $paymentData['last_four_digits'] ?? null,
                json_encode($paymentData['raw_result'] ?? null),
                $orderId
            ]);
        } catch (\PDOException $e) {
            error_log('iyzico updateOrderPayment error: ' . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Sipariş durumunu güncelle
     */
    public function updateOrderStatus(int $orderId, string $status, string $note = ''): bool
    {
        try {
            $stmt = $this->db->prepare("
                UPDATE orders SET 
                    status = ?,
                    admin_note = CONCAT(IFNULL(admin_note, ''), ?),
                    updated_at = NOW()
                WHERE id = ?
            ");
            
            $noteText = $note ? "\n[" . date('Y-m-d H:i:s') . "] " . $note : '';
            return $stmt->execute([$status, $noteText, $orderId]);
        } catch (\PDOException $e) {
            error_log('iyzico updateOrderStatus error: ' . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Token ile sipariş bul
     */
    public function findOrderByToken(string $token): ?array
    {
        try {
            $stmt = $this->db->prepare("
                SELECT o.*, p.name as package_name, c.name as category_name,
                       c.icon as category_icon, c.color as category_color
                FROM orders o
                JOIN packages p ON o.package_id = p.id
                JOIN categories c ON p.category_id = c.id
                WHERE o.iyzico_token = ? 
                LIMIT 1
            ");
            $stmt->execute([$token]);
            $order = $stmt->fetch(\PDO::FETCH_ASSOC);
            return $order ?: null;
        } catch (\PDOException $e) {
            error_log('iyzico findOrderByToken error: ' . $e->getMessage());
            return null;
        }
    }
    
    /**
     * Conversation ID ile sipariş bul
     */
    public function findOrderByConversationId(string $conversationId): ?array
    {
        try {
            $stmt = $this->db->prepare("
                SELECT o.*, p.name as package_name, c.name as category_name
                FROM orders o
                JOIN packages p ON o.package_id = p.id
                JOIN categories c ON p.category_id = c.id
                WHERE o.iyzico_conversation_id = ? 
                LIMIT 1
            ");
            $stmt->execute([$conversationId]);
            $order = $stmt->fetch(\PDO::FETCH_ASSOC);
            return $order ?: null;
        } catch (\PDOException $e) {
            error_log('iyzico findOrderByConversationId error: ' . $e->getMessage());
            return null;
        }
    }
    
    /**
     * Order Number ile sipariş bul
     */
    public function findOrderByOrderNumber(string $orderNumber): ?array
    {
        try {
            $stmt = $this->db->prepare("
                SELECT o.*, p.name as package_name, p.price as package_price,
                       c.name as category_name, c.icon as category_icon, c.color as category_color
                FROM orders o
                JOIN packages p ON o.package_id = p.id
                JOIN categories c ON p.category_id = c.id
                WHERE o.order_number = ? 
                LIMIT 1
            ");
            $stmt->execute([$orderNumber]);
            $order = $stmt->fetch(\PDO::FETCH_ASSOC);
            return $order ?: null;
        } catch (\PDOException $e) {
            error_log('iyzico findOrderByOrderNumber error: ' . $e->getMessage());
            return null;
        }
    }
    
    /**
     * İsimden ad çıkar
     */
    private function getFirstName(string $fullName): string
    {
        $parts = explode(' ', trim($fullName));
        return !empty($parts[0]) ? $parts[0] : 'Ad';
    }
    
    /**
     * İsimden soyad çıkar
     */
    private function getLastName(string $fullName): string
    {
        $parts = explode(' ', trim($fullName));
        array_shift($parts);
        return !empty($parts) ? implode(' ', $parts) : 'Soyad';
    }
    
    /**
     * Telefon numarasını formatla
     */
    private function formatPhone(string $phone): string
    {
        $phone = preg_replace('/[^0-9]/', '', $phone);
        
        if (strlen($phone) === 10) {
            $phone = '+90' . $phone;
        } elseif (strlen($phone) === 11 && substr($phone, 0, 1) === '0') {
            $phone = '+9' . $phone;
        } elseif (strlen($phone) === 12 && substr($phone, 0, 2) === '90') {
            $phone = '+' . $phone;
        } elseif (strlen($phone) < 10) {
            $phone = '+905000000000';
        }
        
        return $phone;
    }
    
    /**
     * Metni iyzico için temizle
     */
    private function sanitizeText(string $text): string
    {
        // Türkçe karakterleri koru ama özel karakterleri temizle
        $text = preg_replace('/[^\p{L}\p{N}\s\-]/u', '', $text);
        $text = trim(preg_replace('/\s+/', ' ', $text));
        return mb_substr($text, 0, 100);
    }
    
    /**
     * Client IP al
     */
    private function getClientIP(): string
    {
        $ipKeys = ['HTTP_CF_CONNECTING_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_REAL_IP', 'REMOTE_ADDR'];
        
        foreach ($ipKeys as $key) {
            if (!empty($_SERVER[$key])) {
                $ip = $_SERVER[$key];
                if (strpos($ip, ',') !== false) {
                    $ip = trim(explode(',', $ip)[0]);
                }
                if (filter_var($ip, FILTER_VALIDATE_IP)) {
                    return $ip;
                }
            }
        }
        
        return '127.0.0.1';
    }
    
    /**
     * Request logla
     */
    private function logRequest(?int $orderId, ?string $conversationId, string $action, $request): void
    {
        try {
            $requestData = null;
            if (is_object($request) && method_exists($request, 'getJsonObject')) {
                $requestData = json_encode($request->getJsonObject(), JSON_UNESCAPED_UNICODE);
            }
            
            $stmt = $this->db->prepare("
                INSERT INTO iyzico_logs (order_id, conversation_id, action, status, request_data, ip_address, created_at)
                VALUES (?, ?, ?, 'pending', ?, ?, NOW())
            ");
            $stmt->execute([
                $orderId,
                $conversationId,
                $action,
                $requestData,
                $this->getClientIP()
            ]);
        } catch (\PDOException $e) {
            error_log('iyzico log error (request): ' . $e->getMessage());
        }
    }
    
    /**
     * Response logla
     */
    private function logResponse(?int $orderId, ?string $conversationId, string $action, $response): void
    {
        try {
            $status = 'unknown';
            $errorCode = null;
            $errorMessage = null;
            $responseData = null;
            
            if (is_object($response)) {
                if (method_exists($response, 'getStatus')) {
                    $status = $response->getStatus();
                }
                if (method_exists($response, 'getErrorCode')) {
                    $errorCode = $response->getErrorCode();
                }
                if (method_exists($response, 'getErrorMessage')) {
                    $errorMessage = $response->getErrorMessage();
                }
                if (method_exists($response, 'getRawResult')) {
                    $responseData = json_encode($response->getRawResult(), JSON_UNESCAPED_UNICODE);
                }
            }
            
            $stmt = $this->db->prepare("
                INSERT INTO iyzico_logs (order_id, conversation_id, action, status, error_code, error_message, response_data, ip_address, created_at)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW())
            ");
            $stmt->execute([
                $orderId,
                $conversationId,
                $action . '_response',
                $status,
                $errorCode,
                $errorMessage,
                $responseData,
                $this->getClientIP()
            ]);
        } catch (\PDOException $e) {
            error_log('iyzico log error (response): ' . $e->getMessage());
        }
    }
    
    /**
     * Hata logla
     */
    private function logError(?int $orderId, ?string $conversationId, string $action, string $error): void
    {
        try {
            $stmt = $this->db->prepare("
                INSERT INTO iyzico_logs (order_id, conversation_id, action, status, error_message, ip_address, created_at)
                VALUES (?, ?, ?, 'error', ?, ?, NOW())
            ");
            $stmt->execute([
                $orderId,
                $conversationId,
                $action . '_error',
                $error,
                $this->getClientIP()
            ]);
        } catch (\PDOException $e) {
            error_log('iyzico log error (error): ' . $e->getMessage());
        }
    }
}

// ==================== HELPER FONKSİYONLARI ====================

/**
 * iyzico instance oluştur
 */
function getIyzicoInstance($db, $settings): IyzicoPayment
{
    static $instance = null;
    if ($instance === null) {
        $instance = new IyzicoPayment($db, $settings);
    }
    return $instance;
}

/**
 * iyzico aktif mi kontrol et
 */
function isIyzicoEnabled($settings): bool
{
    if (!isIyzicoSDKLoaded()) {
        return false;
    }
    
    $enabled = false;
    $apiKey = '';
    $secretKey = '';
    
    if (is_object($settings) && method_exists($settings, 'get')) {
        $enabled = $settings->get('iyzico_enabled', '0') == '1';
        $apiKey = $settings->get('iyzico_api_key', '');
        $secretKey = $settings->get('iyzico_secret_key', '');
    } elseif (is_array($settings)) {
        $enabled = ($settings['iyzico_enabled'] ?? '0') == '1';
        $apiKey = $settings['iyzico_api_key'] ?? '';
        $secretKey = $settings['iyzico_secret_key'] ?? '';
    }
    
    return $enabled && !empty($apiKey) && !empty($secretKey);
}

/**
 * iyzico SDK yüklü mü kontrol et
 */
function isIyzicoSDKLoaded(): bool
{
    // Önce doğrudan class kontrolü yap
    if (class_exists('\Iyzipay\Options')) {
        return true;
    }
    
    // SDK'yı yüklemeyi dene
    $bootstrapPath = dirname(__DIR__) . '/iyzipay-php/IyzipayBootstrap.php';
    if (file_exists($bootstrapPath)) {
        try {
            require_once $bootstrapPath;
            \IyzipayBootstrap::init();
            return class_exists('\Iyzipay\Options');
        } catch (\Exception $e) {
            error_log('iyzico SDK load error: ' . $e->getMessage());
            return false;
        }
    }
    
    return false;
}

/**
 * Callback URL oluştur
 */
function getIyzicoCallbackUrl(): string
{
    if (defined('SITE_URL')) {
        return SITE_URL . '/iyzico-callback.php';
    }
    
    $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
    $host = $_SERVER['HTTP_HOST'] ?? 'localhost';
    return $protocol . '://' . $host . '/iyzico-callback.php';
}

/**
 * ==================== MOBİL CİHAZ TESPİTİ (Global Helper) ====================
 * Basit User-Agent kontrolü
 * 
 * @return bool
 */
function isMobileDevice(): bool
{
    if (!isset($_SERVER['HTTP_USER_AGENT'])) {
        return false;
    }
    
    $ua = strtolower($_SERVER['HTTP_USER_AGENT']);
    
    $mobileKeywords = [
        'mobile', 'android', 'iphone', 'ipod',
        'windows phone', 'opera mini', 'opera mobi',
        'blackberry', 'bb10', 'webos',
        'silk', 'kindle', 'fennec',
        'symbian', 'nokia', 'samsung',
        'ucbrowser', 'ucweb'
    ];
    
    foreach ($mobileKeywords as $keyword) {
        if (strpos($ua, $keyword) !== false) {
            return true;
        }
    }
    
    return false;
}