CREATE TABLE IF NOT EXISTS users (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, username VARCHAR(32) NOT NULL UNIQUE, password_hash VARCHAR(255) NOT NULL, phone VARCHAR(30) NOT NULL DEFAULT '', invite_code VARCHAR(16) NULL, inviter_id BIGINT UNSIGNED NULL, register_ip VARCHAR(45) NOT NULL DEFAULT '', balance DECIMAL(14,2) NOT NULL DEFAULT 0, status TINYINT NOT NULL DEFAULT 1, last_login_at DATETIME NULL, last_login_ip VARCHAR(45) NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, UNIQUE INDEX idx_users_invite_code(invite_code), INDEX idx_users_inviter(inviter_id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS admins (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, username VARCHAR(32) NOT NULL UNIQUE, password_hash VARCHAR(255) NOT NULL, last_login_at DATETIME NULL, created_at DATETIME NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS settings (`key` VARCHAR(64) PRIMARY KEY, `value` TEXT NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS recharge_orders (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, order_no VARCHAR(32) NOT NULL UNIQUE, user_id BIGINT UNSIGNED NOT NULL, amount DECIMAL(14,2) NOT NULL, method VARCHAR(30) NOT NULL, payer_note VARCHAR(255) NOT NULL DEFAULT '', status VARCHAR(20) NOT NULL DEFAULT 'pending', admin_note VARCHAR(255) NOT NULL DEFAULT '', reviewed_by BIGINT UNSIGNED NULL, reviewed_at DATETIME NULL, reversed_by BIGINT UNSIGNED NULL, reversed_at DATETIME NULL, reversal_note VARCHAR(255) NOT NULL DEFAULT '', created_at DATETIME NOT NULL, INDEX idx_recharge_user(user_id, id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS recharge_cards (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, code VARCHAR(32) NOT NULL UNIQUE, amount DECIMAL(14,2) NOT NULL, card_type VARCHAR(20) NOT NULL DEFAULT 'single', status VARCHAR(20) NOT NULL DEFAULT 'unused', used_by BIGINT UNSIGNED NULL, used_at DATETIME NULL, created_at DATETIME NOT NULL, INDEX idx_card_type_status(card_type, status, id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS recharge_card_redemptions (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, card_id BIGINT UNSIGNED NOT NULL, user_id BIGINT UNSIGNED NOT NULL, amount DECIMAL(14,2) NOT NULL, created_at DATETIME NOT NULL, UNIQUE INDEX idx_card_user_once(card_id, user_id), INDEX idx_card_redemptions(card_id, id), INDEX idx_user_card_redemptions(user_id, id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS balance_logs (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, user_id BIGINT UNSIGNED NOT NULL, type VARCHAR(30) NOT NULL, amount DECIMAL(14,2) NOT NULL, balance_before DECIMAL(14,2) NOT NULL, balance_after DECIMAL(14,2) NOT NULL, note VARCHAR(255) NOT NULL, reference_no VARCHAR(40) NULL, created_at DATETIME NOT NULL, INDEX idx_balance_user(user_id, id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS game_logs (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, user_id BIGINT UNSIGNED NOT NULL, game_type VARCHAR(20) NOT NULL DEFAULT 'spin', bet_amount DECIMAL(14,2) NOT NULL, win_amount DECIMAL(14,2) NOT NULL, profit DECIMAL(14,2) NOT NULL, result_json TEXT NOT NULL, created_at DATETIME NOT NULL, INDEX idx_game_user(user_id, id), INDEX idx_game_type(game_type, id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS withdrawal_orders (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, user_id BIGINT UNSIGNED NOT NULL, amount DECIMAL(14,2) NOT NULL, account VARCHAR(100) NOT NULL, real_name VARCHAR(50) NOT NULL, status VARCHAR(20) NOT NULL DEFAULT 'pending', created_at DATETIME NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS game_pending_wins (user_id BIGINT UNSIGNED PRIMARY KEY, amount DECIMAL(14,2) NOT NULL DEFAULT 0, updated_at DATETIME NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS referral_rewards (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, inviter_id BIGINT UNSIGNED NOT NULL, invitee_id BIGINT UNSIGNED NOT NULL, invitee_ip VARCHAR(45) NOT NULL DEFAULT '', reward_ip VARCHAR(45) NULL, reward_amount DECIMAL(14,2) NOT NULL DEFAULT 0, status VARCHAR(20) NOT NULL, reason VARCHAR(100) NOT NULL DEFAULT '', created_at DATETIME NOT NULL, UNIQUE INDEX idx_referral_invitee(invitee_id), UNIQUE INDEX idx_referral_reward_ip(reward_ip), INDEX idx_referral_inviter(inviter_id, id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS recharge_commissions (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, source_type VARCHAR(20) NOT NULL, source_ref VARCHAR(40) NOT NULL, recharging_user_id BIGINT UNSIGNED NOT NULL, beneficiary_user_id BIGINT UNSIGNED NOT NULL, level TINYINT UNSIGNED NOT NULL, rate DECIMAL(7,4) NOT NULL, recharge_amount DECIMAL(14,2) NOT NULL, commission_amount DECIMAL(14,2) NOT NULL, reversed_by BIGINT UNSIGNED NULL, reversed_at DATETIME NULL, created_at DATETIME NOT NULL, UNIQUE INDEX idx_commission_source(source_type, source_ref, beneficiary_user_id, level), INDEX idx_commission_beneficiary(beneficiary_user_id, level, id), INDEX idx_commission_recharging(recharging_user_id, id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS auth_attempts (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, scope VARCHAR(30) NOT NULL, identifier_hash CHAR(64) NOT NULL, ip_address VARCHAR(45) NOT NULL DEFAULT '', succeeded TINYINT NOT NULL DEFAULT 0, attempted_at DATETIME NOT NULL, INDEX idx_auth_limit(scope, identifier_hash, ip_address, attempted_at)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS admin_audit_logs (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, admin_id BIGINT UNSIGNED NOT NULL, action VARCHAR(50) NOT NULL, target_type VARCHAR(40) NOT NULL DEFAULT '', target_id VARCHAR(64) NOT NULL DEFAULT '', before_json TEXT NULL, after_json TEXT NULL, ip_address VARCHAR(45) NOT NULL DEFAULT '', created_at DATETIME NOT NULL, INDEX idx_admin_audit(admin_id, id), INDEX idx_admin_target(target_type, target_id, id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
