<?php
/**
 * Cliente API para Big4pay
 * Maneja todas las operaciones relacionadas con la integración de Big4pay
 */

if (!defined('BASE_PATH')) {
    define('BASE_PATH', dirname(dirname(__DIR__)));
}

require_once BASE_PATH . '/database/connection.php';

class Big4payClient {
    private $pdo;
    private $apiUrl = 'https://big4pay.com/create-access-token';
    // Endpoint Live para iniciar pagos
    private $paymentInitiateUrl = 'https://big4pay.com/payment/initiate';
    private $paymentInitiateTestUrl = 'https://big4pay.com/test/payment/initiate';
    private $username;
    private $password;
    private $currency = 'MXN';
    private $accessToken;
    private $ipnUrl;
    private $successUrl;
    private $cancelUrl;
    
    public function __construct($pdo = null) {
        if ($pdo === null) {
            $db = Database::getInstance();
            $this->pdo = $db->getConnection();
        } else {
            $this->pdo = $pdo;
        }
        
        $this->loadConfiguration();
    }
    
    /**
     * Carga la configuración de Big4pay desde la base de datos
     */
    private function loadConfiguration() {
        try {
            // Preferir configuración desde payment_methods
            $this->pdo->exec("CREATE TABLE IF NOT EXISTS payment_methods (
                id INT AUTO_INCREMENT PRIMARY KEY,
                name VARCHAR(64) NOT NULL,
                display_name VARCHAR(128) NOT NULL,
                provider_key VARCHAR(64) NOT NULL,
                api_category VARCHAR(64) NOT NULL DEFAULT 'Payment Method',
                category VARCHAR(32) NOT NULL,
                type ENUM('deposit','withdraw','both') NOT NULL DEFAULT 'deposit',
                logo_path VARCHAR(255) NULL,
                config JSON NULL,
                is_active TINYINT(1) NOT NULL DEFAULT 1,
                created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                updated_at DATETIME NULL
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
            try { $this->pdo->exec("ALTER TABLE payment_methods ADD COLUMN api_username VARCHAR(128) NULL"); } catch (Throwable $__) {}
            try { $this->pdo->exec("ALTER TABLE payment_methods ADD COLUMN api_password VARCHAR(128) NULL"); } catch (Throwable $__) {}
            try { $this->pdo->exec("ALTER TABLE payment_methods ADD COLUMN api_ipn_url VARCHAR(255) NULL"); } catch (Throwable $__) {}
            try { $this->pdo->exec("ALTER TABLE payment_methods ADD COLUMN api_success_url VARCHAR(255) NULL"); } catch (Throwable $__) {}
            try { $this->pdo->exec("ALTER TABLE payment_methods ADD COLUMN api_cancel_url VARCHAR(255) NULL"); } catch (Throwable $__) {}

            $sel = $this->pdo->prepare("SELECT api_username, api_password, api_ipn_url, api_success_url, api_cancel_url FROM payment_methods WHERE provider_key = 'big4pay' AND is_active = 1 AND (type='deposit' OR type='both') ORDER BY id DESC LIMIT 1");
            $sel->execute();
            if ($pm = $sel->fetch()) {
                $this->username = $pm['api_username'] ?? $this->username;
                $this->password = $pm['api_password'] ?? $this->password;
                $this->ipnUrl = $pm['api_ipn_url'] ?? $this->ipnUrl;
                $this->successUrl = $pm['api_success_url'] ?? $this->successUrl;
                $this->cancelUrl = $pm['api_cancel_url'] ?? $this->cancelUrl;
            }

            // Fallback a integration_settings si aún falta algo
            $stmt = $this->pdo->prepare("SELECT setting_key, setting_value FROM integration_settings WHERE integration_name = 'big4pay'");
            $stmt->execute();
            while ($row = $stmt->fetch()) {
                switch ($row['setting_key']) {
                    case 'username': $this->username = $this->username ?: $row['setting_value']; break;
                    case 'password': $this->password = $this->password ?: $row['setting_value']; break;
                    case 'currency': $this->currency = $row['setting_value'] ?: 'MXN'; break;
                    case 'access_token': $this->accessToken = $row['setting_value']; break;
                    case 'ipn_url': $this->ipnUrl = $this->ipnUrl ?: $row['setting_value']; break;
                    case 'success_url': $this->successUrl = $this->successUrl ?: $row['setting_value']; break;
                    case 'cancel_url': $this->cancelUrl = $this->cancelUrl ?: $row['setting_value']; break;
                }
            }
        } catch (Exception $e) {
            error_log("Error loading Big4pay configuration: " . $e->getMessage());
        }
    }
    
    /**
     * Verifica si Big4pay está configurado correctamente
     */
    public function isConfigured() {
        return !empty($this->username) && !empty($this->password);
    }
    
    /**
     * Devuelve la contraseña actual (uso controlado desde acciones con permisos)
     */
    public function getPassword() {
        return $this->password;
    }
    
    /**
     * Guarda la configuración de Big4pay
     */
    public function saveConfiguration($username, $password, $currency = null, $extra = []) {
        try {
            // Guardar directamente en payment_methods (último activo de big4pay)
            $sel = $this->pdo->prepare("SELECT id FROM payment_methods WHERE provider_key='big4pay' AND is_active=1 AND (type='deposit' OR type='both') ORDER BY id DESC LIMIT 1");
            $sel->execute();
            $row = $sel->fetch();
            if ($row) {
                $upd = $this->pdo->prepare("UPDATE payment_methods SET api_username = ?, api_password = ?, api_ipn_url = COALESCE(?, api_ipn_url), api_success_url = COALESCE(?, api_success_url), api_cancel_url = COALESCE(?, api_cancel_url) WHERE id = ?");
                $upd->execute([$username, $password, ($extra['ipn_url'] ?? null), ($extra['success_url'] ?? null), ($extra['cancel_url'] ?? null), (int)$row['id']]);
            } else {
                $ins = $this->pdo->prepare("INSERT INTO payment_methods (name, display_name, provider_key, api_category, category, type, is_active, api_username, api_password, api_ipn_url, api_success_url, api_cancel_url) VALUES ('Big4pay','Big4pay','big4pay','Payment Method','Payment Method','deposit',1, ?, ?, ?, ?, ?)");
                $ins->execute([$username, $password, ($extra['ipn_url'] ?? null), ($extra['success_url'] ?? null), ($extra['cancel_url'] ?? null)]);
            }
            
            // Actualizar propiedades locales
            $this->username = $username;
            $this->password = $password;
            if (!empty($currency)) { $this->currency = $currency; }
            $this->ipnUrl = ($extra['ipn_url'] ?? $this->ipnUrl);
            $this->successUrl = ($extra['success_url'] ?? $this->successUrl);
            $this->cancelUrl = ($extra['cancel_url'] ?? $this->cancelUrl);
            
            return true;
        } catch (Exception $e) {
            error_log("Error saving Big4pay configuration: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Crea un token de acceso para Big4pay
     */
    public function createAccessToken($amount, $currency = 'MXN', $testMode = false) {
        if (!$this->isConfigured()) {
            throw new Exception('Big4pay no está configurado correctamente');
        }
        
        $data = [
            'username' => $this->username,
            'password' => $this->password,
            'amount' => $amount,
            'currency' => $currency
        ];
        
        if ($testMode) {
            $data['test_mode'] = true;
        }
        
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->apiUrl);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'Accept: application/json'
        ]);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);
        
        if ($error) {
            throw new Exception('Error de conexión: ' . $error);
        }
        
        if ($httpCode !== 200) {
            throw new Exception('Error HTTP: ' . $httpCode);
        }
        
        $result = json_decode($response, true);
        
        if (!$result || !isset($result['success'])) {
            throw new Exception('Respuesta inválida del servidor');
        }
        
        return $result;
    }

    /**
     * Genera un token enviando únicamente username y password y devuelve respuesta cruda
     */
    public function createAccessTokenRaw() {
        if (!$this->isConfigured()) {
            throw new Exception('Big4pay no está configurado correctamente');
        }
        $payload = [
            'username' => $this->username,
            'password' => $this->password
        ];
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->apiUrl);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'Accept: application/json'
        ]);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
        $error = curl_error($ch);
        curl_close($ch);
        if ($error) {
            return [
                'success' => false,
                'http_code' => null,
                'body' => null,
                'message' => 'Error de conexión: ' . $error
            ];
        }
        $headers = substr($response, 0, $headerSize);
        $body = substr($response, $headerSize);
        $decoded = null;
        if (is_string($body)) {
            $decoded = json_decode($body, true);
        }
        // Buscar Authorization en cabeceras si existe
        $authHeader = null;
        foreach (explode("\r\n", $headers) as $line) {
            if (stripos($line, 'Authorization:') === 0) {
                $parts = explode(':', $line, 2);
                if (count($parts) === 2) { $authHeader = trim($parts[1]); }
                break;
            }
        }
        // También aceptar access_token en JSON
        $tokenFromJson = $decoded['access_token'] ?? $decoded['Authorization'] ?? null;
        if ($tokenFromJson) { $authHeader = $tokenFromJson; }
        return [
            'success' => ($httpCode >= 200 && $httpCode < 300),
            'http_code' => $httpCode,
            'body' => $body,
            'json' => $decoded,
            'authorization' => $authHeader
        ];
    }

    /**
     * Guarda el access_token/Authorization en configuración para su uso posterior
     */
    public function saveAccessToken($token) {
        if (empty($token)) return false;
        try {
            $stmtDel = $this->pdo->prepare("DELETE FROM integration_settings WHERE integration_name = 'big4pay' AND setting_key = 'access_token'");
            $stmtDel->execute();
            $stmtIns = $this->pdo->prepare("INSERT INTO integration_settings (integration_name, setting_key, setting_value) VALUES ('big4pay', 'access_token', ?)");
            $stmtIns->execute([$token]);
            $this->accessToken = $token;
            return true;
        } catch (Exception $e) {
            error_log('Error saving access token: ' . $e->getMessage());
            return false;
        }
    }
    public function getAccessToken() { return $this->accessToken; }

    /**
     * Genera un identificador incremental tipo TRX_xxxxx
     */
    public function generateIdentifier() {
        try {
            $this->pdo->beginTransaction();
            $stmtSel = $this->pdo->prepare("SELECT setting_value FROM integration_settings WHERE integration_name = 'big4pay' AND setting_key = 'trx_counter' LIMIT 1");
            $stmtSel->execute();
            $row = $stmtSel->fetch();
            $counter = $row ? (int)$row['setting_value'] : 0;
            $counter++;
            $stmtDel = $this->pdo->prepare("DELETE FROM integration_settings WHERE integration_name = 'big4pay' AND setting_key = 'trx_counter'");
            $stmtDel->execute();
            $stmtIns = $this->pdo->prepare("INSERT INTO integration_settings (integration_name, setting_key, setting_value) VALUES ('big4pay', 'trx_counter', ?)");
            $stmtIns->execute([$counter]);
            $this->pdo->commit();
            return 'TRX_' . str_pad((string)$counter, 8, '0', STR_PAD_LEFT);
        } catch (Exception $e) {
            $this->pdo->rollBack();
            // Fallback a timestamp
            $fallback = (int)(microtime(true) * 1000) % 100000000; // 8 dígitos
            return 'TRX_' . str_pad((string)$fallback, 8, '0', STR_PAD_LEFT);
        }
    }

    /**
     * Inicia pago en Big4pay
     */
    public function initiatePayment($params, $useTest = false) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $useTest ? $this->paymentInitiateTestUrl : $this->paymentInitiateUrl);
        curl_setopt($ch, CURLOPT_POST, true);
        // Enviar como JSON
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, true);
        $headers = [
            'Content-Type: application/json',
            'Accept: application/json',
            'User-Agent: ProfixCRM/1.0'
        ];
        // Usar Authorization exacto si está disponible
        $token = $this->accessToken ?? ($params['access_token'] ?? null);
        if (!empty($token)) {
            $headers[] = 'Authorization: ' . $token;
        }
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
        $error = curl_error($ch);
        curl_close($ch);
        if ($error) {
            return [ 'success' => false, 'http_code' => null, 'body' => null, 'message' => 'Error de conexión: ' . $error ];
        }
        $headers = substr($response, 0, $headerSize);
        $body = substr($response, $headerSize);
        $decoded = null;
        if (is_string($body)) { $decoded = json_decode($body, true); }
        return [
            'success' => ($httpCode >= 200 && $httpCode < 300),
            'http_code' => $httpCode,
            'body' => $body,
            'json' => $decoded
        ];
    }

    /**
     * Flujo de prueba: genera token, guarda Authorization y llama a initiate
     */
    public function testPaymentInitiation($amount = 200, $currency = null, $customer = null) {
        if (!$currency) { $currency = $this->currency ?: 'MXN'; }
        // Paso 1: token
        $raw = $this->createAccessTokenRaw();
        if (!$raw['success']) {
            return [ 'success' => false, 'step' => 'token', 'http_code' => $raw['http_code'], 'body' => $raw['body'], 'message' => $raw['message'] ?? null ];
        }
        $token = $raw['authorization'] ?? ($raw['json']['access_token'] ?? null);
        if ($token) { $this->saveAccessToken($token); }
        // Paso 2: initiate
        $identifier = $this->generateIdentifier();
        $params = [
            'access_token' => $token,
            'identifier' => $identifier,
            'currency' => $currency,
            'amount' => $amount,
            'language' => 'ES',
            'description' => 'Compra de prueba',
            'details' => 'deposit transactions',
            'ipn_url' => $this->ipnUrl ?: '/api/payment_method/big4pay/ipn.php',
            'success_url' => $this->successUrl ?: '/modules/client_portal/big4pay_success.php',
            'cancel_url' => $this->cancelUrl ?: '/modules/client_portal/big4pay_cancel.php',
            'site_name' => 'IAttrade',
            'site_logo' => 'http://yoursite.com/logo.png',
            'checkout_theme' => 'light',
            'customer' => $customer ?: [
                'first_name' => 'John',
                'last_name' => 'Doe',
                'country' => 'MX',
                'email' => 'joan@gmail.com',
                'mobile' => '12345789'
            ]
        ];
        return $this->initiatePayment($params, true);
    }
    
    /**
     * Realiza un pago de prueba
     */
    public function testPayment($amount = 2000, $currency = 'MXN') {
        try {
            $result = $this->createAccessToken($amount, $currency, true);
            
            if ($result['success']) {
                return [
                    'success' => true,
                    'message' => 'Pago de prueba exitoso',
                    'token' => $result['token'] ?? null,
                    'amount' => $amount,
                    'currency' => $currency
                ];
            } else {
                return [
                    'success' => false,
                    'message' => $result['message'] ?? 'Error desconocido'
                ];
            }
        } catch (Exception $e) {
            return [
                'success' => false,
                'message' => $e->getMessage()
            ];
        }
    }
    
    /**
     * Obtiene la configuración actual (sin contraseña)
     */
    public function getConfiguration() {
        return [
            'username' => $this->username,
            'configured' => $this->isConfigured(),
            'currency' => $this->currency,
            'access_token' => $this->accessToken,
            'ipn_url' => $this->ipnUrl,
            'success_url' => $this->successUrl,
            'cancel_url' => $this->cancelUrl
        ];
    }
}