<?php
// تنظیمات دیتابیس
define('DB_HOST', 'localhost');
define('DB_NAME', 'movihac1_xui');
define('DB_USER', 'movihac1_xui');
define('DB_PASS', 'ahmad2405');

// تنظیمات جلسه
define('SESSION_LIFETIME', 3600 * 24); // 24 ساعت

// تنظیمات امنیتی
define('SALT', 'your-secret-salt-change-this');

// مسیرهای پروژه
define('BASE_URL', 'http://localhost');
define('ROOT_PATH', __DIR__);

// ربات تلگرام استعلام وضعیت کانفیگ (خالی = غیرفعال)
define('TELEGRAM_BOT_TOKEN', '');

// برای دیدن متن خطا در داشبورد نماینده روی true بگذارید؛ بعد از رفع خطا حتماً false کنید
if (!defined('LIVE_USER_STATS')) define('LIVE_USER_STATS', true);
// The LIVE_USER_STATS setting was removed to resolve an API error.
if (!defined('DEBUG')) define('DEBUG', false);

// تنظیمات پیش‌فرض برای کاربران جدید
define('DEFAULT_PROTOCOL', 'vmess');
define('DEFAULT_FLOW', 'xtls-rprx-vision');

// کیف پول: مقادیر پیش‌فرض (در صورت نبود در جدول settings از این‌ها استفاده می‌شود)
define('WALLET_PRICE_PER_CONFIG', 1000);
define('WALLET_PRICE_PER_GB', 0);
define('WALLET_PRICE_PER_DAY', 0);

// اتصال به دیتابیس
try {
    $pdo = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=utf8mb4", DB_USER, DB_PASS);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
} catch(PDOException $e) {
    die("خطا در اتصال به دیتابیس: " . $e->getMessage());
}

// شروع جلسه
if (session_status() === PHP_SESSION_NONE) {
    session_start();
}

// تابع بررسی پسورد
function verifyPassword($password, $hash) {
    return password_verify($password . SALT, $hash);
}

// تابع بررسی لاگین
function isLoggedIn() {
    return isset($_SESSION['user_id']) && isset($_SESSION['user_type']);
}

// تابع بررسی نوع کاربر
function isAdmin() {
    return isLoggedIn() && $_SESSION['user_type'] === 'admin';
}

function isRepresentative() {
    return isLoggedIn() && $_SESSION['user_type'] === 'representative';
}

// تابع به‌روزرسانی آخرین فعالیت نماینده
function updateRepresentativeActivity($pdo, $representative_id) {
    try {
        // بررسی وجود فیلد last_activity
        $check = $pdo->query("SHOW COLUMNS FROM representatives LIKE 'last_activity'");
        if ($check->rowCount() > 0) {
            $stmt = $pdo->prepare("UPDATE representatives SET last_activity = NOW() WHERE id = ?");
            $stmt->execute([$representative_id]);
        }
    } catch (Exception $e) {
        // خطا را نادیده می‌گیریم تا صفحه لود شود
    }
}

// تابع ریدایرکت
function redirect($url) {
    // اگر header قبلاً ارسال شده باشد، از JavaScript استفاده می‌کنیم
    if (headers_sent()) {
        echo "<script>window.location.href = '" . htmlspecialchars($url) . "';</script>";
        exit;
    }
    header("Location: " . $url);
    exit;
}

// تابع نمایش پیام
function setMessage($message, $type = 'success') {
    $_SESSION['message'] = $message;
    $_SESSION['message_type'] = $type;
}

function getMessage() {
    if (isset($_SESSION['message'])) {
        $message = $_SESSION['message'];
        $type = $_SESSION['message_type'] ?? 'success';
        unset($_SESSION['message'], $_SESSION['message_type']);
        return ['message' => $message, 'type' => $type];
    }
    return null;
}

// تابع هش کردن رمز عبور
function hashPassword($password) {
    // همیشه از الگوریتم‌های قوی و به‌روز استفاده کنید
    // PASSWORD_DEFAULT به طور خودکار بهترین الگوریتم موجود را انتخاب می‌کند
    return password_hash($password, PASSWORD_DEFAULT);
}

/**
 * کسر از کیف پول نماینده (مثلاً برای ساخت کانفیگ)
 * @return true اگر موفق، در غیر این صورت Exception
 */
function walletDeduct($pdo, $representative_id, $amount, $type = 'create_user', $ref_id = null, $description = null) {
    $amount = abs((float)$amount);
    if ($amount <= 0) return true;
    $pdo->beginTransaction();
    try {
        $stmt = $pdo->prepare("SELECT wallet_balance FROM representatives WHERE id = ? FOR UPDATE");
        $stmt->execute([$representative_id]);
        $row = $stmt->fetch();
        if (!$row) {
            $pdo->rollBack();
            throw new Exception("نماینده یافت نشد");
        }
        $balance = (float)($row['wallet_balance'] ?? 0);
        if ($balance < $amount) {
            $pdo->rollBack();
            throw new Exception("موجودی کیف پول کافی نیست. موجودی: " . number_format($balance) . "، مبلغ مورد نیاز: " . number_format($amount));
        }
        $pdo->prepare("UPDATE representatives SET wallet_balance = wallet_balance - ? WHERE id = ?")->execute([$amount, $representative_id]);
        $pdo->prepare("INSERT INTO wallet_transactions (representative_id, amount, type, ref_id, description) VALUES (?, ?, ?, ?, ?)")
            ->execute([$representative_id, -$amount, $type, $ref_id, $description]);
        $pdo->commit();
        return true;
    } catch (Exception $e) {
        $pdo->rollBack();
        throw $e;
    }
}

/**
 * واریز به کیف پول نماینده (توسط ادمین)
 */
function walletDeposit($pdo, $representative_id, $amount, $type = 'admin_deposit', $ref_id = null, $description = null) {
    $amount = abs((float)$amount);
    if ($amount <= 0) return true;
    $pdo->prepare("UPDATE representatives SET wallet_balance = wallet_balance + ? WHERE id = ?")->execute([$amount, $representative_id]);
    $pdo->prepare("INSERT INTO wallet_transactions (representative_id, amount, type, ref_id, description) VALUES (?, ?, ?, ?, ?)")
        ->execute([$representative_id, $amount, $type, $ref_id, $description]);
    return true;
}

/**
 * موجودی کیف پول نماینده (در صورت نبود ستون 0 برمی‌گرداند)
 */
function walletBalance($pdo, $representative_id) {
    try {
        $stmt = $pdo->prepare("SELECT wallet_balance FROM representatives WHERE id = ?");
        $stmt->execute([$representative_id]);
        $row = $stmt->fetch();
        return $row ? (float)$row['wallet_balance'] : 0;
    } catch (Exception $e) {
        return 0;
    }
}

/**
 * خواندن تنظیم از جدول settings (اول از DB، در غیر این صورت مقدار پیش‌فرض)
 */
function getSetting($pdo, $name, $default = null) {
    static $cache = null;
    if ($cache === null) {
        $cache = [];
        try {
            $stmt = $pdo->query("SELECT name, value FROM settings");
            if ($stmt) while ($row = $stmt->fetch()) $cache[$row['name']] = $row['value'];
        } catch (Exception $e) { /* جدول ممکن است نباشد */ }
    }
    return isset($cache[$name]) ? $cache[$name] : $default;
}

/**
 * ذخیره تنظیم در جدول settings
 */
function setSetting($pdo, $name, $value) {
    $stmt = $pdo->prepare("INSERT INTO settings (name, value) VALUES (?, ?) ON DUPLICATE KEY UPDATE value = VALUES(value)");
    $stmt->execute([$name, (string)$value]);
    if (function_exists('getSetting')) {
        $r = new ReflectionFunction('getSetting');
        // کش استاتیک را پاک می‌کنیم با فراخوانی مجدد در درخواست بعدی
    }
}

/**
 * قیمت هر کانفیگ (اول از settings، بعد از constant)
 */
function walletPricePerConfig($pdo) {
    $v = getSetting($pdo, 'wallet_price_per_config', null);
    return $v !== null && $v !== '' ? (float)$v : (defined('WALLET_PRICE_PER_CONFIG') ? (float)WALLET_PRICE_PER_CONFIG : 0);
}

/**
 * قیمت هر گیگابایت (اول از settings، بعد از constant)
 */
function walletPricePerGB($pdo) {
    $v = getSetting($pdo, 'wallet_price_per_gb', null);
    return $v !== null && $v !== '' ? (float)$v : (defined('WALLET_PRICE_PER_GB') ? (float)WALLET_PRICE_PER_GB : 0);
}

/**
 * قیمت هر روز اعتبار (اول از settings، بعد از constant)
 */
function walletPricePerDay($pdo) {
    $v = getSetting($pdo, 'wallet_price_per_day', null);
    return $v !== null && $v !== '' ? (float)$v : (defined('WALLET_PRICE_PER_DAY') ? (float)WALLET_PRICE_PER_DAY : 0);
}

/**
 * محدودیت پیش‌فرض کاربر برای هر اینباند (۰ = نامحدود؛ برای پیش‌فرض فرم‌ها استفاده می‌شود)
 */
function defaultInboundUserLimit($pdo) {
    $v = getSetting($pdo, 'default_inbound_user_limit', null);
    return $v !== null && $v !== '' ? (int)$v : 0;
}

/**
 * تخفیف سراسری (درصد، ۰ تا ۱۰۰). اگر نماینده تخفیف جداگانه داشته باشد از آن استفاده می‌شود.
 */
function defaultDiscountPercent($pdo) {
    $v = getSetting($pdo, 'default_discount_percent', null);
    return $v !== null && $v !== '' ? max(0, min(100, (int)$v)) : 0;
}

/** حداقل ترافیک (GB) برای قیمت عادی — اگر نماینده کاربری با ترافیک کمتر بسازد، هزینه اضافی کسر می‌شود */
function minTrafficGbForNormalPrice($pdo) {
    $v = getSetting($pdo, 'min_traffic_gb_for_normal_price', null);
    return $v !== null && $v !== '' ? max(0, (float)$v) : 0;
}

/** هزینه اضافی (تومان) وقتی کاربر با ترافیک زیر حداقل ساخته شود */
function minTrafficExtraCharge($pdo) {
    $v = getSetting($pdo, 'min_traffic_extra_charge', null);
    return $v !== null && $v !== '' ? max(0, (float)$v) : 0;
}

/** امکان تعویض اینباند — ۱ = بله، ۰ = خیر */
function allowInboundChange($pdo) {
    $v = getSetting($pdo, 'allow_inbound_change', null);
    return ($v ?? '') === '1';
}

/** امکان عودت / بازگشت مبلغ — ۱ = بله، ۰ = خیر (از طریق تیکت) */
function allowRefund($pdo) {
    $v = getSetting($pdo, 'allow_refund', null);
    return ($v ?? '') === '1';
}

/** دعوت از دوستان (ریفرال) — ۱ = فعال، ۰ = غیرفعال */
function referralEnabled($pdo) {
    $v = getSetting($pdo, 'referral_enabled', null);
    return ($v ?? '') === '1';
}

/** پاداش ریفرال (تومان یا درصد) به ازای هر دعوت موفق — عدد صحیح */
function referralRewardAmount($pdo) {
    $v = getSetting($pdo, 'referral_reward_amount', null);
    return $v !== null && $v !== '' ? max(0, (int)$v) : 0;
}

/** حداکثر تعداد کاربر هر نماینده — ۰ = نامحدود */
function maxUsersPerRepresentative($pdo) {
    $v = getSetting($pdo, 'max_users_per_representative', null);
    return $v !== null && $v !== '' ? max(0, (int)$v) : 0;
}

/** حداکثر ترافیک هر کاربر (GB) — ۰ = نامحدود */
function maxTrafficPerUserGb($pdo) {
    $v = getSetting($pdo, 'max_traffic_per_user_gb', null);
    return $v !== null && $v !== '' ? max(0, (float)$v) : 0;
}

/** حداقل ترافیک هر کاربر (GB) */
function minTrafficPerUserGb($pdo) {
    $v = getSetting($pdo, 'min_traffic_per_user_gb', null);
    return $v !== null && $v !== '' ? max(0, (float)$v) : 0;
}

/**
 * تبدیل بایت به فرمت خوانا
 */
function formatBytes($bytes, $precision = 2) {
    if ($bytes === null || $bytes < 0) {
        return 'N/A';
    }
    if ($bytes == 0) {
        return '0 B';
    }
    $units = ['B', 'KB', 'MB', 'GB', 'TB'];
    $bytes = max($bytes, 0);
    $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
    $pow = min($pow, count($units) - 1);
    $bytes /= (1 << (10 * $pow));
    return round($bytes, $precision) . ' ' . $units[$pow];
}

?>
