-- =====================================================================
--  00 — HISTORY: every SQL file of the project, in the order they belong, in ONE file
--
--  FOR THE RECORD ONLY — do NOT run this on your live database: the ALTER TABLE statements
--  fail when the column already exists. To (re)build a database use 03_full_schema_current.sql
--  (from scratch) or 02_upgrade_from_install.sql (on top of 01_install.sql).
--
--  Order: install.sql → migration_01 … migration_16 → migration_help_center → migration_bot_texts → reorder_menu.
--  (The exact date each one was run is not known; this is the order their content requires.)
--  Each file is copied unchanged between the "BEGIN"/"END" lines.
-- =====================================================================


-- #####################################################################
-- BEGIN install.sql
-- #####################################################################
-- =====================================================================
--  VPN SHOP BOT - DATABASE SCHEMA
--  Everything an admin needs to change later (plans, buttons, admins,
--  channels, texts, prices) lives in these tables, NOT in PHP code.
-- =====================================================================

SET NAMES utf8mb4;

-- ---------------------------------------------------------------------
-- users
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS users (
    id              INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    tg_id           BIGINT UNSIGNED NOT NULL UNIQUE,
    username        VARCHAR(64)  NULL,
    first_name      VARCHAR(128) NULL,
    phone           VARCHAR(32)  NULL,
    balance         BIGINT       NOT NULL DEFAULT 0,      -- Toman
    ref_by          INT UNSIGNED NULL,                    -- users.id of inviter
    is_banned       TINYINT(1)   NOT NULL DEFAULT 0,
    used_free_test  TINYINT(1)   NOT NULL DEFAULT 0,
    created_at      DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (ref_by) REFERENCES users(id) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ---------------------------------------------------------------------
-- admins  (role: owner | manager | support)
--   owner   -> full access, can add/remove other admins
--   manager -> everything except managing admins
--   support -> only approve/reject orders & wallet charges + broadcast
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS admins (
    id          INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    tg_id       BIGINT UNSIGNED NOT NULL UNIQUE,
    role        ENUM('owner','manager','support') NOT NULL DEFAULT 'support',
    added_by    BIGINT UNSIGNED NULL,
    created_at  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ---------------------------------------------------------------------
-- settings  (generic key/value store, edited entirely from bot panel)
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS settings (
    setting_key     VARCHAR(64) PRIMARY KEY,
    setting_value   TEXT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ---------------------------------------------------------------------
-- menu_buttons  (main-menu feature toggles - add/remove/enable/disable
--                 without touching code)
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS menu_buttons (
    id          INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    button_key  VARCHAR(32) NOT NULL UNIQUE,   -- internal code, e.g. 'buy'
    label       VARCHAR(64) NOT NULL,          -- what user sees, e.g. 'خرید اشتراک 🛒'
    enabled     TINYINT(1) NOT NULL DEFAULT 1,
    sort_order  INT NOT NULL DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ---------------------------------------------------------------------
-- categories  ("مولتی لوکیشن" etc.) - the top level of the buy flow
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS categories (
    id          INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    title       VARCHAR(64) NOT NULL,
    pg_group_ids VARCHAR(255) NULL,  -- PasarGuard group/inbound ids for this category
    enabled     TINYINT(1) NOT NULL DEFAULT 1,
    sort_order  INT NOT NULL DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ---------------------------------------------------------------------
-- durations  (1 ماهه / 2 ماهه / 3 ماهه ...) attached to a category
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS durations (
    id            INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    category_id   INT UNSIGNED NOT NULL,
    title         VARCHAR(32) NOT NULL,   -- '1 ماهه'
    days          INT NOT NULL,           -- 30
    enabled       TINYINT(1) NOT NULL DEFAULT 1,
    sort_order    INT NOT NULL DEFAULT 0,
    FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ---------------------------------------------------------------------
-- plans  (the actual gb/price rows shown after duration is picked)
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS plans (
    id            INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    duration_id   INT UNSIGNED NOT NULL,
    gb            INT NOT NULL,           -- 0 = unlimited
    price         BIGINT NOT NULL,        -- Toman
    enabled       TINYINT(1) NOT NULL DEFAULT 1,
    sort_order    INT NOT NULL DEFAULT 0,
    FOREIGN KEY (duration_id) REFERENCES durations(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ---------------------------------------------------------------------
-- force_join_channels
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS force_join_channels (
    id          INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    chat_id     VARCHAR(64) NOT NULL,   -- @channelusername OR -100xxxxxxxxxx
    title       VARCHAR(128) NULL,
    invite_link VARCHAR(255) NULL,
    enabled     TINYINT(1) NOT NULL DEFAULT 1
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ---------------------------------------------------------------------
-- service_names  (names a user has previously used, offered again)
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS service_names (
    id          INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    user_id     INT UNSIGNED NOT NULL,
    name        VARCHAR(40) NOT NULL,
    created_at  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    UNIQUE KEY uniq_user_name (user_id, name),
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ---------------------------------------------------------------------
-- orders  (purchase requests waiting/approved/rejected)
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS orders (
    id              INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    user_id         INT UNSIGNED NOT NULL,
    plan_id         INT UNSIGNED NULL,          -- NULL for wallet-paid instantly
    service_name    VARCHAR(40) NOT NULL,
    amount          BIGINT NOT NULL,
    pay_method      ENUM('wallet','card') NOT NULL DEFAULT 'wallet',
    status          ENUM('pending','approved','rejected') NOT NULL DEFAULT 'pending',
    receipt_file_id VARCHAR(255) NULL,
    sub_link        TEXT NULL,
    admin_msg_id    BIGINT NULL,      -- message id sent to admin for approve/reject
    reviewed_by     BIGINT UNSIGNED NULL,
    created_at      DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    reviewed_at     DATETIME NULL,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
    FOREIGN KEY (plan_id) REFERENCES plans(id) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ---------------------------------------------------------------------
-- wallet_charges  (کارت‌به‌کارت افزایش موجودی, pending admin approval)
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS wallet_charges (
    id              INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    user_id         INT UNSIGNED NOT NULL,
    amount          BIGINT NOT NULL,
    receipt_file_id VARCHAR(255) NULL,
    status          ENUM('pending','approved','rejected') NOT NULL DEFAULT 'pending',
    admin_msg_id    BIGINT NULL,
    reviewed_by     BIGINT UNSIGNED NULL,
    created_at      DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    reviewed_at     DATETIME NULL,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ---------------------------------------------------------------------
-- transactions  (full ledger: charge / purchase / referral_commission)
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS transactions (
    id              INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    user_id         INT UNSIGNED NOT NULL,
    type            ENUM('charge','purchase','referral_commission','admin_adjust') NOT NULL,
    amount          BIGINT NOT NULL,         -- positive = credit, negative = debit
    balance_after   BIGINT NOT NULL,
    meta            VARCHAR(255) NULL,
    created_at      DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ---------------------------------------------------------------------
-- user_state  (multi-step conversation state machine)
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS user_state (
    tg_id       BIGINT UNSIGNED PRIMARY KEY,
    step        VARCHAR(64) NOT NULL,
    data        TEXT NULL,          -- JSON blob of collected step data
    updated_at  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- =====================================================================
--  SEED DATA - default settings & menu buttons
--  (all editable later from inside the bot, this is just the starting
--   point so the bot works immediately after install)
-- =====================================================================

INSERT INTO settings (setting_key, setting_value) VALUES
    ('welcome_text', 'به ربات IranJrVPN خوش آمدید 🤍\n\nاز منوی زیر بخش مورد نظرتان را انتخاب کنید.'),
    ('card_number', '6037-XXXX-XXXX-XXXX'),
    ('card_holder', 'نام صاحب کارت'),
    ('min_charge_amount', '50000'),
    ('referral_percent', '5'),
    ('force_join_enabled', '0'),
    ('reseller_enabled', '0'),
    ('free_test_gb', '1'),
    ('free_test_days', '1'),
    ('bot_username', 'your_bot_username')
ON DUPLICATE KEY UPDATE setting_key = setting_key;

INSERT INTO menu_buttons (button_key, label, enabled, sort_order) VALUES
    ('buy',        'خرید اشتراک 🛒',        1, 1),
    ('plans_info', 'انواع اشتراک 📚',        1, 2),
    ('free_test',  'تست رایگان 🧪',         1, 3),
    ('account',    'حساب کاربری 👤',        1, 4),
    ('charge',     'افزایش موجودی 💰',      1, 5),
    ('referral',   'دعوت دوستان 🎁',        1, 6),
    ('reseller',   'درخواست نمایندگی 🤝',   0, 7),
    ('support',    'پشتیبانی 💬',           1, 8)
ON DUPLICATE KEY UPDATE button_key = button_key;

INSERT INTO categories (title, pg_group_ids, enabled, sort_order) VALUES
    ('مولتی لوکیشن', '', 1, 1)
ON DUPLICATE KEY UPDATE title = title;

INSERT INTO durations (category_id, title, days, enabled, sort_order) VALUES
    (1, '1 ماهه', 30, 1, 1),
    (1, '2 ماهه', 60, 1, 2),
    (1, '3 ماهه', 90, 1, 3)
ON DUPLICATE KEY UPDATE title = title;

-- Example plans under "1 ماهه" - EDIT/ADD FROM THE ADMIN PANEL LATER
INSERT INTO plans (duration_id, gb, price, enabled, sort_order) VALUES
    (1, 10, 30000, 1, 1),
    (1, 20, 60000, 1, 2),
    (1, 30, 90000, 1, 3)
ON DUPLICATE KEY UPDATE gb = gb;
-- END install.sql


-- #####################################################################
-- BEGIN migration_01_payments.sql
-- #####################################################################
-- Run this once in phpMyAdmin on your existing database (select the database first, then SQL tab).
ALTER TABLE wallet_charges
    ADD COLUMN reject_reason VARCHAR(255) NULL AFTER reviewed_at;

ALTER TABLE orders
    ADD COLUMN reject_reason VARCHAR(255) NULL AFTER reviewed_at;

CREATE TABLE IF NOT EXISTS admin_activity_log (
    id          INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    admin_tg_id BIGINT UNSIGNED NOT NULL,
    action      VARCHAR(100) NOT NULL,
    details     VARCHAR(500) NULL,
    created_at  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- END migration_01_payments.sql


-- #####################################################################
-- BEGIN migration_02_users.sql
-- #####################################################################
-- Run this once in phpMyAdmin (select the database, then SQL tab).
-- Needed for the "کاربران" section — lets the bot auto-detect users who blocked/deleted it.
ALTER TABLE users
    ADD COLUMN blocked_bot TINYINT(1) NOT NULL DEFAULT 0 AFTER is_banned;
-- END migration_02_users.sql


-- #####################################################################
-- BEGIN migration_03_servers.sql
-- #####################################################################
-- Run this once in phpMyAdmin (select the database, then SQL tab).
-- Needed for the "سرورها" section — stores multiple panel connections (PasarGuard, Marzban, Sanaei, X-UI).
CREATE TABLE IF NOT EXISTS servers (
    id         INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    type       VARCHAR(20) NOT NULL,
    name       VARCHAR(100) NOT NULL,
    base_url   VARCHAR(255) NOT NULL,
    username   VARCHAR(100) NULL,
    password   VARCHAR(255) NULL,
    enabled    TINYINT(1) NOT NULL DEFAULT 1,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- END migration_03_servers.sql


-- #####################################################################
-- BEGIN migration_04_category_server.sql
-- #####################################################################
-- Run this once in phpMyAdmin (select the database, then SQL tab).
-- Lets each service (category) be pointed at a specific panel from "سرورها".
-- NULL/0 = keep using the old default panel from config.php.
ALTER TABLE categories
    ADD COLUMN server_id INT UNSIGNED NULL AFTER pg_group_ids;
-- END migration_04_category_server.sql


-- #####################################################################
-- BEGIN migration_05_server_token_auth.sql
-- #####################################################################
-- Run this once in phpMyAdmin (select the database, then SQL tab).
-- Lets a server be authenticated either via username/password (as before)
-- or a static API token pasted directly from the panel.
ALTER TABLE servers
    ADD COLUMN auth_type VARCHAR(10) NOT NULL DEFAULT 'userpass' AFTER type,
    ADD COLUMN api_token VARCHAR(500) NULL AFTER password;
-- END migration_05_server_token_auth.sql


-- #####################################################################
-- BEGIN migration_06_sub_domain.sql
-- #####################################################################
-- Run this once in phpMyAdmin (select the database, then SQL tab).
-- Some panels (PasarGuard included) return the subscription link as a
-- RELATIVE path (e.g. "/sub/xxxx") instead of a full URL. That's fine for
-- the panel's own API calls (which go through base_url — often a
-- Cloudflare Worker/relay), but a relative link is useless if shown to
-- the end user, since it's not a real address to open.
--
-- sub_domain is the REAL public domain of the panel (the one the end
-- user's VPN client connects to), used only to complete relative
-- subscription links. It is separate from base_url on purpose: base_url
-- might point at a relay (e.g. a Cloudflare Worker) used only for the
-- admin API, while sub_domain is what actually gets opened by clients.
-- NULL = fall back to base_url (old behaviour).
ALTER TABLE servers
    ADD COLUMN sub_domain VARCHAR(255) NULL AFTER base_url;
-- END migration_06_sub_domain.sql


-- #####################################################################
-- BEGIN migration_07_default_group.sql
-- NOTE: sets pg_group_ids = 3 — specific to YOUR panel (group id 3 = "Direct & Tunnel"). Only relevant on that panel.
-- #####################################################################
-- Quick fix: sets every existing category to use group id 3 ("Direct & Tunnel"),
-- confirmed via GET /api/user/<username> → "group_ids": [3] on an already-working account.
-- This unblocks purchases immediately, regardless of whether the bot's admin account
-- has "groups.read" permission on the panel yet.
--
-- Longer-term: grant the "Groups: Read" permission to this bot's admin account inside
-- the panel (Admins → the admin used for the bot's userpass login → permissions). Once
-- granted, you can leave pg_group_ids empty for new categories and the bot will
-- automatically fetch + apply ALL panel groups on every purchase (see pg_get_all_group_ids
-- in includes/pasarguard.php) — useful if you add more groups later.
UPDATE categories SET pg_group_ids = '3' WHERE pg_group_ids IS NULL OR pg_group_ids = '';
-- END migration_07_default_group.sql


-- #####################################################################
-- BEGIN migration_08_tariffs.sql
-- #####################################################################
-- Run this once in phpMyAdmin (select the database, then SQL tab).
-- Adds the "تعرفه‌ها" button to the user's main menu and a default tariffs text.
INSERT INTO menu_buttons (button_key, label, enabled, sort_order)
    VALUES ('tariffs', 'تعرفه‌ها 💵', 1, 9)
    ON DUPLICATE KEY UPDATE button_key = button_key;

INSERT INTO settings (setting_key, setting_value)
    VALUES ('tariffs_text', 'تعرفه‌های ما به‌زودی اینجا اعلام می‌شود.')
    ON DUPLICATE KEY UPDATE setting_key = setting_key;
-- END migration_08_tariffs.sql


-- #####################################################################
-- BEGIN migration_09_screen_message.sql
-- #####################################################################
-- Run this once in phpMyAdmin (select the database, then SQL tab).
-- "Clean chat" architecture: instead of sending a new message for every
-- menu/step, the bot edits ONE message in place per chat. This column
-- remembers which message_id is currently the "screen" for that chat.
ALTER TABLE users
    ADD COLUMN screen_message_id BIGINT NULL AFTER blocked_bot;
-- END migration_09_screen_message.sql


-- #####################################################################
-- BEGIN migration_10_menu_message.sql
-- #####################################################################
-- Run this once in phpMyAdmin (select the database, then SQL tab).
-- Companion to migration_09_screen_message.sql. The main (reply-keyboard)
-- menu message can never be tracked as the editable "screen" anchor — see
-- the comment above screen_menu() in includes/screen.php for why — so it
-- gets its own small anchor here, purely so the previous bottom-menu
-- bubble is cleaned up whenever a new one is sent.
ALTER TABLE users
    ADD COLUMN menu_message_id BIGINT NULL AFTER screen_message_id;
-- END migration_10_menu_message.sql


-- #####################################################################
-- BEGIN migration_11_service_name_index.sql
-- #####################################################################
-- Run this once in phpMyAdmin (select the database, then SQL tab).
-- Speeds up the new "is this name already taken by someone else" check in
-- buy_receive_new_name() — without this, that query has to scan the whole
-- table (the existing unique key covers (user_id, name), not name alone).
ALTER TABLE service_names
    ADD INDEX idx_name (name);
-- END migration_11_service_name_index.sql


-- #####################################################################
-- BEGIN migration_12_payment_cards.sql
-- #####################################################################
-- Run this once in phpMyAdmin (select the database, then SQL tab).
-- Replaces the single card_number/card_holder settings with a proper table,
-- so multiple cards can be added, independently enabled/disabled (only
-- enabled ones are shown to users in the top-up invoice), and deleted.
CREATE TABLE IF NOT EXISTS payment_cards (
    id          INT AUTO_INCREMENT PRIMARY KEY,
    card_number VARCHAR(32)  NOT NULL,
    card_holder VARCHAR(100) NOT NULL,
    enabled     TINYINT(1)   NOT NULL DEFAULT 1,
    sort_order  INT          NOT NULL DEFAULT 0,
    created_at  TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- If the table already got created by an earlier failed run of this file,
-- make sure it's on the right charset (fixes "Incorrect string value" for Persian text).
ALTER TABLE payment_cards CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- Carry over whatever single card was already configured (if any) as the
-- first row, so nothing is lost for bots that were already running.
SET @old_number = (SELECT setting_value FROM settings WHERE setting_key = 'card_number' LIMIT 1);
SET @old_holder  = (SELECT setting_value FROM settings WHERE setting_key = 'card_holder' LIMIT 1);

INSERT INTO payment_cards (card_number, card_holder, enabled, sort_order)
SELECT @old_number, COALESCE(@old_holder, ''), 1, 0
WHERE @old_number IS NOT NULL AND @old_number <> ''
  AND NOT EXISTS (SELECT 1 FROM payment_cards);
-- END migration_12_payment_cards.sql


-- #####################################################################
-- BEGIN migration_13_free_test_rework.sql
-- #####################################################################
-- Run this once in phpMyAdmin (select the database, then SQL tab).
-- Reworks the free test: was GB/days + a one-time boolean flag; now
-- MB/hours + a per-user counter, so the admin can allow more than one
-- free test per person (free_test_max_count) and reset it whenever needed.
ALTER TABLE users
    ADD COLUMN free_test_used_count INT NOT NULL DEFAULT 0 AFTER used_free_test;

-- Carry over anyone who already used their (old, one-time) free test.
UPDATE users SET free_test_used_count = 1 WHERE used_free_test = 1;

INSERT INTO settings (setting_key, setting_value) VALUES ('free_test_mb', '1024')
    ON DUPLICATE KEY UPDATE setting_key = setting_key;
INSERT INTO settings (setting_key, setting_value) VALUES ('free_test_hours', '24')
    ON DUPLICATE KEY UPDATE setting_key = setting_key;
INSERT INTO settings (setting_key, setting_value) VALUES ('free_test_max_count', '1')
    ON DUPLICATE KEY UPDATE setting_key = setting_key;
-- Note: if you had customized free_test_gb / free_test_days before, those
-- old settings are left untouched but no longer used — re-set the new
-- free_test_mb / free_test_hours values from "تنظیمات ← تست رایگان" if needed.
-- END migration_13_free_test_rework.sql


-- #####################################################################
-- BEGIN migration_14_admin_activity_log.sql
-- NOTE: same table as in migration_01 (IF NOT EXISTS) — harmless duplicate.
-- #####################################################################
-- «📋 گزارش فعالیت» — جدول لاگ اقدام‌های ادمین‌ها.
--
-- اگه migration_01_payments.sql رو قبلاً اجرا کردی، این جدول همین الان هست و
-- نیازی به اجرای این فایل نیست. ولی اگه اجرا کردنش هم بکنی مشکلی پیش نمیاد
-- (IF NOT EXISTS — به داده‌های موجود دست نمی‌زنه).
--
-- فقط اگه ربات تو «گزارش فعالیت» پیام «جدول پیدا نشد» نشون داد، این رو تو
-- phpMyAdmin اجرا کن (اول دیتابیس رو انتخاب کن، بعد تب SQL).
CREATE TABLE IF NOT EXISTS admin_activity_log (
    id          INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    admin_tg_id BIGINT UNSIGNED NOT NULL,
    action      VARCHAR(100) NOT NULL,
    details     VARCHAR(500) NULL,
    created_at  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- END migration_14_admin_activity_log.sql


-- #####################################################################
-- BEGIN migration_15_about_button.sql
-- #####################################################################
-- Run this once in phpMyAdmin (select the database, then SQL tab).
-- Adds the "درباره سازنده" button to the user's main menu (it already
-- existed inside پنل مدیریت — this just also surfaces it to regular users).
-- Its text is fixed in code (handlers/admin.php, show_about_developer())
-- and NOT stored in settings, so — unlike every other button here — there
-- is no way to edit its content from inside the bot itself.
INSERT INTO menu_buttons (button_key, label, enabled, sort_order)
    VALUES ('about', '🌟 درباره سازنده', 1, 10)
    ON DUPLICATE KEY UPDATE button_key = button_key;
-- END migration_15_about_button.sql


-- #####################################################################
-- BEGIN migration_16_orders_server_link.sql
-- #####################################################################
-- Run this once in phpMyAdmin (select the database, then SQL tab).
-- Needed for «🔗 اتصال اشتراک»: a linked subscription has no plan_id (it
-- wasn't bought through a plan here), so there's no plan→duration→category
-- chain to find which panel it lives on. server_id records that directly,
-- so the subscription can be renewed later exactly like a normal purchase.
ALTER TABLE orders
    ADD COLUMN server_id INT UNSIGNED NULL AFTER plan_id,
    ADD FOREIGN KEY (server_id) REFERENCES servers(id) ON DELETE SET NULL,
    MODIFY COLUMN pay_method ENUM('wallet','card','linked') NOT NULL DEFAULT 'wallet';
-- END migration_16_orders_server_link.sql


-- #####################################################################
-- BEGIN migration_help_center.sql
-- NOTE: the bot also creates this table by itself on first use.
-- #####################################################################
-- Run this once in phpMyAdmin (select the database, then SQL tab).
-- «📘 راهنمای استفاده» با زیرمجموعه (آموزش‌ها + دانلود نرم‌افزار).
--
-- یک درخت ساده:
--   root      = 'guide' (آموزش‌ها) یا 'download' (دانلود نرم‌افزار)
--   parent_id = NULL → مستقیم زیر همان بخش؛ وگرنه داخل یک پوشه
--   kind      = 'folder' پوشه | 'post' پست کانال تلگرام (url = لینک پست) | 'link' لینک دانلود/سایت (url + note)
-- (اجرای دستی لازم نیست؛ ربات هنگام اولین استفاده همین جدول را خودش می‌سازد.)
CREATE TABLE IF NOT EXISTS help_items (
    id         INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    root       ENUM('guide','download') NOT NULL,
    parent_id  INT UNSIGNED NULL,
    kind       ENUM('folder','post','link') NOT NULL,
    title      VARCHAR(100) NOT NULL,
    url        VARCHAR(500) NULL,
    note       TEXT NULL,
    sort_order INT NOT NULL DEFAULT 0,
    enabled    TINYINT(1) NOT NULL DEFAULT 1,
    KEY idx_tree (root, parent_id, sort_order)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- END migration_help_center.sql


-- #####################################################################
-- BEGIN migration_bot_texts.sql
-- NOTE: OBSOLETE — the current bot keeps edited texts in the `settings` table (bot_text() in includes/helpers.php); the bot_texts table is not in your live database and no code reads it. Kept only for the record.
-- #####################################################################
-- ✏️ متن‌ها و دکمه‌ها — جدول تغییرهای ادمین.
--
-- معمولاً لازم نیست این فایل را اجرا کنی: جدول خودش، هنگام اولین ذخیره‌ی یک متن ساخته می‌شود.
-- فقط اگر ربات موقع ذخیره گفت «ذخیره نشد» (یعنی دیتابیس اجازه‌ی ساخت جدول را نمی‌دهد)،
-- این را یک‌بار در phpMyAdmin اجرا کن (اول دیتابیس را انتخاب کن، بعد تب SQL).
-- اجرای چندباره‌اش بی‌خطر است.
CREATE TABLE IF NOT EXISTS bot_texts (
    text_key   VARCHAR(64) NOT NULL PRIMARY KEY,   -- کلید متن/دکمه (مثل btn_back)
    text_value TEXT NOT NULL,                      -- متنی که ادمین گذاشته
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- END migration_bot_texts.sql


-- #####################################################################
-- BEGIN reorder_menu.sql
-- NOTE: expects the buttons buy/charge/link_sub/free_test/plans_info/account/referral/support/about/tariffs/reseller to exist. The «link_sub» button is not created by any of these files (it was added to menu_buttons separately).
-- #####################################################################
-- Run this once in phpMyAdmin (select the database, then SQL tab).
-- Reorders the main menu buttons and renames "افزایش موجودی" to "کیف پول".
-- Colors (green/blue/plain) are handled in code (includes/helpers.php,
-- main_menu_keyboard()) — this file only sets the order + the one label.

UPDATE menu_buttons SET sort_order = 1 WHERE button_key = 'buy';
UPDATE menu_buttons SET sort_order = 2, label = 'کیف پول 💰' WHERE button_key = 'charge';
UPDATE menu_buttons SET sort_order = 3 WHERE button_key = 'link_sub';
UPDATE menu_buttons SET sort_order = 4 WHERE button_key = 'free_test';
UPDATE menu_buttons SET sort_order = 5 WHERE button_key = 'plans_info';
UPDATE menu_buttons SET sort_order = 6 WHERE button_key = 'account';
UPDATE menu_buttons SET sort_order = 7 WHERE button_key = 'referral';
UPDATE menu_buttons SET sort_order = 8 WHERE button_key = 'support';
UPDATE menu_buttons SET sort_order = 9 WHERE button_key = 'about';
-- keeps تعرفه‌ها / نمایندگی (not mentioned in the new order) tucked at the end,
-- wherever they land, instead of disrupting the 9 buttons above
UPDATE menu_buttons SET sort_order = 50 WHERE button_key IN ('tariffs', 'reseller');
-- END reorder_menu.sql
