<?php
/**
 * iPaymu Payment Gateway Integration
 * API v2 Documentation: https://ipaymu.com/dokumentasi-api/
 */
class iPaymu {
    private $va;
    private $apiKey;
    private $baseUrl;
    private $mode;
    
    public function __construct() {
        $this->loadConfig();
    }
    
    /**
     * Load konfigurasi dari database
     */
    private function loadConfig() {
        $db = db();
        $config = [];
        
        try {
            $stmt = $db->query("SELECT setting_key, setting_value FROM payment_config");
            while ($row = $stmt->fetch()) {
                $config[$row['setting_key']] = $row['setting_value'];
            }
        } catch (\Throwable $e) {
            // Fallback ke default
        }
        
        $this->va = $config['ipaymu_va'] ?? '';
        $this->apiKey = $config['ipaymu_api_key'] ?? '';
        $this->mode = $config['ipaymu_mode'] ?? 'sandbox';
        
        // Set base URL berdasarkan mode
        if ($this->mode === 'production') {
            $this->baseUrl = 'https://my.ipaymu.com/api/v2';
        } else {
            $this->baseUrl = 'https://sandbox.ipaymu.com/api/v2';
        }
    }
    
    /**
     * Generate signature untuk iPaymu API
     */
    private function generateSignature($method, $jsonBody) {
        $requestBody = strtolower(hash('sha256', $jsonBody));
        $stringToSign = strtoupper($method) . ':' . $this->va . ':' . $requestBody . ':' . $this->apiKey;
        return hash_hmac('sha256', $stringToSign, $this->apiKey);
    }
    
    /**
     * Generate headers untuk request
     */
    private function generateHeaders($method, $jsonBody) {
        $signature = $this->generateSignature($method, $jsonBody);
        $timestamp = date('YmdHis');
        
        return [
            'Accept: application/json',
            'Content-Type: application/json',
            'va: ' . $this->va,
            'signature: ' . $signature,
            'timestamp: ' . $timestamp
        ];
    }
    
    /**
     * Execute cURL request
     */
    private function request($url, $method, $body = null) {
        if (empty($this->va) || empty($this->apiKey)) {
            return [
                'success' => false,
                'error' => 'Konfigurasi iPaymu belum lengkap. VA: ' . ($this->va ? 'OK' : 'KOSONG') . ', API Key: ' . ($this->apiKey ? 'OK' : 'KOSONG'),
                'data' => []
            ];
        }
        
        $jsonBody = $body ? json_encode($body, JSON_UNESCAPED_SLASHES) : '{}';
        $headers = $this->generateHeaders($method, $jsonBody);
        
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
        
        if ($method === 'POST') {
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonBody);
        } else {
            curl_setopt($ch, CURLOPT_HTTPGET, true);
        }
        
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        $errno = curl_errno($ch);
        curl_close($ch);
        
        if ($error) {
            return [
                'success' => false,
                'error' => 'cURL Error (' . $errno . '): ' . $error,
                'http_code' => $httpCode,
                'data' => []
            ];
        }
        
        $result = json_decode($response, true);
        
        if (json_last_error() !== JSON_ERROR_NONE) {
            return [
                'success' => false,
                'error' => 'Invalid JSON response: ' . json_last_error_msg(),
                'http_code' => $httpCode,
                'raw_response' => $response,
                'data' => []
            ];
        }
        
        return [
            'success' => isset($result['Status']) && $result['Status'] == 200,
            'data' => $result,
            'http_code' => $httpCode,
            'message' => $result['Message'] ?? ''
        ];
    }
    
    /**
     * Get daftar payment channels yang tersedia
     */
    public function getPaymentChannels() {
        $url = $this->baseUrl . '/payment-channels';
        $result = $this->request($url, 'GET');
        
        if ($result['success'] && isset($result['data']['Data'])) {
            return [
                'success' => true,
                'channels' => $result['data']['Data']
            ];
        }
        
        return [
            'success' => false,
            'error' => $result['data']['Message'] ?? $result['error'] ?? 'Gagal mengambil daftar channel pembayaran',
            'data' => $result['data'] ?? []
        ];
    }
    
    /**
     * Create payment session
     */
    public function createPayment($params) {
        $url = $this->baseUrl . '/payment';
        
        // Validate required params
        if (empty($params['referenceId'])) {
            return ['success' => false, 'error' => 'Reference ID wajib diisi', 'data' => []];
        }
        
        if (empty($params['products']) || !is_array($params['products'])) {
            return ['success' => false, 'error' => 'Products wajib diisi', 'data' => []];
        }
        
        // Get default URLs dari config jika tidak disediakan
        $db = db();
        $stmt = $db->query("SELECT setting_value FROM payment_config WHERE setting_key='ipaymu_notify_url'");
        $defaultNotifyUrl = $stmt->fetchColumn() ?: '';
        
        $body = [
            'product'      => array_column($params['products'], 'name'),
            'qty'          => array_column($params['products'], 'qty'),
            'price'        => array_column($params['products'], 'price'),
            'returnUrl'    => $params['returnUrl'] ?? '',
            'cancelUrl'    => $params['cancelUrl'] ?? '',
            'notifyUrl'    => $params['notifyUrl'] ?: $defaultNotifyUrl,
            'referenceId'  => $params['referenceId'],
        ];
        
        // Optional customer info
        if (!empty($params['customerName'])) $body['name'] = $params['customerName'];
        if (!empty($params['customerEmail'])) $body['email'] = $params['customerEmail'];
        if (!empty($params['customerPhone'])) $body['phone'] = $params['customerPhone'];
        
        $result = $this->request($url, 'POST', $body);
        
        if ($result['success'] && isset($result['data']['Data'])) {
            $data = $result['data']['Data'];
            
            // Handle both object and array response
            if (is_object($data)) {
                $sessionId = $data->SessionID ?? '';
                $paymentUrl = $data->Url ?? '';
            } else {
                $sessionId = $data['SessionID'] ?? '';
                $paymentUrl = $data['Url'] ?? '';
            }
            
            return [
                'success' => true,
                'session_id' => $sessionId,
                'payment_url' => $paymentUrl,
                'data' => $data
            ];
        }
        
        $errorMessage = 'Gagal membuat sesi pembayaran';
        if (isset($result['data']['Message'])) {
            $errorMessage = $result['data']['Message'];
        } elseif (isset($result['error'])) {
            $errorMessage = $result['error'];
        }
        
        return [
            'success' => false,
            'error' => $errorMessage,
            'data' => $result['data'] ?? []
        ];
    }
    
    /**
     * Check status transaksi
     */
    public function checkTransaction($referenceId) {
        $url = $this->baseUrl . '/transaction';
        
        $body = [
            'referenceId' => $referenceId
        ];
        
        $result = $this->request($url, 'POST', $body);
        
        if ($result['success']) {
            return [
                'success' => true,
                'data' => $result['data']['Data'] ?? null
            ];
        }
        
        return [
            'success' => false,
            'error' => $result['data']['Message'] ?? 'Gagal mengecek transaksi',
            'data' => $result['data'] ?? []
        ];
    }
    
    /**
     * Get mode (sandbox/production)
     */
    public function getMode() {
        return $this->mode;
    }
    
    /**
     * Check if configured
     */
    public function isConfigured() {
        return !empty($this->va) && !empty($this->apiKey);
    }
    
    /**
     * Get VA number
     */
    public function getVA() {
        return $this->va;
    }
}