<?php
/**
 * Test API for PagoMovil Bank List - FINAL FIXED VERSION
 * Fixed UTF-8 encoding issues and proper bank list display
 */

// Enable error reporting for debugging
error_reporting(E_ALL);
ini_set('display_errors', 1);

class PagoMovilBankTest {
    private $api_base_url = 'https://servicios.bncenlinea.com:16500';
    private $client_guid = '8358c7d5-5a6c-4883-8526-05ec48ed0130';
    private $master_key = '667ce71bfc380183546d0005140b58f3';
    private $working_key = '';
    
    public function __construct() {
        echo "<!DOCTYPE html>
        <html>
        <head>
            <title>PagoMovil Bank List Test - FIXED</title>
            <style>
                body { font-family: Arial, sans-serif; max-width: 1200px; margin: 0 auto; padding: 20px; }
                .success { color: green; background: #f0fff0; padding: 10px; border-left: 4px solid green; }
                .error { color: red; background: #fff0f0; padding: 10px; border-left: 4px solid red; }
                .info { background: #f0f8ff; padding: 10px; border-left: 4px solid #0073aa; margin: 10px 0; }
                table { width: 100%; border-collapse: collapse; margin: 20px 0; }
                th, td { border: 1px solid #ddd; padding: 12px; text-align: left; }
                th { background-color: #f2f2f2; }
                .bank-dropdown { width: 100%; padding: 8px; margin: 10px 0; }
            </style>
        </head>
        <body>";
        
        echo "<h1>PagoMovil Bank List API Test - FINAL FIXED VERSION</h1>\n";
        echo "<p><strong>Base URL:</strong> " . $this->api_base_url . "</p>\n";
        echo "<p><strong>Client GUID:</strong> " . substr($this->client_guid, 0, 8) . "...</p>\n";
    }
    
    public function runTests() {
        echo "<h2>Step 1: Authentication</h2>\n";
        if (!$this->authenticate()) {
            echo "<p class='error'><strong>Authentication FAILED</strong></p>\n";
            return false;
        }
        
        echo "<h2>Step 2: Get Bank List</h2>\n";
        $banks = $this->getBankList();
        
        if ($banks && is_array($banks)) {
            echo "<p class='success'><strong>Bank list retrieved successfully!</strong></p>\n";
            $this->displayBanks($banks);
            $this->displayBankDropdown($banks);
            return true;
        } else {
            echo "<p class='error'><strong>Failed to get bank list</strong></p>\n";
            return false;
        }
    }
    
    private function authenticate() {
        echo "<p>Authenticating with bank API...</p>\n";
        
        $auth_data = array('ClientGUID' => $this->client_guid);
        $encrypted_data = $this->encrypt_data($auth_data, $this->master_key);
        
        if (!$encrypted_data) {
            echo "<p class='error'>Encryption failed</p>\n";
            return false;
        }
        
        $response = $this->make_api_call('/api/Auth/LogOn', $encrypted_data);
        
        if ($response && isset($response['status']) && $response['status'] === 'OK') {
            $decrypted_response = $this->decrypt_data($response['value'], $this->master_key);
            
            if ($decrypted_response === false) {
                echo "<p class='error'>Decryption failed</p>\n";
                return false;
            }
            
            echo "<div class='info'><strong>Decrypted authentication response:</strong> " . htmlspecialchars($decrypted_response) . "</div>\n";
            
            $response_data = json_decode($decrypted_response, true);
            
            if (isset($response_data['WorkingKey'])) {
                $this->working_key = $response_data['WorkingKey'];
                echo "<p class='success'><strong>Authentication SUCCESSFUL</strong></p>\n";
                echo "<p>WorkingKey obtained: " . substr($this->working_key, 0, 20) . "...</p>\n";
                return true;
            } else {
                echo "<p class='error'>WorkingKey not found in response</p>\n";
                if (isset($response_data['Message'])) {
                    echo "<p>API Message: " . htmlspecialchars($response_data['Message']) . "</p>\n";
                }
            }
        } else {
            echo "<p class='error'>Authentication failed: API status not OK</p>\n";
            if (isset($response['message'])) {
                echo "<p>Error message: " . htmlspecialchars($response['message']) . "</p>\n";
            }
        }
        
        return false;
    }
    
    private function getBankList() {
        echo "<p>Requesting bank list from API...</p>\n";
        
        if (empty($this->working_key)) {
            echo "<p class='error'>No WorkingKey available. Please authenticate first.</p>\n";
            return false;
        }
        
        // Use empty object format which worked in your test
        $bank_data = new stdClass();
        $encrypted_data = $this->encrypt_data($bank_data, $this->working_key);
        
        if (!$encrypted_data) {
            echo "<p class='error'>Bank data encryption failed</p>\n";
            return false;
        }
        
        $response = $this->make_api_call('/api/Services/Banks', $encrypted_data);
        
        if ($response && isset($response['status']) && $response['status'] === 'OK') {
            $decrypted_response = $this->decrypt_data($response['value'], $this->working_key);
            
            if ($decrypted_response === false) {
                echo "<p class='error'>Bank list decryption failed</p>\n";
                return false;
            }
            
            echo "<div class='info'>";
            echo "<p><strong>Decrypted bank list response length:</strong> " . strlen($decrypted_response) . " characters</p>\n";
            
            // FIX: Clean UTF-8 encoding before JSON decoding
            $clean_response = $this->clean_utf8($decrypted_response);
            
            // Try to decode JSON with error handling
            $banks = json_decode($clean_response, true);
            
            if (json_last_error() !== JSON_ERROR_NONE) {
                echo "<p class='error'>JSON decode error: " . json_last_error_msg() . "</p>\n";
                
                // Try to fix common JSON issues
                $fixed_response = $this->fix_json($clean_response);
                $banks = json_decode($fixed_response, true);
                
                if (json_last_error() !== JSON_ERROR_NONE) {
                    echo "<p class='error'>Still cannot decode JSON after fixes. Showing raw data:</p>\n";
                    echo "<pre>" . htmlspecialchars($clean_response) . "</pre>\n";
                    return false;
                }
            }
            
            echo "</div>";
            return $banks;
        } else {
            echo "<p class='error'>Bank list API returned non-OK status</p>\n";
            if (isset($response['message'])) {
                echo "<p>Error message: " . htmlspecialchars($response['message']) . "</p>\n";
            }
        }
        
        return false;
    }
    
    /**
     * Clean UTF-8 encoding issues
     */
    private function clean_utf8($string) {
        // First, try to detect encoding and convert to UTF-8
        $encoding = mb_detect_encoding($string, ['UTF-8', 'ISO-8859-1', 'Windows-1252'], true);
        
        if ($encoding && $encoding != 'UTF-8') {
            $string = mb_convert_encoding($string, 'UTF-8', $encoding);
        }
        
        // Remove any invalid UTF-8 characters
        $string = mb_convert_encoding($string, 'UTF-8', 'UTF-8');
        
        // Replace common problematic characters
        $string = str_replace(
            ['á', 'é', 'í', 'ó', 'ú', 'ñ', 'Á', 'É', 'Í', 'Ó', 'Ú', 'Ñ'],
            ['á', 'é', 'í', 'ó', 'ú', 'ñ', 'Á', 'É', 'Í', 'Ó', 'Ú', 'Ñ'],
            $string
        );
        
        return $string;
    }
    
    /**
     * Fix common JSON formatting issues
     */
    private function fix_json($json_string) {
        // Remove BOM if present
        $json_string = str_replace("\xEF\xBB\xBF", '', $json_string);
        
        // Trim whitespace
        $json_string = trim($json_string);
        
        return $json_string;
    }
    
    private function make_api_call($endpoint, $data) {
        $url = $this->api_base_url . $endpoint;
        
        echo "<div class='info'>\n";
        echo "<p><strong>API Request:</strong></p>\n";
        echo "<p>Endpoint: " . htmlspecialchars($url) . "</p>\n";
        
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => json_encode($data),
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/json',
                'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
            ],
            CURLOPT_TIMEOUT => 30,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_FOLLOWLOCATION => true
        ]);
        
        $response = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $curl_error = curl_error($ch);
        curl_close($ch);
        
        echo "<p><strong>HTTP Response Code:</strong> " . $http_code . "</p>\n";
        
        // HTTP 202 Accepted is a SUCCESS status
        $success_codes = [200, 202];
        
        if ($curl_error) {
            echo "<p class='error'><strong>cURL Error:</strong> " . htmlspecialchars($curl_error) . "</p>\n";
            echo "</div>\n";
            return false;
        }
        
        if (!in_array($http_code, $success_codes)) {
            echo "<p class='error'><strong>HTTP Error:</strong> " . $http_code . "</p>\n";
            echo "<p><strong>Raw Response:</strong> " . htmlspecialchars($response) . "</p>\n";
            echo "</div>\n";
            return false;
        }
        
        echo "</div>\n";
        
        $decoded_response = json_decode($response, true);
        
        if (json_last_error() !== JSON_ERROR_NONE) {
            echo "<p class='error'>JSON decode error: " . json_last_error_msg() . "</p>\n";
            return false;
        }
        
        return $decoded_response;
    }
    
    private function encrypt_data($data, $key) {
        $plain_text = json_encode($data);
        $salt = hex2bin('4976616e204d65647665646576'); // "Ivan Medvedev"
        
        // Use PBKDF2 to derive key and IV (exactly like Postman)
        $derived_key = hash_pbkdf2('sha1', $key, $salt, 1000, 48, true);
        $aes_key = substr($derived_key, 0, 32);
        $iv = substr($derived_key, 32, 16);

        // Convert to UTF-16LE (little endian) and encrypt
        $plain_text_utf16 = '';
        for ($i = 0; $i < strlen($plain_text); $i++) {
            $plain_text_utf16 .= $plain_text[$i] . "\x00";
        }

        $cipher_text = openssl_encrypt(
            $plain_text_utf16,
            'AES-256-CBC',
            $aes_key,
            OPENSSL_RAW_DATA,
            $iv
        );

        if ($cipher_text === false) {
            echo "<p class='error'>Encryption failed: " . openssl_error_string() . "</p>\n";
            return false;
        }

        $validation = hash('sha256', $plain_text);

        return array(
            'ClientGUID' => $this->client_guid,
            'Reference' => 'REF' . time(),
            'Value' => base64_encode($cipher_text),
            'Validation' => $validation,
            'swTestOperation' => false
        );
    }
    
    private function decrypt_data($encrypted_data, $key) {
        $salt = hex2bin('4976616e204d65647665646576');
        $derived_key = hash_pbkdf2('sha1', $key, $salt, 1000, 48, true);
        $aes_key = substr($derived_key, 0, 32);
        $iv = substr($derived_key, 32, 16);

        $decrypted = openssl_decrypt(
            base64_decode($encrypted_data),
            'AES-256-CBC',
            $aes_key,
            OPENSSL_RAW_DATA,
            $iv
        );

        if ($decrypted === false) {
            echo "<p class='error'>Decryption failed: " . openssl_error_string() . "</p>\n";
            return false;
        }

        // Convert from UTF-16LE to UTF-8
        $result = '';
        for ($i = 0; $i < strlen($decrypted); $i += 2) {
            if ($decrypted[$i] != "\x00") {
                $result .= $decrypted[$i];
            }
        }

        return $result;
    }
    
    private function displayBanks($banks) {
        if (!is_array($banks) || empty($banks)) {
            echo "<p>No banks found in response</p>\n";
            return;
        }
        
        echo "<h3>Complete Bank List (" . count($banks) . " banks found)</h3>\n";
        echo "<table>\n";
        echo "<tr><th>Code</th><th>Bank Name</th><th>Services</th></tr>\n";
        
        foreach ($banks as $bank) {
            $code = htmlspecialchars($bank['Code'] ?? 'N/A');
            $name = htmlspecialchars($bank['Name'] ?? 'N/A');
            $services = htmlspecialchars($bank['Services'] ?? 'N/A');
            
            echo "<tr>\n";
            echo "<td><strong>{$code}</strong></td>\n";
            echo "<td>{$name}</td>\n";
            echo "<td>{$services}</td>\n";
            echo "</tr>\n";
        }
        
        echo "</table>\n";
    }
    
    private function displayBankDropdown($banks) {
        if (!is_array($banks) || empty($banks)) {
            echo "<p>No banks available for dropdown</p>\n";
            return;
        }
        
        echo "<h3>Bank Selection Dropdown</h3>\n";
        echo "<select class='bank-dropdown' onchange='showSelectedBank(this)'>\n";
        echo "<option value=''>-- Select Your Bank --</option>\n";
        
        foreach ($banks as $bank) {
            $code = htmlspecialchars($bank['Code'] ?? '');
            $name = htmlspecialchars($bank['Name'] ?? '');
            $services = htmlspecialchars($bank['Services'] ?? '');
            
            $displayText = "{$code}: {$name}";
            if (!empty($services)) {
                $displayText .= " ({$services})";
            }
            
            $value = "{$code}|{$name}";
            
            echo "<option value='{$value}'>{$displayText}</option>\n";
        }
        
        echo "</select>\n";
        
        echo "
        <script>
        function showSelectedBank(select) {
            if(select.value) {
                const [code, name] = select.value.split('|');
                alert('Selected Bank: ' + code + ' - ' + name);
            }
        }
        </script>
        ";
        
        // Also show BNC bank specifically if found
        $bnc_found = false;
        foreach ($banks as $bank) {
            if (($bank['Code'] ?? '') === '0191') {
                $bnc_found = true;
                echo "<div class='success'>\n";
                echo "<h4>✓ BNC Bank Found and Available</h4>\n";
                echo "<p><strong>Code:</strong> " . htmlspecialchars($bank['Code'] ?? '') . "</p>\n";
                echo "<p><strong>Name:</strong> " . htmlspecialchars($bank['Name'] ?? '') . "</p>\n";
                echo "<p><strong>Services:</strong> " . htmlspecialchars($bank['Services'] ?? '') . "</p>\n";
                echo "</div>\n";
                break;
            }
        }
    }
    
    public function __destruct() {
        echo "</body>\n</html>";
    }
}

// Check if required extensions are available
if (!extension_loaded('openssl')) {
    die("<p class='error'><strong>ERROR:</strong> OpenSSL extension is required but not loaded.</p>\n");
}

if (!extension_loaded('mbstring')) {
    die("<p class='error'><strong>ERROR:</strong> MBString extension is required for UTF-8 handling but not loaded.</p>\n");
}

if (!function_exists('hash_pbkdf2')) {
    die("<p class='error'><strong>ERROR:</strong> hash_pbkdf2() function is required but not available. Please upgrade PHP.</p>\n");
}

// Run the test
$test = new PagoMovilBankTest();
$success = $test->runTests();

echo "<hr>\n";
if ($success) {
    echo "<h2 class='success'>✓ TEST COMPLETED SUCCESSFULLY</h2>\n";
    echo "<p>The bank list has been successfully retrieved and displayed in both table and dropdown format.</p>\n";
} else {
    echo "<h2 class='error'>✗ TEST FAILED</h2>\n";
    echo "<p>Check the error messages above for troubleshooting.</p>\n";
}

echo "<h3>Next Steps for Your WooCommerce Plugin:</h3>\n";
echo "<ul>\n";
echo "<li>Use the 'empty_object' format ({}) for bank list requests</li>\n";
echo "<li>Implement similar UTF-8 cleaning in your main plugin</li>\n";
echo "<li>Use the dropdown format: 'Code: Bank Name (Services)'</li>\n";
echo "<li>BNC bank code 0191 is confirmed available</li>\n";
echo "</ul>\n";
?>
en_USEnglish