<?php
//Developer: core tech web designTechnology
//Whatsapp: +2349162671360
//Telegram: @jeditech

// smscodes.io GetCountryPrices and smspva servicesprices can take 30-60+ seconds
set_time_limit(300);

if (session_status() === PHP_SESSION_NONE) {
    session_start();
}

header('Content-Type: application/json');

// ── Bootstrap ─────────────────────────────────────────────────────────────────
$config_path = dirname(__DIR__, 2) . '/include/config.php';
if (file_exists($config_path)) {
    include($config_path);
} else {
    echo json_encode(['status' => '0', 'msg' => 'Configuration file not found']);
    exit();
}

if (!defined('VALID_ACCESS')) {
    define('VALID_ACCESS', true);
}
require_once dirname(__DIR__, 2) . '/include/smspva_functions.php';

// ── Admin guard ───────────────────────────────────────────────────────────────
$stmt = $pdo->prepare("SELECT is_admin FROM users WHERE id = :user_id");
$stmt->bindParam(':user_id', $_SESSION['user_id'], PDO::PARAM_INT);
$stmt->execute();
$admin = $stmt->fetch(PDO::FETCH_ASSOC);

if (!$admin || $admin['is_admin'] != 1) {
    echo json_encode(['status' => '0', 'msg' => 'Unauthorized access']);
    exit();
}

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    echo json_encode(['status' => '0', 'msg' => 'Invalid request method']);
    exit();
}

$action = trim($_POST['action'] ?? '');

// ─── Helper: cURL GET (for smscodes-style plain URL calls) ────────────────────
function admin_curl_get(string $url, int $timeout = 90): string
{
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => $timeout,
        CURLOPT_CONNECTTIMEOUT => 30,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => 0,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_USERAGENT      => 'Mozilla/5.0 (compatible; Bot/1.0)',
        CURLOPT_ENCODING       => '',
        CURLOPT_BUFFERSIZE     => 1048576,
        CURLOPT_MAXREDIRS      => 5,
        CURLOPT_HTTP_VERSION   => CURL_HTTP_VERSION_1_1,
        CURLOPT_HTTPHEADER     => ['Accept: application/json', 'Connection: keep-alive'],
    ]);
    $res  = curl_exec($ch);
    $err  = curl_error($ch);
    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    if ($res === false || $res === '') {
        return 'CURL_ERROR: ' . ($err ?: 'Empty response, HTTP code: ' . $code);
    }
    return (string)$res;
}

// ─── Helper: Build smscodes.io API URL ────────────────────────────────────────
function smscodes_url(string $api_url, string $method, string $api_key, array $params = []): string
{
    $url = rtrim($api_url, '/') . '/' . ltrim($method, '/') . '?key=' . urlencode($api_key);
    foreach ($params as $k => $v) {
        $url .= '&' . urlencode($k) . '=' . urlencode($v);
    }
    return $url;
}


// ═════════════════════════════════════════════════════════════════════════════
// ACTION: sync_countries  (unchanged — works for smscodes)
// ═════════════════════════════════════════════════════════════════════════════
if ($action === 'sync_countries') {

    $api_id = filter_var($_POST['api_id'] ?? '', FILTER_VALIDATE_INT);
    if (!$api_id) { echo json_encode(['status'=>'0','msg'=>'Please select an API first.']); exit(); }

    try {
        $api_stmt = $pdo->prepare("SELECT * FROM api_detail WHERE id = :id LIMIT 1");
        $api_stmt->execute([':id' => $api_id]);
        $api = $api_stmt->fetch(PDO::FETCH_ASSOC);
    } catch (PDOException $e) {
        echo json_encode(['status'=>'0','msg'=>'DB error loading API.']); exit();
    }
    if (!$api) { echo json_encode(['status'=>'0','msg'=>'API not found.']); exit(); }

    $api_type = $api['api_type'] ?? 'smscodes';

    // ── smspva: sync countries from servicesprices ───────────────────────────
    if ($api_type === 'smspva') {

        // Step 1: Delete previously inserted junk rows (numeric server_codes)
        try {
            $pdo->prepare(
                "DELETE FROM otp_server WHERE api_id = :api_id AND server_code REGEXP '^[0-9]+$'"
            )->execute([':api_id' => $api_id]);
        } catch (PDOException $e) { /* non-fatal */ }

        // Step 2: Use servicesprices — the actual working endpoint.
        // Real response: {"statusCode":200,"data":[{"price":"0.50","service":"opt0",
        //   "serviceDescription":"...","country":"AL"}, ...]}
        // We collect unique "country" ISO values from the flat data array.
        $country_list = smspva_get_countries_from_servicesprices($api['api_url'], $api['api_key']);

        if (!$country_list || empty($country_list)) {
            echo json_encode(['status'=>'0','msg'=>'smspva returned no country data. Check API key and connectivity.']);
            exit();
        }

        $inserted = 0; $skipped = 0;
        foreach ($country_list as $iso => $country_name) {
            $iso_lower = strtolower($iso === 'UK' ? 'GB' : $iso);
            $flag_url  = 'https://flagcdn.com/w160/' . $iso_lower . '.png';

            try {
                $check = $pdo->prepare(
                    "SELECT id FROM otp_server WHERE server_code = :code AND api_id = :api_id LIMIT 1"
                );
                $check->execute([':code' => $iso, ':api_id' => $api_id]);
                $existing = $check->fetch(PDO::FETCH_ASSOC);

                if ($existing) {
                    $pdo->prepare(
                        "UPDATE otp_server SET server_name = :name,
                         flag_url = IF(flag_url = '' OR flag_url IS NULL, :flag, flag_url) WHERE id = :id"
                    )->execute([':name' => $country_name, ':flag' => $flag_url, ':id' => $existing['id']]);
                    $skipped++;
                } else {
                    $pdo->prepare(
                        "INSERT INTO otp_server (server_name, server_code, flag_url, api_id, status)
                         VALUES (:name, :code, :flag, :api_id, '1')"
                    )->execute([':name' => $country_name, ':code' => $iso, ':flag' => $flag_url, ':api_id' => $api_id]);
                    $inserted++;
                }
            } catch (PDOException $e) { $skipped++; }
        }

        echo json_encode([
            'status'   => '1',
            'msg'      => "smspva countries sync complete. <strong>{$inserted}</strong> new countries added, <strong>{$skipped}</strong> already existed / updated.",
            'inserted' => $inserted,
            'skipped'  => $skipped,
        ]);
        exit();
    }

    // ── smscodes: original logic ──────────────────────────────────────────────
    $url     = smscodes_url($api['api_url'], 'GetCountryCodes', $api['api_key']);
    $raw     = admin_curl_get($url, 60);
    $decoded = json_decode($raw, true);

    if (!is_array($decoded) || !isset($decoded['Countries']) || empty($decoded['Countries'])) {
        $error_msg = is_array($decoded) && isset($decoded['Error']) && $decoded['Error'] !== 'Non'
            ? $decoded['Error'] : 'Raw: ' . htmlspecialchars(substr($raw,0,300));
        echo json_encode(['status'=>'0','msg'=>'No countries returned from API. '.$error_msg]);
        exit();
    }

    if (isset($decoded['Status']) && strtoupper($decoded['Status']) !== 'SUCCESS') {
        echo json_encode(['status'=>'0','msg'=>'API error: '.($decoded['Error']??$decoded['Status'])]);
        exit();
    }

    $countries = $decoded['Countries'];
    $inserted  = 0; $skipped = 0;

    foreach ($countries as $data) {
        if (!is_array($data)) continue;
        $country_name = trim($data['CountryName'] ?? '');
        $country_code = trim($data['CountryCode'] ?? '');
        if ($country_name === '' || $country_code === '') continue;

        $iso_lower = strtolower($country_code === 'UK' ? 'GB' : $country_code);
        $flag_url  = 'https://flagcdn.com/w160/' . $iso_lower . '.png';

        try {
            $check = $pdo->prepare("SELECT id FROM otp_server WHERE server_code=:code AND api_id=:api_id LIMIT 1");
            $check->execute([':code'=>$country_code,':api_id'=>$api_id]);
            $existing = $check->fetch(PDO::FETCH_ASSOC);

            if ($existing) {
                $pdo->prepare(
                    "UPDATE otp_server SET server_name=:name,
                     flag_url=IF(flag_url='' OR flag_url IS NULL,:flag,flag_url) WHERE id=:id"
                )->execute([':name'=>$country_name,':flag'=>$flag_url,':id'=>$existing['id']]);
                $skipped++;
            } else {
                $pdo->prepare(
                    "INSERT INTO otp_server (server_name,server_code,flag_url,api_id,status)
                     VALUES (:name,:code,:flag,:api_id,'1')"
                )->execute([':name'=>$country_name,':code'=>$country_code,':flag'=>$flag_url,':api_id'=>$api_id]);
                $inserted++;
            }
        } catch (PDOException $e) { $skipped++; }
    }

    echo json_encode([
        'status'   => '1',
        'msg'      => "Sync complete. <strong>{$inserted}</strong> new countries added, <strong>{$skipped}</strong> already existed / updated.",
        'inserted' => $inserted,
        'skipped'  => $skipped,
    ]);
    exit();
}


// ═════════════════════════════════════════════════════════════════════════════
// ACTION: sync_services  (handles BOTH smscodes and smspva)
// ═════════════════════════════════════════════════════════════════════════════
if ($action === 'sync_services') {

    $server_id = filter_var($_POST['server_id'] ?? '', FILTER_VALIDATE_INT);
    $api_id    = filter_var($_POST['api_id']    ?? '', FILTER_VALIDATE_INT);

    if (!$server_id || !$api_id) {
        echo json_encode(['status'=>'0','msg'=>'Invalid server or API ID.']);
        exit();
    }

    try {
        $api_stmt = $pdo->prepare("SELECT * FROM api_detail WHERE id=:id LIMIT 1");
        $api_stmt->execute([':id'=>$api_id]);
        $api = $api_stmt->fetch(PDO::FETCH_ASSOC);

        $srv_stmt = $pdo->prepare("SELECT * FROM otp_server WHERE id=:id LIMIT 1");
        $srv_stmt->execute([':id'=>$server_id]);
        $server = $srv_stmt->fetch(PDO::FETCH_ASSOC);
    } catch (PDOException $e) {
        echo json_encode(['status'=>'0','msg'=>'DB error: '.$e->getMessage()]); exit();
    }

    if (!$api || !$server) {
        echo json_encode(['status'=>'0','msg'=>'API or server not found.']); exit();
    }

    // Price settings
    try {
        $ps = $pdo->query("SELECT setting_key,setting_value FROM price_settings")->fetchAll(PDO::FETCH_KEY_PAIR);
    } catch (PDOException $e) { $ps = []; }

    $api_type   = $api['api_type'] ?? 'smscodes';
    $country_iso = $server['server_code'];
    $inserted   = 0; $updated = 0; $skipped = 0;

    // ── smspva sync ───────────────────────────────────────────────────────────
    if ($api_type === 'smspva') {

        $markup_pct = isset($ps['smspva_markup_percent'])
            ? (float)$ps['smspva_markup_percent']
            : (isset($ps['markup_percent']) ? (float)$ps['markup_percent'] : 35.0);

        $usd_to_ngn = isset($ps['usd_to_ngn']) && (float)$ps['usd_to_ngn'] > 0
            ? (float)$ps['usd_to_ngn'] : 1600.0;

        // Fetch all services + prices for this country
        $prices = smspva_get_country_prices($api['api_url'], $api['api_key'], $country_iso);

        if (!$prices) {
            echo json_encode(['status'=>'0','msg'=>"smspva: no services found for {$country_iso}."]);
            exit();
        }

        // Service name: prefer the 'sd' (serviceDescription) field returned by the API.
        // Fall back to our full official name map, then the raw code.
        $name_map = smspva_service_name_map();

        foreach ($prices as $svc_code => $svc_data) {
            $ops = $svc_data['operators'] ?? [];

            // Pick cheapest operator — smspva returns count=999 (synthetic), filter on price > 0
            $available = array_filter($ops, function($o) { return $o['price'] > 0; });
            if (empty($available)) { $skipped++; continue; }

            usort($available, function($a, $b) { return $a['price'] < $b['price'] ? -1 : ($a['price'] > $b['price'] ? 1 : 0); });
            $best      = reset($available);
            $usd_price = (float)$best['price'];

            $naira_price = round($usd_price * $usd_to_ngn * (1 + $markup_pct / 100), 2);

            // Prefer API-returned name, then our map, then the raw code
            $api_name = trim($svc_data['service_name'] ?? '');
            $svc_name = ($api_name !== '' && $api_name !== $svc_code)
                ? $api_name
                : ($name_map[$svc_code] ?? strtoupper($svc_code));

            // Upsert into shared `service` table
            try {
                $check = $pdo->prepare(
                    "SELECT id FROM service WHERE service_id=:sid AND server_id=:svid LIMIT 1"
                );
                $check->execute([':sid'=>$svc_code, ':svid'=>$server_id]);
                $existing = $check->fetch(PDO::FETCH_ASSOC);

                if ($existing) {
                    $pdo->prepare(
                        "UPDATE service SET service_name=:name,service_price=:price WHERE id=:id"
                    )->execute([':name'=>$svc_name,':price'=>(string)$naira_price,':id'=>$existing['id']]);
                    $updated++;
                } else {
                    $pdo->prepare(
                        "INSERT INTO service (service_name,service_id,server_id,service_price,service_logo,status)
                         VALUES (:name,:sid,:svid,:price,'','1')"
                    )->execute([':name'=>$svc_name,':sid'=>$svc_code,':svid'=>$server_id,':price'=>(string)$naira_price]);
                    $inserted++;
                }

                // Also update smspva_service_cache for reference
                foreach ($ops as $op) {
                    if ($op['price'] <= 0) continue;
                    $ngn = round($op['price'] * $usd_to_ngn * (1 + $markup_pct / 100), 2);
                    try {
                        $pdo->prepare(
                            "INSERT INTO smspva_service_cache
                                (service_code,service_name,country_code,operator,usd_price,ngn_price,count_available)
                             VALUES (:sc,:sn,:cc,:op,:usd,:ngn,:cnt)
                             ON DUPLICATE KEY UPDATE
                                service_name=VALUES(service_name),usd_price=VALUES(usd_price),
                                ngn_price=VALUES(ngn_price),count_available=VALUES(count_available)"
                        )->execute([
                            ':sc'  => $svc_code,
                            ':sn'  => $svc_name,
                            ':cc'  => $country_iso,
                            ':op'  => $op['operator'] ?: 'any',
                            ':usd' => $op['price'],
                            ':ngn' => $ngn,
                            ':cnt' => $op['count'],
                        ]);
                    } catch (PDOException $e) { /* non-fatal */ }
                }

            } catch (PDOException $e) { $skipped++; }
        }

        // Record sync time
        try {
            $pdo->prepare(
                "INSERT INTO price_settings (setting_key,setting_value) VALUES (:key,NOW())
                 ON DUPLICATE KEY UPDATE setting_value=NOW(),updated_at=NOW()"
            )->execute([':key'=>'sync_country_'.$server_id]);
        } catch (PDOException $e) {}

        echo json_encode([
            'status'   => '1',
            'msg'      => "smspva sync done for {$country_iso}. +{$inserted} new, {$updated} updated, {$skipped} skipped.",
            'inserted' => $inserted,
            'updated'  => $updated,
            'skipped'  => $skipped,
        ]);
        exit();
    }

    // ── smscodes sync (original logic) ────────────────────────────────────────
    $markup_pct = isset($ps['markup_percent']) ? (float)$ps['markup_percent'] : 35.0;
    $usd_to_ngn = isset($ps['usd_to_ngn']) && (float)$ps['usd_to_ngn'] > 0 ? (float)$ps['usd_to_ngn'] : 1600.0;

    // Fetch logos once
    $logo_map  = [];
    $logo_url2 = smscodes_url($api['api_url'],'GetServiceCodeLogos',$api['api_key']);
    $logo_raw  = admin_curl_get($logo_url2, 30);
    $logo_resp = json_decode($logo_raw, true);
    if (is_array($logo_resp) && isset($logo_resp['Services'])) {
        foreach ($logo_resp['Services'] as $sv) {
            if (isset($sv['ServiceID'],$sv['ServiceLogo'])) {
                $logo_map[trim($sv['ServiceID'])] = trim($sv['ServiceLogo']);
            }
        }
    }

    $price_url = smscodes_url($api['api_url'],'GetCountryPrices',$api['api_key'],['iso'=>$country_iso]);
    $raw       = admin_curl_get($price_url, 90);
    $pdata     = json_decode($raw, true);

    if (!is_array($pdata) || !isset($pdata['Prices']) || empty($pdata['Prices'])) {
        $err = (is_array($pdata) && isset($pdata['Error']) && $pdata['Error']!=='Non') ? $pdata['Error'] : substr($raw,0,200);
        echo json_encode(['status'=>'0','msg'=>'No prices from smscodes. '.$err]);
        exit();
    }

    foreach ($pdata['Prices'] as $entry) {
        $svc_name  = trim($entry['ServiceName'] ?? '');
        $svc_id    = trim($entry['ServiceID']   ?? '');
        $usd_price = (float)($entry['Price']    ?? 0);

        if (empty($svc_name) || empty($svc_id) || $usd_price <= 0) { $skipped++; continue; }

        $naira_price = round($usd_price * $usd_to_ngn * (1 + $markup_pct / 100), 2);
        $logo_file   = $logo_map[$svc_id] ?? '';

        try {
            $check = $pdo->prepare("SELECT id FROM service WHERE service_id=:sid AND server_id=:svid LIMIT 1");
            $check->execute([':sid'=>$svc_id,':svid'=>$server_id]);
            $existing = $check->fetch(PDO::FETCH_ASSOC);

            if ($existing) {
                $pdo->prepare("UPDATE service SET service_name=:name,service_price=:price,service_logo=:logo WHERE id=:id")
                    ->execute([':name'=>$svc_name,':price'=>(string)$naira_price,':logo'=>$logo_file,':id'=>$existing['id']]);
                $updated++;
            } else {
                $pdo->prepare(
                    "INSERT INTO service (service_name,service_id,server_id,service_price,service_logo,status)
                     VALUES (:name,:sid,:svid,:price,:logo,'1')"
                )->execute([':name'=>$svc_name,':sid'=>$svc_id,':svid'=>$server_id,':price'=>(string)$naira_price,':logo'=>$logo_file]);
                $inserted++;
            }
        } catch (PDOException $e) { $skipped++; }
    }

    try {
        $pdo->prepare(
            "INSERT INTO price_settings (setting_key,setting_value) VALUES (:key,NOW())
             ON DUPLICATE KEY UPDATE setting_value=NOW(),updated_at=NOW()"
        )->execute([':key'=>'sync_country_'.$server_id]);
    } catch (PDOException $e) {}

    echo json_encode([
        'status'   => '1',
        'msg'      => "smscodes sync done for {$country_iso}. +{$inserted} new, {$updated} updated, {$skipped} skipped.",
        'inserted' => $inserted,
        'updated'  => $updated,
        'skipped'  => $skipped,
    ]);
    exit();
}


// ═════════════════════════════════════════════════════════════════════════════
// ACTION: smspva_balance  — check smspva account balance
// ═════════════════════════════════════════════════════════════════════════════
if ($action === 'smspva_balance') {
    try {
        $api = $pdo->query("SELECT * FROM api_detail WHERE api_type='smspva' LIMIT 1")->fetch(PDO::FETCH_ASSOC);
    } catch (PDOException $e) { $api = false; }

    if (!$api) {
        echo json_encode(['status'=>'0','msg'=>'smspva API not configured in api_detail table.']); exit();
    }

    $debug = smspva_get_balance_debug($api['api_url'], $api['api_key']);

    if ($debug['balance'] !== false) {
        // Cache the balance in price_settings for the admin page to show on load
        try {
            $pdo->prepare(
                "INSERT INTO price_settings (setting_key, setting_value) VALUES ('smspva_balance_cached', :b)
                 ON DUPLICATE KEY UPDATE setting_value = :b2, updated_at = NOW()"
            )->execute([':b' => $debug['balance'], ':b2' => $debug['balance']]);
        } catch (PDOException $e) { /* non-fatal */ }

        echo json_encode([
            'status'  => '1',
            'balance' => $debug['balance'],
            'msg'     => 'smspva balance: $'.number_format($debug['balance'], 4),
        ]);
    } else {
        // Return the raw API response so the admin can diagnose
        $raw_snippet = $debug['raw'];
        $hint = '';
        if (empty($raw_snippet)) {
            $hint = 'Empty response — check server connectivity and API URL.';
        } elseif (strpos($raw_snippet, 'smspva_curl_error') !== false) {
            $hint = 'Connection failed — verify the API URL is reachable.';
        } else {
            $hint = 'Unexpected response: ' . htmlspecialchars(substr($raw_snippet, 0, 200));
        }
        echo json_encode([
            'status' => '0',
            'msg'    => 'Could not read balance. ' . $hint,
            'debug'  => $debug['decoded'],
        ]);
    }
    exit();
}


// ═════════════════════════════════════════════════════════════════════════════
// ACTION: smspva_sync_countries  — auto-add countries from smspva servicesprices
// (shortcut that auto-detects the smspva API entry)
// ═════════════════════════════════════════════════════════════════════════════
if ($action === 'smspva_sync_countries') {
    // Shortcut: auto-detects smspva API, delegates to smspva_get_countries_from_servicesprices().
    try {
        $api = $pdo->query("SELECT * FROM api_detail WHERE api_type='smspva' LIMIT 1")->fetch(PDO::FETCH_ASSOC);
    } catch (PDOException $e) { $api = false; }

    if (!$api) {
        echo json_encode(['status'=>'0','msg'=>'smspva API not configured in api_detail.']); exit();
    }

    // Clean up any previously inserted junk numeric rows
    try {
        $pdo->prepare(
            "DELETE FROM otp_server WHERE api_id = :api_id AND server_code REGEXP '^[0-9]+$'"
        )->execute([':api_id' => $api['id']]);
    } catch (PDOException $e) {}

    // Use servicesprices: {"statusCode":200,"data":[{"country":"AL","service":"opt0",...}, ...]}
    $country_list = smspva_get_countries_from_servicesprices($api['api_url'], $api['api_key']);

    if (!$country_list || empty($country_list)) {
        echo json_encode(['status'=>'0','msg'=>'smspva returned no country data. Check API key and connectivity.']);
        exit();
    }

    $inserted = 0; $skipped = 0;
    foreach ($country_list as $iso => $country_name) {
        $iso_lower = strtolower($iso === 'UK' ? 'GB' : $iso);
        $flag_url  = 'https://flagcdn.com/w160/' . $iso_lower . '.png';
        try {
            $check = $pdo->prepare("SELECT id FROM otp_server WHERE server_code=:code AND api_id=:api_id LIMIT 1");
            $check->execute([':code' => $iso, ':api_id' => $api['id']]);
            $existing = $check->fetch(PDO::FETCH_ASSOC);
            if ($existing) {
                $pdo->prepare(
                    "UPDATE otp_server SET server_name=:name,
                     flag_url=IF(flag_url='' OR flag_url IS NULL,:flag,flag_url) WHERE id=:id"
                )->execute([':name'=>$country_name, ':flag'=>$flag_url, ':id'=>$existing['id']]);
                $skipped++;
            } else {
                $pdo->prepare(
                    "INSERT INTO otp_server (server_name,server_code,flag_url,api_id,status) VALUES (:n,:c,:f,:a,'1')"
                )->execute([':n'=>$country_name, ':c'=>$iso, ':f'=>$flag_url, ':a'=>$api['id']]);
                $inserted++;
            }
        } catch (PDOException $e) { $skipped++; }
    }

    echo json_encode([
        'status'   => '1',
        'msg'      => "smspva countries sync done. <strong>{$inserted}</strong> added, <strong>{$skipped}</strong> already existed / updated.",
        'inserted' => $inserted,
        'skipped'  => $skipped,
    ]);
    exit();
}


// ═════════════════════════════════════════════════════════════════════════════
// ACTION: save_smspva_markup  — save smspva-specific markup
// ═════════════════════════════════════════════════════════════════════════════
if ($action === 'save_smspva_markup') {
    $markup = filter_var($_POST['markup'] ?? '', FILTER_VALIDATE_FLOAT);
    if ($markup === false || $markup < 0) {
        echo json_encode(['status'=>'0','msg'=>'Invalid markup value.']); exit();
    }
    try {
        $pdo->prepare(
            "INSERT INTO price_settings (setting_key,setting_value) VALUES ('smspva_markup_percent',:m)
             ON DUPLICATE KEY UPDATE setting_value=:m2,updated_at=NOW()"
        )->execute([':m'=>round($markup,2),':m2'=>round($markup,2)]);
        echo json_encode(['status'=>'1','msg'=>'smspva markup saved: '.round($markup,2).'%']);
    } catch (PDOException $e) {
        echo json_encode(['status'=>'0','msg'=>'DB error: '.$e->getMessage()]);
    }
    exit();
}


// ═════════════════════════════════════════════════════════════════════════════
// ACTION: toggle_smspva  — enable/disable smspva provider
// ═════════════════════════════════════════════════════════════════════════════
if ($action === 'toggle_smspva') {
    $enabled = in_array($_POST['enabled']??'',['0','1']) ? $_POST['enabled'] : '0';
    try {
        $pdo->prepare(
            "INSERT INTO price_settings (setting_key,setting_value) VALUES ('smspva_api_enabled',:v)
             ON DUPLICATE KEY UPDATE setting_value=:v2,updated_at=NOW()"
        )->execute([':v'=>$enabled,':v2'=>$enabled]);
        echo json_encode(['status'=>'1','msg'=>'smspva '.($enabled==='1'?'enabled':'disabled').'.','enabled'=>$enabled]);
    } catch (PDOException $e) {
        echo json_encode(['status'=>'0','msg'=>'DB error: '.$e->getMessage()]);
    }
    exit();
}


// ═════════════════════════════════════════════════════════════════════════════
// Remaining original actions (refresh_rate, resync_prices, save_rates_manual,
// toggle_auto_refresh, get_cron_logs, debug_countries) — preserved unchanged
// ═════════════════════════════════════════════════════════════════════════════

if ($action === 'refresh_rate') {
    // Live rate fetching is disabled. The USD→NGN rate is set manually by the admin
    // in Sync Services → Exchange Rate. Use the Save Rate button to update it.
    try {
        $rows = $pdo->query("SELECT setting_key,setting_value FROM price_settings WHERE setting_key='usd_to_ngn'")->fetchAll(PDO::FETCH_KEY_PAIR);
    } catch (PDOException $e) { $rows=[]; }
    $c_usd = (float)($rows['usd_to_ngn'] ?? 1600.0);
    echo json_encode([
        'status'   => '0',
        'msg'      => 'Live rate fetching is disabled. Current admin-set rate: ₦' . number_format($c_usd, 2) . '. Use the Save Rate button to update it manually.',
        'usd_rate' => $c_usd,
    ]);
    exit();
}

if ($action === 'resync_prices') {
    try {
        $servers = $pdo->query("SELECT * FROM otp_server WHERE status='1'")->fetchAll(PDO::FETCH_ASSOC);
        $ps_rows = $pdo->query("SELECT setting_key,setting_value FROM price_settings")->fetchAll(PDO::FETCH_KEY_PAIR);
    } catch (PDOException $e) {
        echo json_encode(['status'=>'0','msg'=>'DB error: '.$e->getMessage()]); exit();
    }

    $markup_pct = (float)($ps_rows['markup_percent'] ?? 35.0);
    $smspva_mup = (float)($ps_rows['smspva_markup_percent'] ?? $markup_pct);
    $usd_to_ngn = (float)($ps_rows['usd_to_ngn'] > 0 ? $ps_rows['usd_to_ngn'] : 1600.0);

    $total_updated = 0; $total_skipped = 0; $countries_processed = 0;
    $api_cache = [];
    try {
        foreach ($pdo->query("SELECT * FROM api_detail")->fetchAll(PDO::FETCH_ASSOC) as $a) {
            $api_cache[(int)$a['id']] = $a;
        }
    } catch (PDOException $e) {}

    foreach ($servers as $server) {
        $api = $api_cache[(int)$server['api_id']] ?? null;
        if (!$api) continue;

        $api_type    = $api['api_type'] ?? 'smscodes';
        $country_iso = $server['server_code'];

        if ($api_type === 'smspva') {
            $mup    = $smspva_mup;
            $prices = smspva_get_country_prices($api['api_url'],$api['api_key'],$country_iso);
            if (!$prices) continue;

            $countries_processed++;
            foreach ($prices as $svc_code => $svc_data) {
                $ops = array_filter(isset($svc_data['operators']) ? $svc_data['operators'] : [], function($o) { return $o['price'] > 0 && $o['count'] > 0; });
                if (empty($ops)) { $total_skipped++; continue; }
                usort($ops, function($a, $b) { return $a['price'] < $b['price'] ? -1 : ($a['price'] > $b['price'] ? 1 : 0); });
                $best  = reset($ops);
                $naira = round($best['price']*$usd_to_ngn*(1+$mup/100),2);
                try {
                    $pdo->prepare("UPDATE service SET service_price=:p WHERE service_id=:sid AND server_id=:svid")
                        ->execute([':p'=>(string)$naira,':sid'=>$svc_code,':svid'=>$server['id']]);
                    $total_updated++;
                } catch (PDOException $e) { $total_skipped++; }
            }
        } else {
            $mup       = $markup_pct;
            $price_url = smscodes_url($api['api_url'],'GetCountryPrices',$api['api_key'],['iso'=>$country_iso]);
            $raw       = admin_curl_get($price_url,90);
            $pdata     = json_decode($raw,true);
            if (!is_array($pdata)||!isset($pdata['Prices'])||empty($pdata['Prices'])) continue;

            $countries_processed++;
            foreach ($pdata['Prices'] as $entry) {
                $sid   = trim($entry['ServiceID']??'');
                $price = (float)($entry['Price']??0);
                if (!$sid||$price<=0) { $total_skipped++; continue; }
                $naira = round($price*$usd_to_ngn*(1+$mup/100),2);
                try {
                    $pdo->prepare("UPDATE service SET service_price=:p WHERE service_id=:sid AND server_id=:svid")
                        ->execute([':p'=>(string)$naira,':sid'=>$sid,':svid'=>$server['id']]);
                    $total_updated++;
                } catch (PDOException $e) { $total_skipped++; }
            }
        }
    }

    echo json_encode([
        'status'=>'1',
        'msg'=>"Price resync complete. <strong>{$countries_processed}</strong> countries, "
             ."<strong>{$total_updated}</strong> prices updated, <strong>{$total_skipped}</strong> skipped.",
        'updated'=>$total_updated,
    ]);
    exit();
}

if ($action === 'save_rates_manual') {
    $usd_to_ngn = filter_var($_POST['usd_to_ngn']??'',FILTER_VALIDATE_FLOAT);
    if ($usd_to_ngn===false||$usd_to_ngn<=0) {
        echo json_encode(['status'=>'0','msg'=>'Invalid USD rate. Must be greater than 0.']); exit();
    }
    try {
        $pdo->prepare(
            "INSERT INTO price_settings (setting_key,setting_value) VALUES ('usd_to_ngn',:usd),('rate_updated_at',NOW())
             ON DUPLICATE KEY UPDATE setting_value=VALUES(setting_value),updated_at=NOW()"
        )->execute([':usd'=>round($usd_to_ngn,4)]);
        echo json_encode(['status'=>'1','msg'=>'Exchange rate updated manually.','usd_rate'=>round($usd_to_ngn,4)]);
    } catch (PDOException $e) {
        echo json_encode(['status'=>'0','msg'=>'DB error: '.$e->getMessage()]);
    }
    exit();
}

if ($action === 'toggle_auto_refresh') {
    $enabled = in_array($_POST['enabled']??'',['0','1'])?$_POST['enabled']:'0';
    try {
        $pdo->prepare(
            "INSERT INTO price_settings (setting_key,setting_value) VALUES ('auto_refresh_enabled',:val)
             ON DUPLICATE KEY UPDATE setting_value=:val2,updated_at=NOW()"
        )->execute([':val'=>$enabled,':val2'=>$enabled]);
        echo json_encode(['status'=>'1','msg'=>'Auto-refresh '.($enabled=='1'?'enabled':'disabled').'.','enabled'=>$enabled]);
    } catch (PDOException $e) {
        echo json_encode(['status'=>'0','msg'=>'DB error: '.$e->getMessage()]);
    }
    exit();
}

if ($action === 'get_cron_logs') {
    try {
        $stmt = $pdo->query(
            "SELECT id,run_time,countries_processed,services_updated,services_skipped,duration_seconds,status,details
               FROM cron_log ORDER BY run_time DESC LIMIT 20"
        );
        $logs = $stmt->fetchAll(PDO::FETCH_ASSOC);
        foreach ($logs as &$log) {
            $secs = (int)$log['duration_seconds'];
            $log['duration'] = $secs>=60 ? floor($secs/60).'m '.($secs%60).'s' : $secs.'s';
        }
        unset($log);
        echo json_encode(['status'=>'1','logs'=>$logs]);
    } catch (PDOException $e) {
        echo json_encode(['status'=>'0','msg'=>'DB error: '.$e->getMessage()]);
    }
    exit();
}

if ($action === 'get_smspva_cron_logs') {
    try {
        $stmt = $pdo->query(
            "SELECT id,run_time,countries_processed,services_updated,services_skipped,duration_seconds,status,details
               FROM smspva_cron_log ORDER BY run_time DESC LIMIT 20"
        );
        $logs = $stmt->fetchAll(PDO::FETCH_ASSOC);
        foreach ($logs as &$log) {
            $secs = (int)$log['duration_seconds'];
            $log['duration'] = $secs>=60 ? floor($secs/60).'m '.($secs%60).'s' : $secs.'s';
        }
        unset($log);
        echo json_encode(['status'=>'1','logs'=>$logs]);
    } catch (PDOException $e) {
        echo json_encode(['status'=>'0','msg'=>'DB error: '.$e->getMessage()]);
    }
    exit();
}

if ($action === 'debug_countries') {
    $api_id = filter_var($_POST['api_id']??'',FILTER_VALIDATE_INT);
    if (!$api_id) { echo json_encode(['status'=>'0','msg'=>'Select an API.']); exit(); }
    try {
        $api_stmt = $pdo->prepare("SELECT * FROM api_detail WHERE id=:id LIMIT 1");
        $api_stmt->execute([':id'=>$api_id]);
        $api = $api_stmt->fetch(PDO::FETCH_ASSOC);
    } catch (PDOException $e) { echo json_encode(['status'=>'0','msg'=>'DB error.']); exit(); }
    if (!$api) { echo json_encode(['status'=>'0','msg'=>'API not found.']); exit(); }

    $api_type = $api['api_type']??'smscodes';
    if ($api_type==='smspva') {
        $url = rtrim($api['api_url'],'/').'/activation/servicesprices';
        $raw = smspva_curl_get($url,$api['api_key'],60);
    } else {
        $url = smscodes_url($api['api_url'],'GetCountryCodes',$api['api_key']);
        $raw = admin_curl_get($url,60);
    }
    $decoded = json_decode($raw,true);
    echo json_encode(['status'=>'1','sample'=>is_array($decoded)?$decoded:$raw,'raw_snippet'=>substr($raw,0,800),'url_called'=>$url]);
    exit();
}

// ═════════════════════════════════════════════════════════════════════════════
// ACTION: smspva_debug  — test all smspva endpoints and show raw responses
// ═════════════════════════════════════════════════════════════════════════════
if ($action === 'smspva_debug') {
    try {
        $api = $pdo->query("SELECT * FROM api_detail WHERE api_type='smspva' LIMIT 1")->fetch(PDO::FETCH_ASSOC);
    } catch (PDOException $e) { $api = false; }

    if (!$api) {
        echo json_encode(['status'=>'0','msg'=>'smspva API not configured.']); exit();
    }

    $base    = rtrim($api['api_url'], '/');
    $key     = $api['api_key'];
    $results = [];

    // Test each endpoint — capture raw response + HTTP code
    $endpoints = [
        'balance'         => $base . '/activation/balance',
        'getcountries'    => $base . '/activation/getcountries',
        'servicesprices'  => $base . '/activation/servicesprices',
        'countnumbers_RU' => $base . '/activation/countnumbers/RU',
        'serviceprice_RU' => $base . '/activation/serviceprice/RU',
    ];

    foreach ($endpoints as $label => $url) {
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT        => 20,
            CURLOPT_CONNECTTIMEOUT => 10,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => 0,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_USERAGENT      => 'Mozilla/5.0 (compatible; OTPBot/2.0)',
            CURLOPT_ENCODING       => '',
            CURLOPT_HTTPHEADER     => [
                'apikey: ' . $key,
                'Accept: application/json',
            ],
        ]);
        $raw      = curl_exec($ch);
        $http     = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $curl_err = curl_error($ch);
        curl_close($ch);

        $decoded = json_decode($raw, true);

        $results[$label] = [
            'url'        => $url,
            'http_code'  => $http,
            'curl_error' => $curl_err ?: null,
            'raw_length' => strlen($raw),
            // For servicesprices only show structure preview (response can be huge)
            'raw_snippet'=> substr($raw, 0, 400),
            'decoded_type'=> gettype($decoded),
            // Show first 2 keys/items so we understand the structure
            'structure_preview' => is_array($decoded)
                ? array_slice($decoded, 0, 2, true)
                : null,
            'first_key'  => is_array($decoded) ? array_key_first($decoded) : null,
            'is_numeric_key' => is_array($decoded) ? is_numeric(array_key_first($decoded)) : null,
        ];
    }

    echo json_encode([
        'status'   => '1',
        'api_url'  => $base,
        'api_key_preview' => substr($key, 0, 8) . '...',
        'results'  => $results,
    ]);
    exit();
}

// ─── Unknown action ───────────────────────────────────────────────────────────
echo json_encode(['status'=>'0','msg'=>'Unknown action']);


// ═════════════════════════════════════════════════════════════════════════════
// HELPER: smspva service code → readable name map
// ═════════════════════════════════════════════════════════════════════════════
function smspva_country_id_map(): array
{
    // Maps smspva.com internal numeric country IDs to ISO codes + English names.
    // Source: smspva.com documentation + empirical testing.
    // Used when servicesprices returns numeric outer keys instead of ISO codes.
    return [
        1  => ['iso'=>'RU','name'=>'Russia'],
        2  => ['iso'=>'UA','name'=>'Ukraine'],
        3  => ['iso'=>'KZ','name'=>'Kazakhstan'],
        4  => ['iso'=>'CN','name'=>'China'],
        5  => ['iso'=>'PH','name'=>'Philippines'],
        6  => ['iso'=>'MM','name'=>'Myanmar'],
        7  => ['iso'=>'ID','name'=>'Indonesia'],
        8  => ['iso'=>'MA','name'=>'Morocco'],
        9  => ['iso'=>'EG','name'=>'Egypt'],
        10 => ['iso'=>'IN','name'=>'India'],
        11 => ['iso'=>'IE','name'=>'Ireland'],
        12 => ['iso'=>'GB','name'=>'United Kingdom'],
        13 => ['iso'=>'TZ','name'=>'Tanzania'],
        14 => ['iso'=>'US','name'=>'United States'],
        15 => ['iso'=>'IL','name'=>'Israel'],
        16 => ['iso'=>'HK','name'=>'Hong Kong'],
        17 => ['iso'=>'PL','name'=>'Poland'],
        18 => ['iso'=>'UZ','name'=>'Uzbekistan'],
        19 => ['iso'=>'SE','name'=>'Sweden'],
        20 => ['iso'=>'KG','name'=>'Kyrgyzstan'],
        21 => ['iso'=>'LT','name'=>'Lithuania'],
        22 => ['iso'=>'AR','name'=>'Argentina'],
        23 => ['iso'=>'BR','name'=>'Brazil'],
        24 => ['iso'=>'NG','name'=>'Nigeria'],
        25 => ['iso'=>'BD','name'=>'Bangladesh'],
        26 => ['iso'=>'FR','name'=>'France'],
        27 => ['iso'=>'KH','name'=>'Cambodia'],
        28 => ['iso'=>'VN','name'=>'Vietnam'],
        29 => ['iso'=>'LK','name'=>'Sri Lanka'],
        30 => ['iso'=>'PK','name'=>'Pakistan'],
        31 => ['iso'=>'MX','name'=>'Mexico'],
        32 => ['iso'=>'TR','name'=>'Turkey'],
        33 => ['iso'=>'GH','name'=>'Ghana'],
        34 => ['iso'=>'CO','name'=>'Colombia'],
        35 => ['iso'=>'NP','name'=>'Nepal'],
        36 => ['iso'=>'PY','name'=>'Paraguay'],
        37 => ['iso'=>'ZA','name'=>'South Africa'],
        38 => ['iso'=>'LA','name'=>'Laos'],
        39 => ['iso'=>'TH','name'=>'Thailand'],
        40 => ['iso'=>'MD','name'=>'Moldova'],
        41 => ['iso'=>'BY','name'=>'Belarus'],
        42 => ['iso'=>'DE','name'=>'Germany'],
        43 => ['iso'=>'LV','name'=>'Latvia'],
        44 => ['iso'=>'AT','name'=>'Austria'],
        45 => ['iso'=>'RO','name'=>'Romania'],
        46 => ['iso'=>'HU','name'=>'Hungary'],
        47 => ['iso'=>'GE','name'=>'Georgia'],
        48 => ['iso'=>'PT','name'=>'Portugal'],
        49 => ['iso'=>'CZ','name'=>'Czech Republic'],
        50 => ['iso'=>'BG','name'=>'Bulgaria'],
        51 => ['iso'=>'IT','name'=>'Italy'],
        52 => ['iso'=>'TJ','name'=>'Tajikistan'],
        53 => ['iso'=>'AM','name'=>'Armenia'],
        54 => ['iso'=>'RS','name'=>'Serbia'],
        55 => ['iso'=>'AZ','name'=>'Azerbaijan'],
        56 => ['iso'=>'MN','name'=>'Mongolia'],
        57 => ['iso'=>'MY','name'=>'Malaysia'],
        58 => ['iso'=>'PE','name'=>'Peru'],
        59 => ['iso'=>'KR','name'=>'South Korea'],
        60 => ['iso'=>'ET','name'=>'Ethiopia'],
        61 => ['iso'=>'CL','name'=>'Chile'],
        62 => ['iso'=>'KE','name'=>'Kenya'],
        63 => ['iso'=>'SK','name'=>'Slovakia'],
        64 => ['iso'=>'VE','name'=>'Venezuela'],
        65 => ['iso'=>'HR','name'=>'Croatia'],
        66 => ['iso'=>'GW','name'=>'Guinea-Bissau'],
        67 => ['iso'=>'CI','name'=>'Ivory Coast'],
        68 => ['iso'=>'SN','name'=>'Senegal'],
        69 => ['iso'=>'MG','name'=>'Madagascar'],
        70 => ['iso'=>'CM','name'=>'Cameroon'],
        71 => ['iso'=>'EC','name'=>'Ecuador'],
        72 => ['iso'=>'TM','name'=>'Turkmenistan'],
        73 => ['iso'=>'SI','name'=>'Slovenia'],
        74 => ['iso'=>'BO','name'=>'Bolivia'],
        75 => ['iso'=>'ES','name'=>'Spain'],
        76 => ['iso'=>'NL','name'=>'Netherlands'],
        77 => ['iso'=>'RW','name'=>'Rwanda'],
        78 => ['iso'=>'BE','name'=>'Belgium'],
        79 => ['iso'=>'MZ','name'=>'Mozambique'],
        80 => ['iso'=>'ZM','name'=>'Zambia'],
        81 => ['iso'=>'MK','name'=>'North Macedonia'],
        82 => ['iso'=>'YE','name'=>'Yemen'],
        83 => ['iso'=>'UG','name'=>'Uganda'],
        84 => ['iso'=>'GN','name'=>'Guinea'],
        85 => ['iso'=>'CA','name'=>'Canada'],
        86 => ['iso'=>'ZW','name'=>'Zimbabwe'],
        87 => ['iso'=>'LY','name'=>'Libya'],
        88 => ['iso'=>'DK','name'=>'Denmark'],
        89 => ['iso'=>'SY','name'=>'Syria'],
        90 => ['iso'=>'JP','name'=>'Japan'],
        91 => ['iso'=>'FI','name'=>'Finland'],
        92 => ['iso'=>'IQ','name'=>'Iraq'],
        93 => ['iso'=>'SA','name'=>'Saudi Arabia'],
        94 => ['iso'=>'SD','name'=>'Sudan'],
        95 => ['iso'=>'CD','name'=>'DR Congo'],
        96 => ['iso'=>'TT','name'=>'Trinidad and Tobago'],
        97 => ['iso'=>'SL','name'=>'Sierra Leone'],
        98 => ['iso'=>'AU','name'=>'Australia'],
        99 => ['iso'=>'SO','name'=>'Somalia'],
        100=> ['iso'=>'MU','name'=>'Mauritius'],
        101=> ['iso'=>'BF','name'=>'Burkina Faso'],
        102=> ['iso'=>'GT','name'=>'Guatemala'],
        103=> ['iso'=>'TG','name'=>'Togo'],
        104=> ['iso'=>'AF','name'=>'Afghanistan'],
        105=> ['iso'=>'CU','name'=>'Cuba'],
        106=> ['iso'=>'SV','name'=>'El Salvador'],
        107=> ['iso'=>'DO','name'=>'Dominican Republic'],
        108=> ['iso'=>'JM','name'=>'Jamaica'],
        109=> ['iso'=>'GR','name'=>'Greece'],
        110=> ['iso'=>'AO','name'=>'Angola'],
        111=> ['iso'=>'QA','name'=>'Qatar'],
        112=> ['iso'=>'TN','name'=>'Tunisia'],
        113=> ['iso'=>'BI','name'=>'Burundi'],
        114=> ['iso'=>'ML','name'=>'Mali'],
        115=> ['iso'=>'NE','name'=>'Niger'],
        116=> ['iso'=>'BJ','name'=>'Benin'],
        117=> ['iso'=>'MW','name'=>'Malawi'],
        118=> ['iso'=>'CF','name'=>'Central African Republic'],
        119=> ['iso'=>'KW','name'=>'Kuwait'],
        120=> ['iso'=>'DZ','name'=>'Algeria'],
        121=> ['iso'=>'AE','name'=>'United Arab Emirates'],
        122=> ['iso'=>'PG','name'=>'Papua New Guinea'],
        123=> ['iso'=>'GA','name'=>'Gabon'],
        124=> ['iso'=>'BA','name'=>'Bosnia and Herzegovina'],
        125=> ['iso'=>'AL','name'=>'Albania'],
        126=> ['iso'=>'ME','name'=>'Montenegro'],
        127=> ['iso'=>'LB','name'=>'Lebanon'],
        128=> ['iso'=>'JO','name'=>'Jordan'],
        129=> ['iso'=>'IR','name'=>'Iran'],
        130=> ['iso'=>'OM','name'=>'Oman'],
        131=> ['iso'=>'KM','name'=>'Comoros'],
        132=> ['iso'=>'MT','name'=>'Malta'],
        133=> ['iso'=>'HN','name'=>'Honduras'],
        134=> ['iso'=>'NI','name'=>'Nicaragua'],
        135=> ['iso'=>'PA','name'=>'Panama'],
        136=> ['iso'=>'CR','name'=>'Costa Rica'],
        137=> ['iso'=>'UY','name'=>'Uruguay'],
        138=> ['iso'=>'EE','name'=>'Estonia'],
        139=> ['iso'=>'BH','name'=>'Bahrain'],
        140=> ['iso'=>'BZ','name'=>'Belize'],
        141=> ['iso'=>'MR','name'=>'Mauritania'],
        142=> ['iso'=>'GM','name'=>'Gambia'],
        143=> ['iso'=>'SC','name'=>'Seychelles'],
        144=> ['iso'=>'SZ','name'=>'Eswatini'],
        145=> ['iso'=>'LS','name'=>'Lesotho'],
        146=> ['iso'=>'NA','name'=>'Namibia'],
        147=> ['iso'=>'BW','name'=>'Botswana'],
        148=> ['iso'=>'SB','name'=>'Solomon Islands'],
        149=> ['iso'=>'TO','name'=>'Tonga'],
        150=> ['iso'=>'FJ','name'=>'Fiji'],
    ];
}

function smspva_service_name_map(): array
{
    // Complete service list from smspva.com official documentation (260 services)
    return [
        'opt0'   => 'myopinions & erewards',
        'opt1'   => 'Google (YouTube, Gmail)',
        'opt2'   => 'Facebook',
        'opt3'   => 'Parimatch',
        'opt4'   => 'Mail.ru Group',
        'opt5'   => 'OD',
        'opt6'   => 'Fiverr',
        'opt7'   => 'MS Office 365',
        'opt8'   => 'LinkedIn',
        'opt9'   => 'Tinder',
        'opt10'  => 'AOL',
        'opt11'  => 'Viber',
        'opt13'  => 'Fotostrana',
        'opt15'  => 'Microsoft (Azure, Bing, Skype, etc)',
        'opt16'  => 'Instagram (+Threads)',
        'opt17'  => 'bet365',
        'opt18'  => 'Qiwi',
        'opt19'  => 'OTHER (no guarantee)',
        'opt20'  => 'WhatsAPP',
        'opt21'  => 'EasyPay',
        'opt22'  => '888casino',
        'opt23'  => 'Yandex & YooMoney',
        'opt24'  => 'WebMoney & ENUM',
        'opt25'  => 'BetFair',
        'opt26'  => 'CrigslistApp',
        'opt27'  => 'PapaJohns',
        'opt28'  => 'Gamers set (offgamers.com, G2A.com, seagm.com)',
        'opt29'  => 'Telegram',
        'opt30'  => 'GrabTaxi',
        'opt31'  => 'Drug Vokrug',
        'opt32'  => 'Drom.RU',
        'opt33'  => 'Mail.RU',
        'opt34'  => 'Tencent QQ',
        'opt35'  => 'GetTaxi',
        'opt37'  => 'Line Messenger',
        'opt38'  => 'Sisal',
        'opt39'  => 'Verse',
        'opt40'  => 'Doordash',
        'opt41'  => 'X (Twitter)',
        'opt42'  => 'LiveScore',
        'opt43'  => 'FastMail',
        'opt44'  => 'Amazon',
        'opt45'  => 'Discord',
        'opt46'  => 'Airbnb',
        'opt47'  => 'MoneyLion',
        'opt48'  => 'Shopee',
        'opt49'  => 'Skout',
        'opt51'  => 'CONTACT',
        'opt52'  => 'Ticketmaster',
        'opt53'  => 'Deliveroo',
        'opt54'  => 'Weebly',
        'opt55'  => 'ifood',
        'opt56'  => 'Badoo',
        'opt57'  => 'Proton Mail',
        'opt58'  => 'Steam',
        'opt59'  => 'Avito',
        'opt60'  => 'Lazada',
        'opt61'  => 'Alibaba (Taobao, 1688.com)',
        'opt65'  => 'Yahoo',
        'opt66'  => 'Twilio',
        'opt67'  => 'WeChat',
        'opt68'  => 'G2A.COM',
        'opt69'  => 'VK (no guarantee)',
        'opt70'  => 'OLX',
        'opt71'  => 'KakaoTalk',
        'opt72'  => 'Uber',
        'opt73'  => 'Naver',
        'opt74'  => 'Taxi Maksim',
        'opt75'  => 'Lyft',
        'opt76'  => 'CityMobil',
        'opt77'  => 'Gameflip',
        'opt78'  => 'Blizzard',
        'opt80'  => 'WESTSTEIN',
        'opt81'  => 'Bolt',
        'opt82'  => 'Tango',
        'opt83'  => 'PayPal + Ebay',
        'opt84'  => 'POF',
        'opt85'  => 'giocodigitale.it',
        'opt86'  => 'Adidas & Nike',
        'opt88'  => 'Yalla.live',
        'opt89'  => 'Careem',
        'opt90'  => 'Snapchat',
        'opt91'  => 'Wise',
        'opt92'  => 'DiDi',
        'opt93'  => 'Zoho',
        'opt94'  => 'JD.com',
        'opt95'  => 'NetBet',
        'opt96'  => 'MiChat',
        'opt97'  => 'Kuper (SberMarket)',
        'opt98'  => 'Clubhouse',
        'opt99'  => 'KoronaPay',
        'opt100' => 'Mamba',
        'opt101' => 'Netflix',
        'opt103' => 'ICard',
        'opt104' => 'TikTok',
        'opt105' => 'LocalBitcoins',
        'opt106' => 'Wing Money',
        'opt107' => 'Prom.UA',
        'opt108' => 'Glovo & Raketa',
        'opt109' => 'Paddy Power',
        'opt110' => 'Grindr',
        'opt111' => 'IMO',
        'opt112' => 'CoinBase',
        'opt113' => 'OfferUp',
        'opt114' => 'Locanto.com',
        'opt115' => 'foodpanda',
        'opt116' => 'Neteller',
        'opt117' => 'Skrill',
        'opt118' => 'Inboxdollars',
        'opt119' => 'Nico',
        'opt120' => 'Hinge',
        'opt121' => 'Monese',
        'opt122' => 'Paysafecard',
        'opt123' => 'Whoosh',
        'opt124' => 'Credit Karma',
        'opt125' => 'Swagbucks',
        'opt126' => 'Magnit',
        'opt127' => 'Signal',
        'opt129' => 'kwiff.com',
        'opt130' => 'Vinted',
        'opt131' => 'Apple',
        'opt132' => 'OpenAI API (chatGPT, DALL-e 2)',
        'opt133' => 'Revolut',
        'opt134' => 'Schibsted-konto',
        'opt135' => 'blsspain-russia.com',
        'opt136' => 'dundle',
        'opt137' => 'bwin',
        'opt138' => 'Bazos.sk',
        'opt139' => 'fontbet',
        'opt140' => 'Google Voice',
        'opt141' => 'EUROBET',
        'opt142' => 'funpay',
        'opt143' => 'autocosmos.com',
        'opt144' => 'hopper',
        'opt145' => 'bumble',
        'opt146' => 'subito.it',
        'opt147' => 'VooV Meeting',
        'opt148' => 'casa.it',
        'opt149' => 'pm.by',
        'opt150' => 'Czech email services',
        'opt151' => 'novibet.com',
        'opt152' => 'kleinanzeigen.de',
        'opt153' => 'ROOMSTER',
        'opt154' => 'Rambler.ru',
        'opt155' => 'Happn',
        'opt156' => 'mobileDE',
        'opt157' => 'CupidMedia',
        'opt158' => 'Zalo',
        'opt159' => 'Feeld',
        'opt160' => 'U By Prodia',
        'opt161' => 'TANK.RU',
        'opt162' => 'Payoneer',
        'opt163' => 'Wolt',
        'opt164' => 'Leboncoin',
        'opt165' => 'idealista.com',
        'opt166' => 'HUAWEI',
        'opt167' => 'inbox.lv',
        'opt169' => 'Pari.ru',
        'opt170' => 'Royal Canin',
        'opt171' => 'Marktplaats',
        'opt172' => 'WEB.DE',
        'opt173' => 'X World Wallet',
        'opt174' => 'Samsung',
        'opt175' => 'Klarna',
        'opt176' => 'ChoTot',
        'opt177' => 'NHNcorp',
        'opt178' => 'VonageVF',
        'opt179' => 'GetsBet.ro',
        'opt180' => 'Lalamove',
        'opt181' => 'OZON.ru',
        'opt182' => 'LAPOSTE',
        'opt183' => 'PAYSEND',
        'opt184' => 'MOMO',
        'opt185' => 'Samokat',
        'opt186' => 'RusDate',
        'opt187' => 'Beget.com',
        'opt188' => 'GGbet',
        'opt189' => 'foodora',
        'opt190' => 'SNKRDUNK',
        'opt191' => 'TopCashback',
        'opt192' => 'Betano (all countries)',
        'opt193' => 'Ipsos',
        'opt194' => 'ZoomInfo',
        'opt195' => 'Lajumate.ro',
        'opt196' => 'Claude (Anthropic)',
        'opt197' => 'MPSellers',
        'opt198' => 'Nectar',
        'opt199' => 'bunq',
        'opt200' => 'ENEBA',
        'opt201' => 'Casino Plus',
        'opt202' => 'NHNCloud',
        'opt203' => 'HelloTalk',
        'opt204' => 'DenimApp',
        'opt205' => 'Twitch',
        'opt206' => 'WalletHub',
        'opt207' => 'Publi24',
        'opt208' => 'WooPlus',
        'opt209' => 'BANDUS',
        'opt211' => 'MrGreen',
        'opt212' => 'OurTime',
        'opt213' => 'Waitomo',
        'opt214' => 'Cashrewards',
        'opt215' => 'Fbet',
        'opt216' => 'Hey',
        'opt217' => 'Brevo',
        'opt218' => 'TransferGo',
        'opt219' => 'maxline.by',
        'opt220' => 'TOTOGAMING',
        'opt221' => 'Fortuna',
        'opt222' => 'LASVEGAS.RO',
        'opt223' => 'Betmgm',
        'opt224' => '22bet',
        'opt225' => 'Zasilkovna',
        'opt226' => 'Cash App',
        'opt227' => 'Walmart',
        'opt228' => 'OKX',
        'opt229' => 'GGPokerUK',
        'opt230' => 'OkCupid',
        'opt231' => 'Whatnot',
        'opt232' => 'DistroKid',
        'opt233' => 'TrueCaller',
        'opt234' => 'Solitaire',
        'opt235' => 'TLScontact',
        'opt236' => 'Year13',
        'opt237' => 'Bitpanda',
        'opt238' => 'hepsiburada',
        'opt239' => 'Taptap',
        'opt240' => 'goldbet.it',
        'opt241' => 'onet.pl (Onet Konto)',
        'opt242' => 'Abbott',
        'opt243' => 'IQOS',
        'opt244' => 'Truth Social',
        'opt245' => 'Linode',
        'opt246' => 'Outlier',
        'opt247' => 'RadQuest',
        'opt248' => 'ESX (abonamentesali.ro)',
        'opt249' => 'Superbet',
        'opt250' => 'Match',
        'opt251' => '1cupis.ru',
        'opt252' => 'Best Buy',
        'opt253' => 'Zoosk',
        'opt254' => 'Monster Energy',
        'opt255' => 'Casa Pariurilor',
        'opt256' => 'Astropay',
        'opt257' => 'Remitly',
        'opt258' => 'SumUp',
        'opt259' => 'Google Messenger',
        'opt260' => 'Parions Sport',
        'opt261' => 'Welo Data',
        'opt262' => 'BC GAME',
        'opt263' => 'Profee.com',
        'opt264' => 'Toloka.ai',
        'opt265' => 'Reddit',
        'opt266' => 'Capital One Shopping',
        'opt267' => 'Caliente',
        'opt268' => 'Pokemon Center Online',
        'opt269' => 'Neosurf',
        'opt270' => 'Skelbiu',
        'opt271' => 'Google Chat',
        'opt420' => 'Grailed',
    ];
}