<?php
/**
 * Shared secure helpers for sold credential admin APIs.
 * These endpoints intentionally do not trust client supplied user_id.
 */
require_once 'config.php';
require_once '_vpn_helpers.php';
header('Content-Type: application/json; charset=utf-8');

function sold_json_ok(array $data = [], string $message = 'OK'): void {
    echo json_encode(['ok' => true, 'message' => $message, 'data' => $data], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

function sold_json_error(string $message, int $http = 200, array $extra = []): void {
    http_response_code($http);
    echo json_encode(array_merge(['ok' => false, 'error' => $message], $extra), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

function sold_read_input(): array {
    $raw = file_get_contents('php://input');
    $json = json_decode($raw ?: '', true);
    if (is_array($json)) return $json;
    return $_POST ?: $_REQUEST;
}

function sold_get_init_data(array $input = []): string {
    return (string)($_SERVER['HTTP_X_TELEGRAM_INIT_DATA'] ?? $input['initData'] ?? $_GET['initData'] ?? $_POST['initData'] ?? '');
}

function sold_verify_init_data(string $initData): array {
    if ($initData === '') sold_json_error('Missing Telegram initData', 401);
    parse_str($initData, $data);
    if (empty($data['hash'])) sold_json_error('Invalid Telegram initData', 401);

    $receivedHash = (string)$data['hash'];
    unset($data['hash']);
    ksort($data);
    $pairs = [];
    foreach ($data as $k => $v) $pairs[] = $k . '=' . $v;
    $checkString = implode("\n", $pairs);

    if (!defined('BOT_TOKEN') || BOT_TOKEN === '') sold_json_error('BOT_TOKEN is not configured', 500);
    $secretKey = hash_hmac('sha256', BOT_TOKEN, 'WebAppData', true);
    $calculatedHash = hash_hmac('sha256', $checkString, $secretKey);
    if (!hash_equals($calculatedHash, $receivedHash)) sold_json_error('Invalid Telegram initData hash', 401);

    $authDate = isset($data['auth_date']) ? (int)$data['auth_date'] : 0;
    if ($authDate <= 0 || time() - $authDate > 86400) sold_json_error('Expired Telegram initData', 401);

    $user = json_decode((string)($data['user'] ?? ''), true);
    if (!is_array($user) || empty($user['id'])) sold_json_error('Invalid Telegram user data', 401);
    return $user;
}

function sold_require_admin(array $input = []): int {
    $tgUser = sold_verify_init_data(sold_get_init_data($input));
    $adminId = (int)$tgUser['id'];
    if (!isAdmin($adminId)) sold_json_error('Admin access required', 403);
    return $adminId;
}

function sold_column_exists(PDO $pdo, string $table, string $column): bool {
    try {
        $st = $pdo->prepare("SHOW COLUMNS FROM `$table` LIKE ?");
        $st->execute([$column]);
        return (bool)$st->fetch();
    } catch (Throwable $e) { return false; }
}

function sold_admin_log(PDO $pdo, int $adminId, string $action, array $context = []): void {
    $payload = json_encode($context, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    try {
        $st = $pdo->prepare("INSERT INTO admin_logs (admin_user_id, action, target_type, target_id, old_value, new_value, ip_address, created_at) VALUES (?,?,?,?,?,?,?,NOW())");
        $st->execute([
            $adminId,
            $action,
            (string)($context['target_type'] ?? 'sold_credential'),
            isset($context['target_id']) ? (string)$context['target_id'] : null,
            isset($context['old']) ? json_encode($context['old'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) : null,
            isset($context['new']) ? json_encode($context['new'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) : $payload,
            $_SERVER['REMOTE_ADDR'] ?? null,
        ]);
    } catch (Throwable $e) {
        vpnLogEvent('admin_log_fallback', ['admin_id' => $adminId, 'action' => $action, 'context' => $context, 'error' => $e->getMessage()]);
    }
}

function sold_find_delivery_for_update(PDO $pdo, int $deliveryId, int $credentialId = 0): ?array {
    if ($deliveryId > 0) {
        $st = $pdo->prepare("SELECT d.*, o.status AS order_status, o.delivery_status AS order_delivery_status, c.status AS credential_status, c.is_sold, c.used_seats FROM deliveries d LEFT JOIN orders o ON o.id=d.order_id LEFT JOIN credentials c ON c.id=d.credential_id WHERE d.id=? FOR UPDATE");
        $st->execute([$deliveryId]);
        $row = $st->fetch(PDO::FETCH_ASSOC);
        return $row ?: null;
    }
    if ($credentialId > 0) {
        $st = $pdo->prepare("SELECT d.*, o.status AS order_status, o.delivery_status AS order_delivery_status, c.status AS credential_status, c.is_sold, c.used_seats FROM deliveries d LEFT JOIN orders o ON o.id=d.order_id LEFT JOIN credentials c ON c.id=d.credential_id WHERE d.credential_id=? ORDER BY d.id DESC LIMIT 1 FOR UPDATE");
        $st->execute([$credentialId]);
        $row = $st->fetch(PDO::FETCH_ASSOC);
        return $row ?: null;
    }
    return null;
}

function sold_refresh_order_after_delivery_change(PDO $pdo, int $orderId, string $finalStatusWhenEmpty): void {
    $st = $pdo->prepare("SELECT COUNT(*) FROM deliveries WHERE order_id=? AND status='delivered'");
    $st->execute([$orderId]);
    $active = (int)$st->fetchColumn();
    if ($active > 0) {
        $pdo->prepare("UPDATE orders SET delivered_accounts=?, delivery_status='partial', status=IF(status IN ('CANCELLED','REVERTED'), status, 'DELIVERED'), updated_at=NOW() WHERE id=?")->execute([$active, $orderId]);
    } else {
        $deliveryStatus = strtolower($finalStatusWhenEmpty);
        $pdo->prepare("UPDATE orders SET delivered_accounts=0, delivery_status=?, status=?, updated_at=NOW() WHERE id=?")->execute([$deliveryStatus, strtoupper($finalStatusWhenEmpty), $orderId]);
    }
}

function sold_clean_text($value): string {
    return trim((string)$value);
}
