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

// Prevent direct browser access to this helper file.
if (!defined('VALID_ACCESS') || VALID_ACCESS !== true) {
    http_response_code(403);
    exit('Direct access not allowed.');
}

/**
 * Validate a login token and return the user_id.
 */
function otp_check_token(string $token, PDO $pdo)
{
    try {
        $stmt = $pdo->prepare(
            "SELECT lt.user_id
               FROM login_token lt
               JOIN users u ON u.id = lt.user_id
              WHERE lt.token  = :token
                AND lt.status = '1'
                AND u.status  = '1'
              LIMIT 1"
        );
        $stmt->execute([':token' => $token]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        return $row ? (string)$row['user_id'] : false;
    } catch (PDOException $e) {
        return false;
    }
}

/**
 * Verify a user_id from session.
 */
function otp_verify_user(string $user_id_param, PDO $pdo)
{
    if (!is_numeric($user_id_param) || (int)$user_id_param <= 0) return false;
    try {
        $stmt = $pdo->prepare("SELECT id FROM users WHERE id = :uid AND status = '1' LIMIT 1");
        $stmt->execute([':uid' => (int)$user_id_param]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        return $row ? (string)$row['id'] : false;
    } catch (PDOException $e) {
        return false;
    }
}

/**
 * Apply custom price rule for a user/service/server.
 */
function otp_custom_price(string $user_id, string $service_id, string $server_id, float $base_price, PDO $pdo): float
{
    try {
        $stmt = $pdo->prepare(
            "SELECT type, discount FROM custom_price
              WHERE user_id = :uid AND service_id = :sid AND server_id = :svid
              LIMIT 1"
        );
        $stmt->execute([':uid' => $user_id, ':sid' => $service_id, ':svid' => $server_id]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        if (!$row) return $base_price;
        if ($row['type'] === 'flat') return (float)$row['discount'];
        if ($row['type'] === 'percent') return round($base_price - (((float)$row['discount'] / 100) * $base_price), 4);
        return $base_price;
    } catch (PDOException $e) {
        return $base_price;
    }
}

/**
 * cURL GET with smscodes.io-friendly defaults.
 */
function otp_curl_get(string $url, int $timeout = 60): string
{
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => $timeout,
        CURLOPT_CONNECTTIMEOUT => 15,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => 0,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_USERAGENT      => 'Mozilla/5.0 (compatible; Bot/1.0)',
        CURLOPT_ENCODING       => '',
    ]);
    $response = curl_exec($ch);
    $err      = curl_error($ch);
    curl_close($ch);
    if ($response === false || $response === '') {
        return 'CURL_ERROR: ' . ($err ?: 'Empty response');
    }
    return (string)$response;
}

/**
 * Build a smscodes.io API URL.
 * Format: {base_url}/{Method}?key={api_key}&param=value
 */
function otp_build_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;
}

/**
 * Fetch otp_server row by ID.
 */
function otp_get_server(string $server_id, PDO $pdo)
{
    try {
        $stmt = $pdo->prepare("SELECT * FROM otp_server WHERE id = :id LIMIT 1");
        $stmt->execute([':id' => $server_id]);
        return $stmt->fetch(PDO::FETCH_ASSOC);
    } catch (PDOException $e) {
        return false;
    }
}

/**
 * Fetch api_detail row by ID.
 */
function otp_get_api(string $api_id, PDO $pdo)
{
    try {
        $stmt = $pdo->prepare("SELECT * FROM api_detail WHERE id = :id LIMIT 1");
        $stmt->execute([':id' => $api_id]);
        return $stmt->fetch(PDO::FETCH_ASSOC);
    } catch (PDOException $e) {
        return false;
    }
}

/**
 * Get the service logo URL.
 */
function otp_get_logo(string $service_id, PDO $pdo): string
{
    $default = 'https://i.ibb.co/ySRhxqh/default.png';

    // Try local icon table
    try {
        $stmt = $pdo->prepare("SELECT img_url FROM service_icon WHERE short_code = :code LIMIT 1");
        $stmt->execute([':code' => $service_id]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        if ($row && !empty($row['img_url'])) return $row['img_url'];
    } catch (PDOException $e) {}

    // Try service_logo from service table
    try {
        $stmt = $pdo->prepare("SELECT service_logo FROM service WHERE service_id = :sid LIMIT 1");
        $stmt->execute([':sid' => $service_id]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        if ($row && !empty($row['service_logo'])) {
            return 'https://dashboard.smscodes.io/assets/images/services/' . $row['service_logo'];
        }
    } catch (PDOException $e) {}

    return $default;
}

/**
 * Random alphanumeric string.
 */
function otp_random_string(int $length = 20): string
{
    $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $str   = '';
    $max   = strlen($chars) - 1;
    for ($i = 0; $i < $length; $i++) {
        $str .= $chars[random_int(0, $max)];
    }
    return $str;
}

/**
 * Send a JSON response and exit.
 */
function otp_json_response(array $data, int $http_code = 200): void
{
    http_response_code($http_code);
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode($data);
    exit;
}

// ══════════════════════════════════════════════════════════════════
// LIVE PRICING HELPERS (USD → NGN)
// ══════════════════════════════════════════════════════════════════

/**
 * Get the admin-set USD→NGN exchange rate from the database.
 *
 * IMPORTANT: This function only reads the rate set by the admin in the
 * Sync Services page. It never fetches a live rate or overwrites the
 * admin value. The rate can only be changed by the admin manually.
 */
function otp_get_usd_to_ngn(PDO $pdo): float
{
    try {
        $stmt = $pdo->prepare("SELECT setting_value FROM price_settings WHERE setting_key = 'usd_to_ngn' LIMIT 1");
        $stmt->execute();
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        if ($row && (float)$row['setting_value'] > 0) return (float)$row['setting_value'];
    } catch (PDOException $e) {}
    return 1600.0;
}

/**
 * Fetch admin markup percentage.
 */
function otp_get_markup(PDO $pdo): float
{
    try {
        $stmt = $pdo->prepare("SELECT setting_value FROM price_settings WHERE setting_key = 'markup_percent' LIMIT 1");
        $stmt->execute();
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        return ($row && is_numeric($row['setting_value'])) ? (float)$row['setting_value'] : 35.0;
    } catch (PDOException $e) { return 35.0; }
}

/**
 * Convert USD to NGN with markup.
 */
function otp_convert_price(float $usd_price, PDO $pdo): float
{
    $usd_to_ngn = otp_get_usd_to_ngn($pdo);
    $markup_pct = otp_get_markup($pdo);
    $naira_base = $usd_price * $usd_to_ngn;
    return round($naira_base * (1 + $markup_pct / 100), 2);
}

/**
 * Fetch live price for a service in a country using GetServicePrices (fast ~4s).
 */
function otp_fetch_live_price(string $api_key, string $api_url, string $country_iso, string $service_id)
{
    $url     = otp_build_url($api_url, 'GetServicePrices', $api_key, ['serviceId' => $service_id]);
    $raw     = otp_curl_get($url, 15);
    $decoded = json_decode($raw, true);
    if (is_array($decoded) && isset($decoded['Status'], $decoded['Prices']) && $decoded['Status'] === 'Success') {
        foreach ($decoded['Prices'] as $entry) {
            if (isset($entry['Iso'], $entry['Price']) && strtoupper($entry['Iso']) === strtoupper($country_iso)) {
                return (float)$entry['Price'];
            }
        }
    }
    return false;
}

/**
 * Validate that an SMS value is a real OTP/code and not a provider error string.
 * Rejects known non-code strings like "Message not received yet", "Waiting", etc.
 */
function otp_is_valid_sms(string $sms): bool
{
    if (empty($sms)) return false;

    // Reject known provider placeholder/error strings
    $invalid_strings = [
        'message not received yet',
        'waiting',
        'no sms',
        'not received',
        'error',
        'expired',
        'cancelled',
        'n/a',
    ];

    $lower = strtolower(trim($sms));
    foreach ($invalid_strings as $bad) {
        if (strpos($lower, $bad) !== false) return false;
    }

    // Must be at least 3 chars and no longer than 255
    if (strlen($sms) < 3 || strlen($sms) > 255) return false;

    return true;
}