<?php
//Developer: CORE TECH WEB DESIGN
ob_start(); // Buffer output so PHP notices don't corrupt JSON
if (!defined('VALID_ACCESS')) define('VALID_ACCESS', true);
require_once dirname(__DIR__) . '/include/config.php';
require_once dirname(__DIR__) . '/include/SMSMan.php';

ob_clean(); // Discard any notices output during includes
header('Content-Type: application/json; charset=utf-8');

if (!isset($user) || empty($user['id'])) {
    echo json_encode(['status' => '0', 'msg' => 'Not authenticated.']); exit();
}

$user_id  = (int)$user['id'];
$action   = trim($_POST['action'] ?? $_GET['action'] ?? '');
$token    = $site_data['smsman_api_token'] ?? '';
$base_url = $site_data['smsman_api_url']   ?? 'https://api.sms-man.com/control';
$markup   = (float)($site_data['smsman_markup'] ?? 30);
$usd_ngn  = (float)($site_data['usd_to_ngn']   ?? 1600);

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

$smsman = new SMSMan($token, $base_url);

// ── get_services: load countries + apps + prices for a country ─
if ($action === 'get_services') {
    $country_id = (int)($_GET['country_id'] ?? 0);

    $countries = $pdo->query("SELECT id AS country_id, title FROM smsman_countries ORDER BY title ASC")->fetchAll(PDO::FETCH_ASSOC);
    $apps      = $pdo->query("SELECT id AS application_id, name, code FROM smsman_applications ORDER BY name ASC")->fetchAll(PDO::FETCH_ASSOC);

    $limits = [];
    $prices = [];
    if ($country_id > 0) {
        $lim_r = $smsman->getLimits($country_id);
        if ($lim_r['success'] && is_array($lim_r['data'])) {
            foreach ($lim_r['data'] as $l) {
                $limits[(int)$l['application_id']] = (int)$l['numbers'];
            }
        }
        $prc_r = $smsman->getPrices($country_id);
        if ($prc_r['success'] && is_array($prc_r['data'])) {
            foreach ($prc_r['data'] as $cid => $apps_arr) {
                if (is_array($apps_arr)) {
                    foreach ($apps_arr as $aid => $info) {
                        $prices[(int)$aid] = (float)($info['cost'] ?? 0);
                    }
                }
            }
        }
    }

    echo json_encode([
        'status'    => '1',
        'countries' => $countries,
        'apps'      => $apps,
        'limits'    => $limits,
        'prices'    => $prices,
        'usd_ngn'   => $usd_ngn,
        'markup'    => $markup,
    ]);
    exit();
}

// ── get_country_services: load services for a country from smsman_prices ──
// Queries the pre-synced smsman_prices table — instant, no live API call needed
if ($action === 'get_country_services') {
    $country_id = (int)$_POST['country_id'];
    if (!$country_id) {
        echo json_encode(['status' => '0', 'msg' => 'Missing country.']); exit();
    }

    try {
        $rows = $pdo->prepare("SELECT application_id, app_name, app_code, cost_usd, our_price, available
            FROM smsman_prices
            WHERE country_id = :cid AND available > 0 AND cost_usd > 0
            ORDER BY app_name ASC");
        $rows->execute(['cid' => $country_id]);
        $price_rows = $rows->fetchAll(PDO::FETCH_ASSOC);
    } catch (PDOException $e) {
        echo json_encode(['status' => '0', 'msg' => 'Prices not synced yet. Ask admin to run Sync Prices from Settings.']); exit();
    }

    if (empty($price_rows)) {
        echo json_encode(['status' => '0', 'msg' => 'No services available for this country. Ask admin to sync prices.']); exit();
    }

    $services = [];
    foreach ($price_rows as $p) {
        $services[(int)$p['application_id']] = [
            'name'      => $p['app_name'],
            'code'      => $p['app_code'],
            'cost_usd'  => (float)$p['cost_usd'],
            'our_price' => (float)$p['our_price'],
            'available' => (int)$p['available'],
        ];
    }

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


// ── get_price: kept for backward compat — now uses getLimits correctly ─
if ($action === 'get_price') {
    $country_id     = (int)$_POST['country_id'];
    $application_id = (int)$_POST['application_id'];

    if (!$country_id || !$application_id) {
        echo json_encode(['status' => '0', 'msg' => 'Missing country or service.']); exit();
    }

    $lim_r = $smsman->getLimits($country_id, $application_id);
    $cost_usd  = 0;
    $available = 0;

    if ($lim_r['success'] && is_array($lim_r['data'])) {
        // Flat object keyed by app_id: { "125": { "cost":"12.63","numbers":50674,... } }
        $item = $lim_r['data'][$application_id]
             ?? $lim_r['data'][(string)$application_id]
             ?? null;
        if ($item) {
            $cost_usd  = (float)($item['cost']    ?? 0);
            $available = (int)($item['numbers']   ?? 0);
        }
    }

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

    $our_price = round($cost_usd * $usd_ngn * (1 + $markup / 100), 2);
    echo json_encode([
        'status' => '1',
        'price'  => ['cost_usd'=>$cost_usd,'our_price'=>$our_price,'available'=>$available],
    ]);
    exit();
}

// ── buy_number: purchase a number and deduct balance ───────────
if ($action === 'buy_number') {
    $country_id     = (int)$_POST['country_id'];
    $application_id = (int)$_POST['application_id'];
    // Recalculate price server-side using getLimits (flat keyed by app_id)
    $lim_buy = $smsman->getLimits($country_id, $application_id);
    $cost_usd2 = 0;
    if ($lim_buy['success'] && is_array($lim_buy['data'])) {
        $item2 = $lim_buy['data'][$application_id]
              ?? $lim_buy['data'][(string)$application_id]
              ?? null;
        if ($item2) $cost_usd2 = (float)($item2['cost'] ?? 0);
    }
    if ($cost_usd2 <= 0) {
        echo json_encode(['status' => '0', 'msg' => 'Service not available in this country right now.']); exit();
    }
    $our_price = round($cost_usd2 * $usd_ngn * (1 + $markup / 100), 2);

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

    $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();
    }

    $cr = $pdo->prepare("SELECT title FROM smsman_countries WHERE id = :id");
    $cr->execute(['id' => $country_id]);
    $country_name = $cr->fetchColumn() ?: '';

    $ar = $pdo->prepare("SELECT name, code FROM smsman_applications WHERE id = :id");
    $ar->execute(['id' => $application_id]);
    $app_row  = $ar->fetch(PDO::FETCH_ASSOC);
    $app_name = $app_row['name'] ?? '';
    $app_code = $app_row['code'] ?? '';

    $result = $smsman->getNumber($country_id, $application_id);
    if (!$result['success']) {
        echo json_encode(['status' => '0', 'msg' => 'Unable to get number. Please try again.']); exit();
    }

    $data       = $result['data'];
    $request_id = (int)($data['request_id'] ?? 0);
    $number     = $data['number'] ?? '';

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

    // Ensure smsman_orders table exists
    try {
        $pdo->exec("CREATE TABLE IF NOT EXISTS smsman_orders (
            id              INT AUTO_INCREMENT PRIMARY KEY,
            user_id         INT           NOT NULL,
            request_id      INT           NOT NULL,
            number          VARCHAR(30)   NOT NULL,
            country_id      INT           NOT NULL,
            country_name    VARCHAR(150)  NOT NULL DEFAULT '',
            application_id  INT           NOT NULL,
            app_name        VARCHAR(150)  NOT NULL DEFAULT '',
            app_code        VARCHAR(50)   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 '',
            sms_full_msg    TEXT,
            expires_at      DATETIME,
            received_at     DATETIME,
            created_at      TIMESTAMP     NOT NULL DEFAULT CURRENT_TIMESTAMP
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
    } 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();
        }

        $expires = date('Y-m-d H:i:s', strtotime('+5 minutes'));

        $ins = $pdo->prepare("INSERT INTO smsman_orders
            (user_id, request_id, number, country_id, country_name, application_id, app_name, app_code, cost_usd, our_price, status, expires_at)
            VALUES (:uid,:rid,:num,:cid,:cname,:aid,:aname,:acode,:cusd,:price,'waiting',:exp)");
        $ins->execute([
            'uid'   => $user_id, 'rid'   => $request_id, 'num'   => $number,
            'cid'   => $country_id, 'cname' => $country_name,
            'aid'   => $application_id, 'aname' => $app_name, 'acode' => $app_code,
            'cusd'  => $cost_usd2, 'price' => $our_price, 'exp' => $expires,
        ]);
        $order_id = $pdo->lastInsertId();

        $txn_ref = 'SM_' . 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,
            'amt'  => $our_price,
            'meta' => json_encode(['service' => $app_name, 'country' => $country_name, 'number' => $number, 'request_id' => $request_id]),
        ]);

        $pdo->commit();

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

    } catch (Exception $e) {
        $pdo->rollBack();
        $smsman->setStatus($request_id, 'cancel');
        echo json_encode(['status' => '0', 'msg' => 'Something went wrong. Your balance was not charged.']);
    }
    exit();
}

// ── check_sms: poll for OTP ────────────────────────────────────
if ($action === 'check_sms') {
    $order_id = (int)$_POST['order_id'];

    $ord = $pdo->prepare("SELECT * FROM smsman_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'], 'sms_full_msg' => $row['sms_full_msg']]);
        exit();
    }
    if ($row['status'] === 'cancelled') { echo json_encode(['status' => '0', 'msg' => 'Number was cancelled.']); exit(); }
    if ($row['status'] === 'expired' || strtotime($row['expires_at']) < time()) {
        $pdo->prepare("UPDATE smsman_orders SET status='expired' WHERE id=:id")->execute(['id' => $order_id]);
        echo json_encode(['status' => '0', 'msg' => 'Number expired. 20-minute window passed.']); exit();
    }

    $r = $smsman->getSMS($row['request_id']);

    if ($r['success'] && !empty($r['data']['sms_code'])) {
        $pdo->prepare("UPDATE smsman_orders SET status='received', sms_code=:code, sms_full_msg=:msg, received_at=NOW() WHERE id=:id")
            ->execute(['code' => $r['data']['sms_code'], 'msg' => $r['data']['sms_full_msg'] ?? '', 'id' => $order_id]);
        echo json_encode(['status' => '1', 'sms_code' => $r['data']['sms_code'], 'sms_full_msg' => $r['data']['sms_full_msg'] ?? '']);
    } else {
        echo json_encode(['status' => 'waiting', 'msg' => 'Still waiting for SMS...']);
    }
    exit();
}

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

    $ord = $pdo->prepare("SELECT * FROM smsman_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 waiting for SMS.']); exit(); }

    $r = $smsman->setStatus($row['request_id'], 'cancel');
    if ($r['success']) {
        $pdo->prepare("UPDATE users SET main_balance = main_balance + :amt WHERE id=:uid")->execute(['amt' => $row['our_price'], 'uid' => $user_id]);
        $pdo->prepare("UPDATE smsman_orders SET status='cancelled' WHERE id=:id")->execute(['id' => $order_id]);
        $refund_ref = 'SMREF_' . 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,
            'amt'  => $row['our_price'],
            'meta' => json_encode(['reason' => 'Virtual number cancelled', 'request_id' => $row['request_id']]),
        ]);
        $new_bal = $pdo->prepare("SELECT main_balance FROM users WHERE id=:uid");
        $new_bal->execute(['uid' => $user_id]);
        $nb = number_format((float)$new_bal->fetchColumn(), 2);
        echo json_encode(['status' => '1', 'msg' => '&#8358;' . number_format($row['our_price'], 2) . ' refunded to your wallet.', 'new_balance' => $nb]);
    } else {
        echo json_encode(['status' => '0', 'msg' => 'Cancel failed: ' . ($r['error_msg'] ?? 'Unknown')]);
    }
    exit();
}

// ── finish_number: mark complete, no refund ───────────────────
if ($action === 'finish_number') {
    $order_id = (int)$_POST['order_id'];

    $ord = $pdo->prepare("SELECT * FROM smsman_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(); }

    $smsman->setStatus($row['request_id'], 'finish');
    $pdo->prepare("UPDATE smsman_orders SET status='finished' WHERE id=:id")->execute(['id' => $order_id]);
    echo json_encode(['status' => '1', 'msg' => 'Number released. Thank you!']);
    exit();
}

// ── get_active_orders: waiting orders for this user on page load ──
if ($action === 'get_active_orders') {
    $rows = $pdo->prepare("SELECT * FROM smsman_orders WHERE user_id=:uid AND status = 'waiting' ORDER BY created_at DESC");
    $rows->execute(['uid' => $user_id]);
    $orders = $rows->fetchAll(PDO::FETCH_ASSOC);

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

// ── get_balance: return user's current main_balance ──────────
if ($action === 'get_balance') {
    $b = $pdo->prepare("SELECT main_balance FROM users WHERE id=:uid");
    $b->execute(['uid' => $user_id]);
    $bal = (float)$b->fetchColumn();
    echo json_encode(['status' => '1', 'balance' => number_format($bal, 2, '.', '')]);
    exit();
}

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