<?php
//Developer: core tech web design
//Whatsapp: +234 9162671360
//Telegram: @jeditech

error_reporting(0); // prevent PHP warnings from corrupting JSON output
ob_start();
require_once dirname(__DIR__) . '/include/config.php';
require_once dirname(__DIR__) . '/include/SmsBus.php';

ob_clean();
header('Content-Type: application/json; charset=utf-8');

// Auth: load user from session
if (!isset($_SESSION['logged_in']) || $_SESSION['logged_in'] !== true || empty($_SESSION['user_id'])) {
    echo json_encode(['status' => '0', 'msg' => 'Not authenticated.']); exit();
}
$user = null;
try {
    $stmt = $pdo->prepare("SELECT id, main_balance FROM users WHERE id = :uid AND status = '1' LIMIT 1");
    $stmt->execute([':uid' => (int)$_SESSION['user_id']]);
    $user = $stmt->fetch(PDO::FETCH_ASSOC);
} catch (PDOException $e) {}
if (!$user || empty($user['id'])) {
    echo json_encode(['status' => '0', 'msg' => 'Not authenticated.']); exit();
}

$user_id = (int)$user['id'];
$action  = trim($_POST['action'] ?? $_GET['action'] ?? '');

// Load SMS-Bus credentials fresh from settings
$token    = '';
$base_url = 'https://sms-bus.com/api/control';
$markup   = 35.0;
try {
    $sb = $pdo->query("SELECT smsbus_api_token, smsbus_api_url, smsbus_markup FROM settings WHERE id=1")->fetch(PDO::FETCH_ASSOC);
    if ($sb) {
        $token    = trim($sb['smsbus_api_token'] ?? '');
        $base_url = !empty($sb['smsbus_api_url']) ? $sb['smsbus_api_url'] : 'https://sms-bus.com/api/control';
        $markup   = (float)($sb['smsbus_markup'] ?? 35);
    }
} catch (PDOException $e) {}

// Live USD→NGN exchange rate
$usd_ngn = 1600.0;
try {
    $r2 = $pdo->query("SELECT setting_value FROM price_settings WHERE setting_key='usd_to_ngn' LIMIT 1")->fetch(PDO::FETCH_ASSOC);
    if ($r2 && (float)$r2['setting_value'] > 0) $usd_ngn = (float)$r2['setting_value'];
} catch (Exception $e) {}

if (empty($token)) {
    echo json_encode(['status' => '0', 'msg' => 'Service temporarily unavailable. Please try again later.']); exit();
}

$api = new SmsBus($token, $base_url);

// ────────────────────────────────────────────────────────────────
// get_countries — load all synced countries
// ────────────────────────────────────────────────────────────────
if ($action === 'get_countries') {
    try {
        $rows = $pdo->query(
            "SELECT id, title, code FROM smsbus_countries ORDER BY title ASC"
        )->fetchAll(PDO::FETCH_ASSOC);
        echo json_encode(['status' => '1', 'countries' => $rows]);
    } catch (PDOException $e) {
        echo json_encode(['status' => '0', 'msg' => 'Database error: ' . $e->getMessage()]);
    }
    exit();
}

// ────────────────────────────────────────────────────────────────
// get_country_projects — services+prices for a chosen country
// ────────────────────────────────────────────────────────────────
if ($action === 'get_country_projects') {
    $country_id = (int)($_POST['country_id'] ?? 0);
    if ($country_id <= 0) {
        echo json_encode(['status' => '0', 'msg' => 'Missing country.']); exit();
    }

    try {
        $rows = $pdo->prepare(
            "SELECT project_id, project_title, project_code, cost_usd, our_price, total_count
               FROM smsbus_prices
              WHERE country_id = :cid AND total_count > 0
              ORDER BY project_title ASC"
        );
        $rows->execute(['cid' => $country_id]);
        $cached = $rows->fetchAll(PDO::FETCH_ASSOC);

        if (!empty($cached)) {
            $projects = [];
            foreach ($cached as $row) {
                // Recalculate our_price with live exchange rate
                $our_price = round((float)$row['cost_usd'] * $usd_ngn * (1 + $markup / 100), 2);
                $projects[(int)$row['project_id']] = [
                    'project_id'    => (int)$row['project_id'],
                    'title'         => $row['project_title'],
                    'code'          => $row['project_code'],
                    'cost_usd'      => (float)$row['cost_usd'],
                    'our_price'     => $our_price,
                    'total_count'   => (int)$row['total_count'],
                ];
            }
            echo json_encode(['status' => '1', 'projects' => $projects, 'source' => 'cache']);
            exit();
        }
    } catch (PDOException $e) {}

    // Live API fallback
    $r = $api->getPrices($country_id);
    if (!$r['success']) {
        echo json_encode(['status' => '0', 'msg' => 'Could not load services. Please try again.']); exit();
    }

    // Get project titles from DB
    $projects_map = [];
    try {
        $proj_rows = $pdo->query("SELECT id, title, code FROM smsbus_projects")->fetchAll(PDO::FETCH_ASSOC);
        foreach ($proj_rows as $p) $projects_map[(int)$p['id']] = $p;
    } catch (PDOException $e) {}

    $projects = [];
    if (is_array($r['data'])) {
        foreach ($r['data'] as $item) {
            if (!is_array($item)) continue;
            $pid      = (int)($item['project_id'] ?? 0);
            $cost_usd = (float)($item['cost']       ?? 0);
            $cnt      = (int)($item['total_count']  ?? 0);
            if ($pid <= 0 || $cost_usd <= 0 || $cnt <= 0) continue;

            $p_info    = $projects_map[$pid] ?? null;
            $p_title   = $p_info ? $p_info['title'] : 'Project ' . $pid;
            $p_code    = $p_info ? $p_info['code']  : '';
            $our_price = round($cost_usd * $usd_ngn * (1 + $markup / 100), 2);

            $projects[$pid] = [
                'project_id'  => $pid,
                'title'       => $p_title,
                'code'        => $p_code,
                'cost_usd'    => $cost_usd,
                'our_price'   => $our_price,
                'total_count' => $cnt,
            ];
        }
    }

    echo json_encode(['status' => '1', 'projects' => $projects, 'source' => 'live']);
    exit();
}

// ────────────────────────────────────────────────────────────────
// buy_number — verify price, deduct balance, get number
// ────────────────────────────────────────────────────────────────
if ($action === 'buy_number') {
    $country_id = (int)($_POST['country_id'] ?? 0);
    $project_id = (int)($_POST['project_id'] ?? 0);

    if ($country_id <= 0 || $project_id <= 0) {
        echo json_encode(['status' => '0', 'msg' => 'Invalid parameters.']); exit();
    }

    // Verify price server-side via live API
    $r_price = $api->getPrices($country_id);
    if (!$r_price['success'] || !is_array($r_price['data'])) {
        echo json_encode(['status' => '0', 'msg' => 'Could not verify price. Try again.']); exit();
    }

    $price_item = null;
    foreach ($r_price['data'] as $item) {
        if (is_array($item) && (int)($item['project_id'] ?? 0) === $project_id) {
            $price_item = $item;
            break;
        }
    }

    if (!$price_item) {
        echo json_encode(['status' => '0', 'msg' => 'Service not available in this country right now.']); exit();
    }

    $cost_usd   = (float)($price_item['cost']        ?? 0);
    $cnt        = (int)($price_item['total_count']   ?? 0);
    if ($cost_usd <= 0 || $cnt <= 0) {
        echo json_encode(['status' => '0', 'msg' => 'Service not available in this country right now.']); exit();
    }

    $our_price = round($cost_usd * $usd_ngn * (1 + $markup / 100), 2);

    // Check user balance
    $u = $pdo->prepare("SELECT main_balance FROM users WHERE id = :id");
    $u->execute(['id' => $user_id]);
    $balance = (float)$u->fetchColumn();

    if ($balance < $our_price) {
        echo json_encode(['status' => '0', 'msg' => 'Insufficient balance. Please fund your wallet.']); exit();
    }

    // Get display names
    $country_title = '';
    try {
        $cr = $pdo->prepare("SELECT title FROM smsbus_countries WHERE id = :id");
        $cr->execute(['id' => $country_id]);
        $country_title = $cr->fetchColumn() ?: '';
    } catch (PDOException $e) {}

    $project_title = '';
    try {
        $pr = $pdo->prepare("SELECT title FROM smsbus_projects WHERE id = :id");
        $pr->execute(['id' => $project_id]);
        $project_title = $pr->fetchColumn() ?: 'Project ' . $project_id;
    } catch (PDOException $e) {}

    // Call SMS-Bus to get a number
    $result = $api->getNumber($country_id, $project_id);
    if (!$result['success']) {
        echo json_encode(['status' => '0', 'msg' => 'Unable to get number. Please try again.']); exit();
    }

    $data       = $result['data'];
    $request_id = (string)($data['request_id'] ?? '');
    $phone      = (string)($data['number']     ?? '');
    $expires_at = date('Y-m-d H:i:s', strtotime('+5 minutes'));

    if (empty($request_id) || !$phone) {
        echo json_encode(['status' => '0', 'msg' => 'Invalid response from server. Please try again.']); exit();
    }

    // Ensure orders table exists
    try {
        $pdo->exec("CREATE TABLE IF NOT EXISTS smsbus_orders (
            id            INT AUTO_INCREMENT PRIMARY KEY,
            user_id       INT           NOT NULL,
            request_id    VARCHAR(64)   NOT NULL UNIQUE,
            phone         VARCHAR(30)   NOT NULL,
            country_id    INT           NOT NULL,
            country_title VARCHAR(150)  NOT NULL DEFAULT '',
            project_id    INT           NOT NULL,
            project_title VARCHAR(150)  NOT NULL DEFAULT '',
            cost_usd      FLOAT         NOT NULL DEFAULT 0,
            our_price     DECIMAL(12,2) NOT NULL DEFAULT 0,
            status        VARCHAR(30)   NOT NULL DEFAULT 'waiting',
            sms_code      VARCHAR(100)  NOT NULL DEFAULT '',
            expires_at    DATETIME,
            received_at   DATETIME,
            created_at    TIMESTAMP     NOT NULL DEFAULT CURRENT_TIMESTAMP
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
    } catch (PDOException $e) {}

    // Migrate request_id column to VARCHAR if it's still INT
    try {
        $pdo->exec("ALTER TABLE smsbus_orders MODIFY COLUMN request_id VARCHAR(64) NOT NULL");
    } catch (PDOException $e) {}

    try {
        $pdo->beginTransaction();

        $upd = $pdo->prepare(
            "UPDATE users SET main_balance = main_balance - :amt WHERE id = :id AND main_balance >= :amt2"
        );
        $upd->execute(['amt' => $our_price, 'id' => $user_id, 'amt2' => $our_price]);

        if ($upd->rowCount() === 0) {
            $pdo->rollBack();
            echo json_encode(['status' => '0', 'msg' => 'Balance changed. Please retry.']); exit();
        }

        $ins = $pdo->prepare(
            "INSERT INTO smsbus_orders
             (user_id, request_id, phone, country_id, country_title, project_id, project_title, cost_usd, our_price, status, expires_at)
             VALUES (:uid,:rid,:phone,:cid,:ctitle,:pid,:ptitle,:cusd,:oprice,'waiting',:exp)"
        );
        $ins->execute([
            'uid'    => $user_id,
            'rid'    => $request_id,
            'phone'  => $phone,
            'cid'    => $country_id,
            'ctitle' => $country_title,
            'pid'    => $project_id,
            'ptitle' => $project_title,
            'cusd'   => $cost_usd,
            'oprice' => $our_price,
            'exp'    => $expires_at,
        ]);
        $local_order_id = (int)$pdo->lastInsertId();

        $txn_ref_sb = 'SB_' . strtoupper(substr(md5(uniqid()), 0, 12));
        $pdo->prepare(
            "INSERT INTO transactions (user_id, transaction_ref, payment_gateway, transaction_type, amount, currency, status, metadata)
             VALUES (:uid, :ref, 'virtual_number', 'number_purchase', :amt, 'NGN', 'successful', :meta)"
        )->execute([
            'uid'  => $user_id,
            'ref'  => $txn_ref_sb,
            'amt'  => $our_price,
            'meta' => json_encode(['project' => $project_title, 'country' => $country_title, 'phone' => $phone, 'request_id' => $request_id]),
        ]);

        $pdo->commit();

        echo json_encode([
            'status'      => '1',
            'msg'         => 'Number purchased!',
            'order_id'    => $local_order_id,
            'request_id'  => $request_id,
            'phone'       => $phone,
            'expires_at'  => $expires_at,
            'new_balance' => number_format($balance - $our_price, 2),
        ]);

    } catch (Exception $e) {
        $pdo->rollBack();
        // Try to cancel at SMS-Bus so user isn't double-charged
        $api->cancel($request_id);
        echo json_encode(['status' => '0', 'msg' => 'Something went wrong. Your balance was not charged.']);
    }
    exit();
}

// ────────────────────────────────────────────────────────────────
// check_sms — poll SMS-Bus for OTP
// ────────────────────────────────────────────────────────────────
if ($action === 'check_sms') {
    $order_id = (int)($_POST['order_id'] ?? 0);

    $ord = $pdo->prepare("SELECT * FROM smsbus_orders WHERE id=:id AND user_id=:uid");
    $ord->execute(['id' => $order_id, 'uid' => $user_id]);
    $row = $ord->fetch(PDO::FETCH_ASSOC);

    if (!$row) {
        echo json_encode(['status' => '0', 'msg' => 'Order not found.']); exit();
    }
    if ($row['status'] === 'received') {
        echo json_encode(['status' => '1', 'sms_code' => $row['sms_code']]); exit();
    }
    if (in_array($row['status'], ['cancelled', 'timeout'], true)) {
        echo json_encode(['status' => '0', 'msg' => 'Order was ' . $row['status'] . '.']); exit();
    }
    if (!empty($row['expires_at']) && strtotime($row['expires_at']) < time()) {
        $pdo->prepare("UPDATE smsbus_orders SET status='timeout' WHERE id=:id")->execute(['id' => $order_id]);
        // Auto-refund on local expiry
        $pdo->prepare("UPDATE users SET main_balance = main_balance + :amt WHERE id=:uid")->execute(['amt' => $row['our_price'], 'uid' => $user_id]);
        $ref = 'SBAUTO_' . strtoupper(substr(md5(uniqid()), 0, 8));
        $pdo->prepare("INSERT INTO transactions (user_id, transaction_ref, payment_gateway, transaction_type, amount, currency, status, metadata) VALUES (:uid,:ref,'virtual_number','refund',:amt,'NGN','successful',:meta)")
            ->execute(['uid' => $user_id, 'ref' => $ref, 'amt' => $row['our_price'], 'meta' => json_encode(['reason' => 'Auto-refund: number expired', 'request_id' => $row['request_id']])]);
        $nb = $pdo->prepare("SELECT main_balance FROM users WHERE id=:uid"); $nb->execute(['uid' => $user_id]);
        echo json_encode(['status' => '0', 'msg' => 'Number expired. ₦' . number_format($row['our_price'], 2) . ' refunded to your wallet.', 'refunded' => true, 'new_balance' => number_format((float)$nb->fetchColumn(), 2)]); exit();
    }

    $r = $api->getSms($row['request_id']);

    // code 50101 = still waiting
    if ($r['code'] === 50101) {
        echo json_encode(['status' => 'waiting', 'msg' => 'Waiting for SMS...']); exit();
    }
    // code 50102 = expired/timeout — auto-refund
    if ($r['code'] === 50102) {
        $pdo->prepare("UPDATE smsbus_orders SET status='timeout' WHERE id=:id")->execute(['id' => $order_id]);
        $pdo->prepare("UPDATE users SET main_balance = main_balance + :amt WHERE id=:uid")->execute(['amt' => $row['our_price'], 'uid' => $user_id]);
        $ref = 'SBAUTO_' . strtoupper(substr(md5(uniqid()), 0, 8));
        $pdo->prepare("INSERT INTO transactions (user_id, transaction_ref, payment_gateway, transaction_type, amount, currency, status, metadata) VALUES (:uid,:ref,'virtual_number','refund',:amt,'NGN','successful',:meta)")
            ->execute(['uid' => $user_id, 'ref' => $ref, 'amt' => $row['our_price'], 'meta' => json_encode(['reason' => 'Auto-refund: number timeout', 'request_id' => $row['request_id']])]);
        $nb = $pdo->prepare("SELECT main_balance FROM users WHERE id=:uid"); $nb->execute(['uid' => $user_id]);
        echo json_encode(['status' => '0', 'msg' => 'Number expired. ₦' . number_format($row['our_price'], 2) . ' refunded to your wallet.', 'refunded' => true, 'new_balance' => number_format((float)$nb->fetchColumn(), 2)]); exit();
    }

    if ($r['success'] && $r['data'] !== null) {
        $sms_code = (string)$r['data'];

        $pdo->prepare(
            "UPDATE smsbus_orders SET status='received', sms_code=:code, received_at=NOW() WHERE id=:id"
        )->execute(['code' => $sms_code, 'id' => $order_id]);

        echo json_encode(['status' => '1', 'sms_code' => $sms_code]);

    } elseif (!$r['success']) {
        echo json_encode(['status' => '0', 'msg' => $r['error'] ?? 'Unknown error.']);
    } else {
        echo json_encode(['status' => 'waiting', 'msg' => 'Waiting for SMS...']);
    }
    exit();
}

// ────────────────────────────────────────────────────────────────
// cancel_number — cancel + refund
// ────────────────────────────────────────────────────────────────
if ($action === 'cancel_number') {
    $order_id = (int)($_POST['order_id'] ?? 0);

    $ord = $pdo->prepare("SELECT * FROM smsbus_orders WHERE id=:id AND user_id=:uid");
    $ord->execute(['id' => $order_id, 'uid' => $user_id]);
    $row = $ord->fetch(PDO::FETCH_ASSOC);

    if (!$row) {
        echo json_encode(['status' => '0', 'msg' => 'Order not found.']); exit();
    }
    if ($row['status'] !== 'waiting') {
        echo json_encode(['status' => '0', 'msg' => 'Can only cancel numbers still waiting for SMS.']); exit();
    }

    $r = $api->cancel($row['request_id']);

    // Always refund regardless of API response (order may already be closed at SMS-Bus)
    $pdo->prepare("UPDATE users SET main_balance = main_balance + :amt WHERE id=:uid")
        ->execute(['amt' => $row['our_price'], 'uid' => $user_id]);
    $pdo->prepare("UPDATE smsbus_orders SET status='cancelled' WHERE id=:id")
        ->execute(['id' => $order_id]);
    $refund_ref_sb = 'SBREF_' . strtoupper(substr(md5(uniqid()), 0, 10));
    $pdo->prepare("INSERT INTO transactions (user_id, transaction_ref, payment_gateway, transaction_type, amount, currency, status, metadata) VALUES (:uid,:ref,'virtual_number','refund',:amt,'NGN','successful',:meta)")
        ->execute(['uid' => $user_id, 'ref' => $refund_ref_sb, 'amt' => $row['our_price'], 'meta' => json_encode(['reason' => 'Number cancelled', 'request_id' => $row['request_id']])]);

    $nb = $pdo->prepare("SELECT main_balance FROM users WHERE id=:uid");
    $nb->execute(['uid' => $user_id]);
    echo json_encode([
        'status'      => '1',
        'msg'         => '&#8358;' . number_format($row['our_price'], 2) . ' refunded to your wallet.',
        'new_balance' => number_format((float)$nb->fetchColumn(), 2),
    ]);
    exit();
}

// ────────────────────────────────────────────────────────────────
// get_active_orders — waiting/received orders on page load
// ────────────────────────────────────────────────────────────────
if ($action === 'get_active_orders') {
    try {
        $rows = $pdo->prepare(
            "SELECT * FROM smsbus_orders WHERE user_id=:uid AND status = 'waiting' ORDER BY created_at DESC"
        );
        $rows->execute(['uid' => $user_id]);
        echo json_encode(['status' => '1', 'orders' => $rows->fetchAll(PDO::FETCH_ASSOC)]);
    } catch (PDOException $e) {
        echo json_encode(['status' => '1', 'orders' => []]);
    }
    exit();
}

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