#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
╔══════════════════════════════════════════════════════════════╗
║        🎌 ANIME BOT — TO'LIQ O'ZBEK TELEGRAM BOTI            ║
║           PHP bot.php → Python (aiogram 3.x)                 ║
║                                                              ║
║  Asosiy dasturchi: @ZenoAdmin                                ║
║                                                              ║
╚══════════════════════════════════════════════════════════════╝

O'rnatish:
    pip install aiogram aiosqlite

Ishga tushirish:
    python uzbek.py
"""

import asyncio
import logging
import sqlite3
import time
import re
from datetime import datetime
from typing import Optional

from aiogram import Bot, Dispatcher, types, F
from aiogram.filters import Command, CommandStart
from aiogram.types import (
    InlineKeyboardMarkup, InlineKeyboardButton,
    ReplyKeyboardMarkup, KeyboardButton,
    ReplyKeyboardRemove, CallbackQuery, FSInputFile
)
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.exceptions import TelegramBadRequest, TelegramForbiddenError

# ════════════════════════════════════════════════════════════════
#                    ⚙️ ASOSIY SOZLAMALAR
# ════════════════════════════════════════════════════════════════

BOT_TOKEN    = "8717761679:AAGSf8QrwsjqnHz7W1UP99-SdE4xaZ0BlrY"          # 🔑 BotFather tokeningizni shu yerga yozing
ADMIN_ID     =  8054494326                    # 👑 O'z Telegram ID raqamingizni shu yerga yozing
DB_FILE      = "anime_bot.db"

# Logging
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s | %(levelname)s | %(message)s",
    handlers=[
        logging.FileHandler("anime_bot.log", encoding="utf-8"),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger(__name__)

# ════════════════════════════════════════════════════════════════
#                    🗄️  DATABASE
# ════════════════════════════════════════════════════════════════

def get_db():
    conn = sqlite3.connect(DB_FILE)
    conn.row_factory = sqlite3.Row
    return conn

def init_db():
    """Barcha jadvallarni yaratish (PHP sql.php analog)"""
    conn = get_db()
    c = conn.cursor()

    # Foydalanuvchilar (user_id)
    c.execute("""
        CREATE TABLE IF NOT EXISTS user_id (
            id      INTEGER PRIMARY KEY AUTOINCREMENT,
            user_id TEXT UNIQUE NOT NULL,
            status  TEXT NOT NULL DEFAULT 'Oddiy',
            refid   TEXT DEFAULT NULL,
            sana    TEXT NOT NULL DEFAULT ''
        )
    """)

    # Kabinet (hisobot)
    c.execute("""
        CREATE TABLE IF NOT EXISTS kabinet (
            id      INTEGER PRIMARY KEY AUTOINCREMENT,
            user_id TEXT UNIQUE NOT NULL,
            pul     REAL NOT NULL DEFAULT 0,
            pul2    REAL NOT NULL DEFAULT 0,
            odam    INTEGER NOT NULL DEFAULT 0,
            ban     TEXT NOT NULL DEFAULT 'unban'
        )
    """)

    # VIP status
    c.execute("""
        CREATE TABLE IF NOT EXISTS status (
            id      INTEGER PRIMARY KEY AUTOINCREMENT,
            user_id TEXT UNIQUE NOT NULL,
            kun     INTEGER NOT NULL DEFAULT 0,
            date    TEXT NOT NULL DEFAULT ''
        )
    """)

    # Anime asosiy ma'lumotlari (animelar)
    c.execute("""
        CREATE TABLE IF NOT EXISTS animelar (
            id       INTEGER PRIMARY KEY AUTOINCREMENT,
            nom      TEXT NOT NULL,
            rams     TEXT NOT NULL,
            qismi    TEXT NOT NULL,
            davlat   TEXT NOT NULL,
            tili     TEXT NOT NULL,
            yili     TEXT NOT NULL,
            janri    TEXT NOT NULL,
            qidiruv  INTEGER NOT NULL DEFAULT 0,
            sana     TEXT NOT NULL DEFAULT '',
            aniType  TEXT DEFAULT '',
            like_c   INTEGER DEFAULT 0,
            deslike  INTEGER DEFAULT 0
        )
    """)

    # Anime qismlari (anime_datas)
    c.execute("""
        CREATE TABLE IF NOT EXISTS anime_datas (
            data_id INTEGER PRIMARY KEY AUTOINCREMENT,
            id      TEXT NOT NULL,
            file_id TEXT NOT NULL,
            qism    INTEGER NOT NULL,
            sana    TEXT DEFAULT NULL
        )
    """)

    # Majburiy obuna kanallari (channels)
    c.execute("""
        CREATE TABLE IF NOT EXISTS channels (
            id          INTEGER PRIMARY KEY AUTOINCREMENT,
            channelId   TEXT NOT NULL,
            channelType TEXT NOT NULL,
            channelLink TEXT NOT NULL
        )
    """)

    # Join so'rovlari
    c.execute("""
        CREATE TABLE IF NOT EXISTS joinRequests (
            id        INTEGER PRIMARY KEY AUTOINCREMENT,
            channelId TEXT NOT NULL,
            userId    TEXT NOT NULL,
            UNIQUE(channelId, userId)
        )
    """)

    # Adminlar
    c.execute("""
        CREATE TABLE IF NOT EXISTS admins (
            id      INTEGER PRIMARY KEY AUTOINCREMENT,
            user_id TEXT UNIQUE NOT NULL
        )
    """)

    # Bot sozlamalari
    c.execute("""
        CREATE TABLE IF NOT EXISTS settings (
            key_name TEXT PRIMARY KEY,
            val      TEXT NOT NULL DEFAULT ''
        )
    """)

    # Anime kanallar (post uchun)
    c.execute("""
        CREATE TABLE IF NOT EXISTS anime_kanallar (
            id         INTEGER PRIMARY KEY AUTOINCREMENT,
            channel_id TEXT UNIQUE NOT NULL
        )
    """)

    # Birlamchi sozlamalar
    defaults = [
        ("valyuta",     "so'm"),
        ("vip_narx",    "25000"),
        ("studio_name", "Anime Bot"),
        ("bot_holat",   "Yoqilgan"),
        ("content",     "false"),
        ("start_text",  "✨ Botga xush kelibsiz!"),
        ("qollanma",    "📚 Bu bot orqali anime tomosha qilishingiz mumkin."),
        ("homiy",       "💵 Homiylik uchun admin bilan bog'laning."),
        ("key1", "🔎 Anime izlash"),
        ("key2", "💎 VIP"),
        ("key3", "💰 Hisobim"),
        ("key4", "➕ Pul kiritish"),
        ("key5", "📚 Qo'llanma"),
        ("key6", "💵 Reklama va Homiylik"),
    ]
    for k, v in defaults:
        c.execute("INSERT OR IGNORE INTO settings (key_name, val) VALUES (?, ?)", (k, v))

    conn.commit()
    conn.close()
    logger.info("✅ Database tayyor")


# ════════════════════════════════════════════════════════════════
#                    🔧 YORDAMCHI FUNKSIYALAR
# ════════════════════════════════════════════════════════════════

def db_get(key: str) -> str:
    """Sozlama qiymatini olish"""
    conn = get_db()
    row = conn.execute("SELECT val FROM settings WHERE key_name=?", (key,)).fetchone()
    conn.close()
    return row["val"] if row else ""

def db_set(key: str, val: str):
    """Sozlama qiymatini o'zgartirish"""
    conn = get_db()
    conn.execute("INSERT OR REPLACE INTO settings (key_name, val) VALUES (?,?)", (key, val))
    conn.commit()
    conn.close()

def is_admin(user_id: int) -> bool:
    if user_id == ADMIN_ID:
        return True
    conn = get_db()
    row = conn.execute("SELECT 1 FROM admins WHERE user_id=?", (str(user_id),)).fetchone()
    conn.close()
    return row is not None

def get_admins_list() -> list:
    conn = get_db()
    rows = conn.execute("SELECT user_id FROM admins").fetchall()
    conn.close()
    return [int(r["user_id"]) for r in rows] + [ADMIN_ID]

def get_user(user_id) -> Optional[dict]:
    conn = get_db()
    row = conn.execute("SELECT * FROM user_id WHERE user_id=?", (str(user_id),)).fetchone()
    conn.close()
    return dict(row) if row else None

def get_kabinet(user_id) -> Optional[dict]:
    conn = get_db()
    row = conn.execute("SELECT * FROM kabinet WHERE user_id=?", (str(user_id),)).fetchone()
    conn.close()
    return dict(row) if row else None

def get_status_row(user_id) -> Optional[dict]:
    conn = get_db()
    row = conn.execute("SELECT * FROM status WHERE user_id=?", (str(user_id),)).fetchone()
    conn.close()
    return dict(row) if row else None

def register_user(user_id, refid=None):
    """Foydalanuvchini ro'yxatga olish"""
    sana = datetime.now().strftime("%H:%M %d.%m.%Y")
    conn = get_db()
    try:
        conn.execute(
            "INSERT OR IGNORE INTO user_id (user_id, status, refid, sana) VALUES (?,?,?,?)",
            (str(user_id), "Oddiy", str(refid) if refid else None, sana)
        )
        conn.execute(
            "INSERT OR IGNORE INTO kabinet (user_id, pul, pul2, odam, ban) VALUES (?,0,0,0,'unban')",
            (str(user_id),)
        )
        conn.execute(
            "INSERT OR IGNORE INTO status (user_id, kun, date) VALUES (?,0,?)",
            (str(user_id), sana)
        )
        # Taklif bergan odamning odam sonini oshirish
        if refid:
            conn.execute(
                "UPDATE kabinet SET odam = odam + 1 WHERE user_id=?",
                (str(refid),)
            )
        conn.commit()
    finally:
        conn.close()

def is_banned(user_id) -> bool:
    k = get_kabinet(user_id)
    return k and k.get("ban") == "ban"

def get_user_status(user_id) -> str:
    """VIP yoki Oddiy"""
    row = get_status_row(user_id)
    if row and row.get("kun", 0) > 0:
        return "VIP"
    return "Oddiy"

def get_all_users() -> list:
    conn = get_db()
    rows = conn.execute("SELECT user_id FROM user_id").fetchall()
    conn.close()
    return [int(r["user_id"]) for r in rows]

def count_users() -> dict:
    conn = get_db()
    total   = conn.execute("SELECT COUNT(*) as c FROM user_id").fetchone()["c"]
    vip     = conn.execute("SELECT COUNT(*) as c FROM status WHERE kun > 0").fetchone()["c"]
    banned  = conn.execute("SELECT COUNT(*) as c FROM kabinet WHERE ban='ban'").fetchone()["c"]
    animes  = conn.execute("SELECT COUNT(*) as c FROM animelar").fetchone()["c"]
    conn.close()
    return {"total": total, "vip": vip, "banned": banned, "animes": animes}

# ── Anime ──
def get_anime_by_id(aid) -> Optional[dict]:
    conn = get_db()
    row = conn.execute("SELECT * FROM animelar WHERE id=?", (int(aid),)).fetchone()
    conn.close()
    return dict(row) if row else None

def search_anime_by_name(query: str) -> list:
    conn = get_db()
    rows = conn.execute(
        "SELECT * FROM animelar WHERE nom LIKE ? LIMIT 10",
        (f"%{query}%",)
    ).fetchall()
    conn.close()
    return [dict(r) for r in rows]

def get_episodes(anime_id) -> list:
    conn = get_db()
    rows = conn.execute(
        "SELECT * FROM anime_datas WHERE id=? ORDER BY qism ASC",
        (str(anime_id),)
    ).fetchall()
    conn.close()
    return [dict(r) for r in rows]

def get_episode(anime_id, qism) -> Optional[dict]:
    conn = get_db()
    row = conn.execute(
        "SELECT * FROM anime_datas WHERE id=? AND qism=?",
        (str(anime_id), int(qism))
    ).fetchone()
    conn.close()
    return dict(row) if row else None

def increment_views(anime_id):
    conn = get_db()
    conn.execute("UPDATE animelar SET qidiruv = qidiruv + 1 WHERE id=?", (int(anime_id),))
    conn.commit()
    conn.close()

def get_latest_animes(limit=10) -> list:
    conn = get_db()
    rows = conn.execute("SELECT * FROM animelar ORDER BY id DESC LIMIT ?", (limit,)).fetchall()
    conn.close()
    return [dict(r) for r in rows]

def get_top_animes(limit=10) -> list:
    conn = get_db()
    rows = conn.execute("SELECT * FROM animelar ORDER BY qidiruv DESC LIMIT ?", (limit,)).fetchall()
    conn.close()
    return [dict(r) for r in rows]

def get_all_animes() -> list:
    conn = get_db()
    rows = conn.execute("SELECT * FROM animelar ORDER BY id DESC").fetchall()
    conn.close()
    return [dict(r) for r in rows]

# ── Kanallar (majburiy obuna) ──
def get_channels() -> list:
    conn = get_db()
    rows = conn.execute("SELECT * FROM channels").fetchall()
    conn.close()
    return [dict(r) for r in rows]

# ── Anime kanallar (post uchun) ──
def get_anime_kanallar() -> list:
    conn = get_db()
    rows = conn.execute("SELECT channel_id FROM anime_kanallar").fetchall()
    conn.close()
    return [r["channel_id"] for r in rows]

# ════════════════════════════════════════════════════════════════
#                    📋 FSM HOLATLARI
# ════════════════════════════════════════════════════════════════

class S(StatesGroup):
    # Qidiruv
    search_name   = State()
    search_code   = State()
    search_genre  = State()

    # Anime qo'shish
    anime_name    = State()
    anime_qismi   = State()
    anime_country = State()
    anime_lang    = State()
    anime_year    = State()
    anime_genre   = State()
    anime_fandub  = State()
    anime_picture = State()

    # Qism qo'shish
    ep_code       = State()
    ep_video      = State()

    # Tahrirlash
    edit_code     = State()
    edit_field    = State()
    edit_ep_code  = State()
    edit_ep_num   = State()
    edit_ep_field = State()

    # Foydalanuvchi boshqarish
    user_id_input = State()
    add_balance   = State()
    sub_balance   = State()

    # Admin qo'shish/o'chirish
    add_admin     = State()
    remove_admin  = State()

    # Broadcast
    broadcast     = State()

    # Sozlamalar
    set_valyuta   = State()
    set_vip_narx  = State()
    set_studio    = State()
    set_start_txt = State()
    set_qollanma  = State()
    set_homiy     = State()

    # Tugma nomlari
    set_key       = State()

    # Majburiy obuna kanal qo'shish
    ch_add_id     = State()
    ch_add_link   = State()
    ch_add_type   = State()

    # Anime kanal
    anime_ch_add  = State()

    # Post tayyorlash
    post_code     = State()


# ════════════════════════════════════════════════════════════════
#                    ⌨️  KLAVIATURALAR
# ════════════════════════════════════════════════════════════════

def main_menu(user_id: int) -> ReplyKeyboardMarkup:
    k1 = db_get("key1"); k2 = db_get("key2")
    k3 = db_get("key3"); k4 = db_get("key4")
    k5 = db_get("key5"); k6 = db_get("key6")
    rows = [
        [KeyboardButton(text=k1)],
        [KeyboardButton(text=k2), KeyboardButton(text=k3)],
        [KeyboardButton(text=k4), KeyboardButton(text=k5)],
        [KeyboardButton(text=k6)],
    ]
    if is_admin(user_id):
        rows.append([KeyboardButton(text="🗄 Boshqarish")])
    return ReplyKeyboardMarkup(keyboard=rows, resize_keyboard=True)

def back_kb() -> ReplyKeyboardMarkup:
    return ReplyKeyboardMarkup(
        keyboard=[[KeyboardButton(text="◀️ Orqaga")]],
        resize_keyboard=True
    )

def manage_kb() -> ReplyKeyboardMarkup:
    return ReplyKeyboardMarkup(
        keyboard=[[KeyboardButton(text="🗄 Boshqarish")]],
        resize_keyboard=True
    )

def admin_panel_kb() -> ReplyKeyboardMarkup:
    return ReplyKeyboardMarkup(
        keyboard=[
            [KeyboardButton(text="*️⃣ Birlamchi sozlamalar")],
            [KeyboardButton(text="📊 Statistika"), KeyboardButton(text="✉ Xabar Yuborish")],
            [KeyboardButton(text="📬 Post tayyorlash")],
            [KeyboardButton(text="🎥 Animelar sozlash"), KeyboardButton(text="💳 Hamyonlar")],
            [KeyboardButton(text="🔎 Foydalanuvchini boshqarish")],
            [KeyboardButton(text="📢 Kanallar"), KeyboardButton(text="📃 Matnlar")],
            [KeyboardButton(text="📋 Adminlar"), KeyboardButton(text="🤖 Bot holati")],
            [KeyboardButton(text="◀️ Orqaga")],
        ],
        resize_keyboard=True
    )

def sub_keyboard(channels: list, key: str = "") -> InlineKeyboardMarkup:
    """Majburiy obuna klaviaturasi"""
    btns = []
    for ch in channels:
        if ch["channelType"] == "request":
            btns.append([InlineKeyboardButton(
                text=f"📨 So'rov yuborish",
                url=ch["channelLink"]
            )])
        else:
            btns.append([InlineKeyboardButton(
                text=f"📢 Kanalga o'tish",
                url=ch["channelLink"]
            )])
    cb = f"chack={key}" if key else "panel"
    btns.append([InlineKeyboardButton(text="✅ Tekshirish", callback_data=cb)])
    return InlineKeyboardMarkup(inline_keyboard=btns)


# ════════════════════════════════════════════════════════════════
#                    🔍 OBUNA TEKSHIRISH
# ════════════════════════════════════════════════════════════════

async def check_sub(bot: Bot, user_id: int) -> bool:
    """Foydalanuvchi barcha kanallarga obuna bo'lganligini tekshirish"""
    if is_admin(user_id):
        return True
    if get_user_status(user_id) == "VIP":
        return True

    channels = get_channels()
    if not channels:
        return True

    conn = get_db()
    for ch in channels:
        if ch["channelType"] == "request":
            row = conn.execute(
                "SELECT 1 FROM joinRequests WHERE channelId=? AND userId=?",
                (ch["channelId"], str(user_id))
            ).fetchone()
            if not row:
                conn.close()
                return False
        else:
            try:
                member = await bot.get_chat_member(ch["channelId"], user_id)
                if member.status in ("left", "kicked"):
                    conn.close()
                    return False
            except Exception:
                conn.close()
                return False
    conn.close()
    return True

async def require_sub(bot: Bot, message: types.Message, key: str = "") -> bool:
    """Obuna bo'lmasa xabar yuborish va False qaytarish"""
    if await check_sub(bot, message.from_user.id):
        return True
    channels = get_channels()
    await message.answer(
        "<b>Botdan foydalanish uchun quyidagi kanallarga obuna bo'ling yoki so'rov yuboring❗️</b>",
        parse_mode="HTML",
        reply_markup=sub_keyboard(channels, key)
    )
    return False


# ════════════════════════════════════════════════════════════════
#               🎬 ANIME YUBORISH YORDAMCHI FUNKSIYA
# ════════════════════════════════════════════════════════════════

def build_anime_caption(rew: dict, kanal_list: list) -> str:
    kanal_str = " ".join(kanal_list) if kanal_list else ""
    return (
        f"<b>🎬 Nomi: {rew['nom']}</b>\n\n"
        f"🎥 Qismi: {rew['qismi']}\n"
        f"🌍 Davlati: {rew['davlat']}\n"
        f"🇺🇿 Tili: {rew['tili']}\n"
        f"📆 Yili: {rew['yili']}\n"
        f"🎞 Janri: {rew['janri']}\n\n"
        f"🔍 Qidirishlar soni: {rew['qidiruv']}\n\n"
        f"🍿 {kanal_str}"
    )

async def send_anime(bot: Bot, chat_id: int, rew: dict, protect=False):
    """Animeni foydalanuvchiga yuborish"""
    kanal_list = get_anime_kanallar()
    caption = build_anime_caption(rew, kanal_list)
    protect_content = (db_get("content") == "true")

    kb = InlineKeyboardMarkup(inline_keyboard=[
        [InlineKeyboardButton(
            text="📥 YUKLAB OLISH",
            callback_data=f"yuklanolish={rew['id']}=1"
        )]
    ])

    file_id = rew["rams"]
    # PHP kodida: file_id[0] == 'B' → video, aks holda photo
    if file_id and file_id[0].upper() == "B":
        await bot.send_video(
            chat_id, file_id,
            caption=caption, parse_mode="HTML",
            reply_markup=kb,
            protect_content=protect_content
        )
    else:
        await bot.send_photo(
            chat_id, file_id,
            caption=caption, parse_mode="HTML",
            reply_markup=kb,
            protect_content=protect_content
        )

async def send_anime_post(bot: Bot, chat_id, rew: dict):
    """Kanalga post yuborish (tomosha qilish tugmasi bilan)"""
    bot_info = await bot.get_me()
    btn_url = f"https://t.me/{bot_info.username}?start={rew['id']}"
    caption = (
        f"<b>✽ ──...──:•°⛩°•:──...──╮\n"
        f"🏷️ Anime nomi: </b>{rew['nom']}\n"
        f"<b>🖋️ Janri:</b> {rew['janri']}\n"
        f"<b>🎞️ Qismlar soni:</b> {rew['qismi']}\n"
        f"<b>🎙️ Ovoz berdi:</b> {rew['aniType']}\n"
        f"<b>💭 Tili:</b> {rew['tili']}"
    )
    kb = InlineKeyboardMarkup(inline_keyboard=[
        [InlineKeyboardButton(text="🔹 Tomosha qilish 🔹", url=btn_url)]
    ])
    file_id = rew["rams"]
    if file_id and file_id[0].upper() == "B":
        await bot.send_video(chat_id, file_id, caption=caption, parse_mode="HTML", reply_markup=kb)
    else:
        await bot.send_photo(chat_id, file_id, caption=caption, parse_mode="HTML", reply_markup=kb)


# ════════════════════════════════════════════════════════════════
#                    🤖 BOT VA DISPATCHER
# ════════════════════════════════════════════════════════════════

bot = Bot(token=BOT_TOKEN)
dp  = Dispatcher(storage=MemoryStorage())

# Vaqtinchalik ma'lumot saqlash
_tmp = {}   # {user_id: {...}}

def tmp_set(uid, key, val):
    _tmp.setdefault(uid, {})[key] = val

def tmp_get(uid, key, default=None):
    return _tmp.get(uid, {}).get(key, default)


# ════════════════════════════════════════════════════════════════
#                    🏠 /START
# ════════════════════════════════════════════════════════════════

@dp.message(CommandStart())
async def cmd_start(message: types.Message, state: FSMContext):
    await state.clear()
    uid = message.from_user.id
    text = message.text or ""

    # Referal
    refid = None
    parts = text.split()
    if len(parts) > 1 and parts[1].startswith("ref_"):
        try:
            refid = int(parts[1].replace("ref_", ""))
            if refid == uid:
                refid = None
        except ValueError:
            refid = None

    is_new = get_user(uid) is None
    register_user(uid, refid)

    if is_new and refid:
        try:
            valyuta = db_get("valyuta")
            await bot.send_message(refid, f"👤 Do'stingiz botga qo'shildi! +5 ball.")
        except Exception:
            pass

    # Raqamli start (anime kodi)
    if len(parts) > 1 and parts[1].isdigit():
        if not await require_sub(bot, message, parts[1]):
            return
        rew = get_anime_by_id(parts[1])
        if rew:
            increment_views(rew["id"])
            await send_anime(bot, uid, rew)
        else:
            await message.answer("❌ Ma'lumot topilmadi.")
        return

    if is_banned(uid):
        await message.answer("⛔️ Siz ban qilingansiz!")
        return

    if db_get("bot_holat") == "O'chirilgan" and not is_admin(uid):
        await message.answer("⛔️ <b>Bot vaqtinchalik o'chirilgan!</b>", parse_mode="HTML")
        return

    start_text = db_get("start_text")
    await message.answer(
        start_text or "✨ Botga xush kelibsiz!",
        parse_mode="HTML",
        reply_markup=main_menu(uid)
    )

# ════════════════════════════════════════════════════════════════
#                 ✅ OBUNA TEKSHIRISH CALLBACK
# ════════════════════════════════════════════════════════════════

@dp.callback_query(F.data.startswith("chack="))
async def cb_check_sub(call: CallbackQuery):
    uid = call.from_user.id
    anime_id = call.data.replace("chack=", "")

    # Progress ko'rsatish
    bars = ["░░░░░░", "█░░░░░", "██░░░░", "███░░░", "████░░", "█████░", "██████"]
    msg = await call.message.edit_text("⏳ <b>Tekshirilmoqda... 0%</b>", parse_mode="HTML")
    for i, bar in enumerate(bars):
        try:
            await call.message.bot.edit_message_text(
                f"⏳ <b>Tekshirilmoqda... {i*15}%\n{bar}</b>",
                chat_id=call.message.chat.id,
                message_id=msg.message_id,
                parse_mode="HTML"
            )
        except Exception:
            pass
        await asyncio.sleep(0.3)

    try:
        await call.message.bot.delete_message(call.message.chat.id, msg.message_id)
    except Exception:
        pass

    if await check_sub(call.message.bot, uid):
        rew = get_anime_by_id(anime_id)
        if rew:
            increment_views(rew["id"])
            await send_anime(call.message.bot, uid, rew)
        else:
            await call.message.answer("❌ Ma'lumot topilmadi.")
    else:
        channels = get_channels()
        await call.message.answer(
            "⚠ Obuna aniqlanmadi. Iltimos, kanallarga obuna bo'ling va qayta urinib ko'ring.",
            reply_markup=sub_keyboard(channels, anime_id)
        )

@dp.callback_query(F.data == "panel")
async def cb_panel(call: CallbackQuery):
    if await check_sub(call.message.bot, call.from_user.id):
        await call.message.edit_text("✅ Obuna tasdiqlandi!")
        await call.message.answer(
            "✨ Botdan foydalanishingiz mumkin!",
            reply_markup=main_menu(call.from_user.id)
        )
    else:
        await call.answer("❌ Hali obuna bo'lmadingiz!", show_alert=True)

# ════════════════════════════════════════════════════════════════
#              🔎 ANIME IZLASH (key1 tugmasi)
# ════════════════════════════════════════════════════════════════

@dp.message(F.text.func(lambda t: t == db_get("key1")))
async def key1_handler(message: types.Message):
    uid = message.from_user.id
    if is_banned(uid): return
    if not await require_sub(bot, message):
        return

    await message.answer(
        "<b>🔍 Qidiruv tipini tanlang:</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [
                InlineKeyboardButton(text="🏷 Anime nomi orqali", callback_data="searchByName"),
                InlineKeyboardButton(text="⏱ So'ngi yuklanganlar", callback_data="lastUploads"),
            ],
            [InlineKeyboardButton(text="💬 Janr orqali qidirish", callback_data="searchByGenre")],
            [
                InlineKeyboardButton(text="📌 Kod orqali", callback_data="searchByCode"),
                InlineKeyboardButton(text="👁️ Eng ko'p ko'rilgan", callback_data="topViewers"),
            ],
            [InlineKeyboardButton(text="📚 Barcha animelar", callback_data="allAnimes")],
        ])
    )

@dp.callback_query(F.data == "searchByName")
async def cb_search_name(call: CallbackQuery, state: FSMContext):
    await state.set_state(S.search_name)
    await call.message.answer("<b>Anime nomini yuboring:</b>", parse_mode="HTML", reply_markup=back_kb())
    await call.answer()

@dp.message(S.search_name)
async def process_search_name(message: types.Message, state: FSMContext):
    if message.text == "◀️ Orqaga":
        await state.clear()
        await message.answer("◀️", reply_markup=main_menu(message.from_user.id))
        return
    results = search_anime_by_name(message.text)
    await state.clear()
    if not results:
        await message.answer(f"🙁 Natija mavjud emas!", reply_markup=main_menu(message.from_user.id))
        return
    btns = [[InlineKeyboardButton(text=f"{i+1}. {a['nom']}", callback_data=f"loadAnime={a['id']}")]
            for i, a in enumerate(results)]
    await message.answer(
        "<b>⬇️ Qidiruv natijalari:</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=btns)
    )

@dp.callback_query(F.data == "searchByCode")
async def cb_search_code(call: CallbackQuery, state: FSMContext):
    await state.set_state(S.search_code)
    await call.message.answer("<b>📌 Anime kodini kiriting:</b>", parse_mode="HTML", reply_markup=back_kb())
    await call.answer()

@dp.message(S.search_code)
async def process_search_code(message: types.Message, state: FSMContext):
    if message.text == "◀️ Orqaga":
        await state.clear()
        await message.answer("◀️", reply_markup=main_menu(message.from_user.id))
        return
    await state.clear()
    rew = get_anime_by_id(message.text.strip())
    if rew:
        increment_views(rew["id"])
        await send_anime(bot, message.from_user.id, rew)
    else:
        await message.answer(
            f"<b>[ {message.text} ] kodiga tegishli anime topilmadi😔\n\n• Boshqa Kod yuboring</b>",
            parse_mode="HTML"
        )

@dp.callback_query(F.data == "searchByGenre")
async def cb_search_genre(call: CallbackQuery, state: FSMContext):
    if get_user_status(call.from_user.id) != "VIP" and not is_admin(call.from_user.id):
        key2 = db_get("key2")
        await call.answer(
            f"Ushbu funksiyadan foydalanish uchun {key2} sotib olishingiz zarur!",
            show_alert=True
        )
        return
    await state.set_state(S.search_genre)
    await call.message.answer(
        "<b>🔍 Qidirish uchun anime janrini yuboring.</b>\n📌 Namuna: Syonen",
        parse_mode="HTML",
        reply_markup=back_kb()
    )
    await call.answer()

@dp.message(S.search_genre)
async def process_search_genre(message: types.Message, state: FSMContext):
    if message.text == "◀️ Orqaga":
        await state.clear()
        await message.answer("◀️", reply_markup=main_menu(message.from_user.id))
        return
    conn = get_db()
    rows = conn.execute("SELECT * FROM animelar WHERE janri LIKE ? LIMIT 10", (f"%{message.text}%",)).fetchall()
    conn.close()
    await state.clear()
    if not rows:
        await message.answer(
            f"<b>[ {message.text} ] janriga tegishli anime topilmadi😔\n\n• Boshqa janrni alohida yuboring</b>",
            parse_mode="HTML"
        )
        return
    btns = [[InlineKeyboardButton(text=f"{i+1}. {r['nom']}", callback_data=f"loadAnime={r['id']}")]
            for i, r in enumerate(rows)]
    await message.answer(
        "<b>⬇️ Qidiruv natijalari:</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=btns)
    )

@dp.callback_query(F.data == "lastUploads")
async def cb_last_uploads(call: CallbackQuery):
    if get_user_status(call.from_user.id) != "VIP" and not is_admin(call.from_user.id):
        key2 = db_get("key2")
        await call.answer(f"Ushbu funksiyadan foydalanish uchun {key2} sotib olishingiz zarur!", show_alert=True)
        return
    animes = get_latest_animes(10)
    btns = [[InlineKeyboardButton(text=f"{i+1} - {a['nom']}", callback_data=f"loadAnime={a['id']}")]
            for i, a in enumerate(animes)]
    await call.message.edit_text(
        "<b>⬇️ So'nggi yuklanganlar:</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=btns)
    )

@dp.callback_query(F.data == "topViewers")
async def cb_top_viewers(call: CallbackQuery):
    if get_user_status(call.from_user.id) != "VIP" and not is_admin(call.from_user.id):
        key2 = db_get("key2")
        await call.answer(f"Ushbu funksiyadan foydalanish uchun {key2} sotib olishingiz zarur!", show_alert=True)
        return
    animes = get_top_animes(10)
    btns = [[InlineKeyboardButton(text=f"{i+1} - {a['nom']}", callback_data=f"loadAnime={a['id']}")]
            for i, a in enumerate(animes)]
    await call.message.edit_text(
        "<b>⬇️ Eng ko'p ko'rilganlar:</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=btns)
    )

@dp.callback_query(F.data == "allAnimes")
async def cb_all_animes(call: CallbackQuery):
    animes = get_all_animes()
    bot_info = await bot.get_me()
    text = (
        f"{bot_info.username} anime botida mavjud bo'lgan barcha animelar ro'yxati\n"
        f"Barcha animelar soni : {len(animes)} ta\n\n"
    )
    for i, a in enumerate(animes, 1):
        text += f"---- | {i} | ----\nAnime kodi : {a['id']}\nNomi : {a['nom']}\nJanri : {a['janri']}\n\n"

    import io
    buf = io.BytesIO(text.encode("utf-8"))
    buf.name = "animes_list.txt"
    await call.message.answer_document(
        types.BufferedInputFile(buf.getvalue(), filename="animes_list.txt"),
        caption=f"<b>📝 {bot_info.username} Anime botida mavjud bo'lgan {len(animes)} ta animening ro'yxati</b>",
        parse_mode="HTML"
    )
    await call.answer()

# ── loadAnime callback ──
@dp.callback_query(F.data.startswith("loadAnime="))
async def cb_load_anime(call: CallbackQuery):
    uid = call.from_user.id
    n = call.data.replace("loadAnime=", "")
    rew = get_anime_by_id(n)
    if not rew:
        await call.answer("❌ Ma'lumot topilmadi.", show_alert=True)
        return

    await call.message.delete()
    increment_views(rew["id"])

    file_id = rew["rams"]
    kanal_list = get_anime_kanallar()
    caption = build_anime_caption(rew, kanal_list)
    protect_content = (db_get("content") == "true")

    btns = [[InlineKeyboardButton(text="YUKLAB OLISH 📥", callback_data=f"yuklanolish={n}=1")]]
    if is_admin(uid):
        btns.append([InlineKeyboardButton(text="🗑️ O'chirish", callback_data=f"deleteAnime={n}=1")])
    kb = InlineKeyboardMarkup(inline_keyboard=btns)

    if file_id and file_id[0].upper() == "B":
        await call.message.answer_video(file_id, caption=caption, parse_mode="HTML",
                                        reply_markup=kb, protect_content=protect_content)
    else:
        await call.message.answer_photo(file_id, caption=caption, parse_mode="HTML",
                                        reply_markup=kb, protect_content=protect_content)

# ── deleteAnime callback ──
@dp.callback_query(F.data.startswith("deleteAnime="))
async def cb_delete_anime(call: CallbackQuery):
    if not is_admin(call.from_user.id):
        return
    parts = call.data.split("=")
    n, res = parts[1], parts[2]
    if res == "1":
        await call.message.edit_caption(
            caption="<b>❗O'chirishga ishonchingiz komilmi?</b>",
            parse_mode="HTML",
            reply_markup=InlineKeyboardMarkup(inline_keyboard=[
                [InlineKeyboardButton(text="✅ Tasdiqlash", callback_data=f"deleteAnime={n}=2")],
                [InlineKeyboardButton(text="🔙 Orqaga", callback_data=f"yuklanolish={n}=1")],
            ])
        )
    elif res == "2":
        conn = get_db()
        conn.execute("DELETE FROM animelar WHERE id=?", (int(n),))
        conn.execute("DELETE FROM anime_datas WHERE id=?", (str(n),))
        conn.commit()
        conn.close()
        await call.message.delete()
        await call.message.answer("Anime o'chirildi!")

# ════════════════════════════════════════════════════════════════
#               📥 YUKLAB OLISH (qismlar)
# ════════════════════════════════════════════════════════════════

@dp.callback_query(F.data.startswith("yuklanolish="))
async def cb_yuklab_olish(call: CallbackQuery):
    parts = call.data.split("=")
    anime_id = int(parts[1])
    ep_num   = int(parts[2]) if len(parts) > 2 else 1

    rew = get_anime_by_id(anime_id)
    if not rew:
        await call.answer("❌ Anime topilmadi", show_alert=True)
        return

    ep = get_episode(anime_id, ep_num)
    if not ep:
        await call.answer("❌ Qism topilmadi", show_alert=True)
        return

    # Qismlar tugmalari (25 ta sahifalash)
    offset = ((ep_num - 1) // 25) * 25
    conn = get_db()
    eps = conn.execute(
        "SELECT * FROM anime_datas WHERE id=? ORDER BY qism ASC LIMIT ? OFFSET ?",
        (str(anime_id), 25, offset)
    ).fetchall()
    conn.close()

    btns = []
    row = []
    for e in eps:
        q = e["qism"]
        if q == ep_num:
            row.append(InlineKeyboardButton(text=f"[📀] - {q}", callback_data="null"))
        else:
            row.append(InlineKeyboardButton(text=str(q), callback_data=f"yuklanolish={anime_id}={q}"))
        if len(row) == 4:
            btns.append(row)
            row = []
    if row:
        btns.append(row)

    if is_admin(call.from_user.id):
        btns.append([InlineKeyboardButton(
            text=f"🗑 {ep_num}-qismni o'chirish",
            callback_data=f"deleteEpisode={anime_id}={ep_num}=1"
        )])

    btns.append([
        InlineKeyboardButton(text="⬅️ Oldingi", callback_data=f"pagenation={anime_id}={ep_num}=back"),
        InlineKeyboardButton(text="❌ Yopish",  callback_data="close"),
        InlineKeyboardButton(text="➡️ Keyingi",  callback_data=f"pagenation={anime_id}={ep_num}=next"),
    ])
    kb = InlineKeyboardMarkup(inline_keyboard=btns)

    protect_content = (db_get("content") == "true")
    await call.message.delete()
    await call.message.answer_video(
        ep["file_id"],
        caption=f"<b>{rew['nom']}</b>\n\n{ep_num}-qism",
        parse_mode="HTML",
        reply_markup=kb,
        protect_content=protect_content
    )

@dp.callback_query(F.data == "null")
async def cb_null(call: CallbackQuery):
    await call.answer()

@dp.callback_query(F.data == "close")
async def cb_close(call: CallbackQuery):
    await call.message.delete()

@dp.callback_query(F.data.startswith("pagenation="))
async def cb_pagenation(call: CallbackQuery):
    parts  = call.data.split("=")
    anime_id = int(parts[1])
    cur_ep   = int(parts[2])
    action   = parts[3]

    cur_page = ((cur_ep - 1) // 25) + 1
    start_from = (cur_page - 1) * 25
    if action == "back":
        start_from = max(start_from - 25, 0)
    elif action == "next":
        start_from += 25

    conn = get_db()
    eps = conn.execute(
        "SELECT * FROM anime_datas WHERE id=? ORDER BY qism ASC LIMIT 25 OFFSET ?",
        (str(anime_id), start_from)
    ).fetchall()
    conn.close()

    if not eps:
        await call.answer("💔 Qismlar topilmadi.", show_alert=True)
        return

    rew = get_anime_by_id(anime_id)
    btns = []
    row = []
    for e in eps:
        q = e["qism"]
        if q == cur_ep:
            row.append(InlineKeyboardButton(text=f"[📀] - {q}", callback_data="null"))
        else:
            row.append(InlineKeyboardButton(text=str(q), callback_data=f"yuklanolish={anime_id}={q}"))
        if len(row) == 4:
            btns.append(row)
            row = []
    if row:
        btns.append(row)

    btns.append([
        InlineKeyboardButton(text="⬅️ Oldingi", callback_data=f"pagenation={anime_id}={cur_ep}=back"),
        InlineKeyboardButton(text="❌ Yopish",  callback_data="close"),
        InlineKeyboardButton(text="➡️ Keyingi",  callback_data=f"pagenation={anime_id}={cur_ep}=next"),
    ])
    kb = InlineKeyboardMarkup(inline_keyboard=btns)
    first_ep = eps[0]
    protect_content = (db_get("content") == "true")

    await call.message.delete()
    await call.message.answer_video(
        first_ep["file_id"],
        caption=f"<b>{rew['nom']}</b>\n\n{first_ep['qism']}-qism",
        parse_mode="HTML",
        reply_markup=kb,
        protect_content=protect_content
    )

@dp.callback_query(F.data.startswith("deleteEpisode="))
async def cb_delete_episode(call: CallbackQuery):
    if not is_admin(call.from_user.id):
        return
    parts = call.data.split("=")
    anime_id, ep_num, step = parts[1], parts[2], parts[3]
    if step == "1":
        await call.message.edit_caption(
            caption=f"❗ {ep_num}-qismni o'chirishni tasdiqlaysizmi?",
            reply_markup=InlineKeyboardMarkup(inline_keyboard=[
                [InlineKeyboardButton(text="✅ Ha", callback_data=f"deleteEpisode={anime_id}={ep_num}=2")],
                [InlineKeyboardButton(text="❌ Yo'q", callback_data=f"yuklanolish={anime_id}={ep_num}")],
            ])
        )
    elif step == "2":
        conn = get_db()
        conn.execute("DELETE FROM anime_datas WHERE id=? AND qism=?", (str(anime_id), int(ep_num)))
        conn.commit()
        conn.close()
        await call.message.delete()
        await call.message.answer(f"✅ {ep_num}-qism o'chirildi!")


# ════════════════════════════════════════════════════════════════
#                    💎 VIP TUGMASI (key2)
# ════════════════════════════════════════════════════════════════

@dp.message(F.text.func(lambda t: t == db_get("key2")))
async def key2_vip(message: types.Message):
    uid = message.from_user.id
    if is_banned(uid): return
    if not await require_sub(bot, message): return

    narx = db_get("vip_narx"); valyuta = db_get("valyuta")
    status = get_user_status(uid)

    if status == "Oddiy":
        key2 = db_get("key2")
        await message.answer(
            f"<b>{key2}'ga ulanish\n\n"
            f"{key2}da qanday imkoniyatlar bor?\n"
            "• VIP kanal uchun 1martalik havola beriladi\n"
            "• Hech qanday reklamalarsiz botdan foydalanasiz\n"
            "• Majburiy obunalik so'ralmaydi</b>",
            parse_mode="HTML",
            reply_markup=InlineKeyboardMarkup(inline_keyboard=[
                [InlineKeyboardButton(text=f"30 kun - {narx} {valyuta}", callback_data="shop=30")],
                [InlineKeyboardButton(text=f"60 kun - {int(narx)*2} {valyuta}", callback_data="shop=60")],
                [InlineKeyboardButton(text=f"90 kun - {int(narx)*3} {valyuta}", callback_data="shop=90")],
            ])
        )
    else:
        row = get_status_row(uid)
        await message.answer(
            f"<b>Siz {db_get('key2')} sotib olgansiz!\n\n"
            f"⏳ Qolgan kun: {row['kun']}</b>",
            parse_mode="HTML",
            reply_markup=InlineKeyboardMarkup(inline_keyboard=[
                [InlineKeyboardButton(text="🗓️ Uzaytirish", callback_data="uzaytirish")]
            ])
        )

@dp.callback_query(F.data == "uzaytirish")
async def cb_uzaytirish(call: CallbackQuery):
    narx = db_get("vip_narx"); valyuta = db_get("valyuta")
    await call.message.edit_text(
        "<b>❗ Obunani necha kunga uzaytirmoqchisiz?</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text=f"30 kun - {narx} {valyuta}", callback_data="shop=30")],
            [InlineKeyboardButton(text=f"60 kun - {int(narx)*2} {valyuta}", callback_data="shop=60")],
            [InlineKeyboardButton(text=f"90 kun - {int(narx)*3} {valyuta}", callback_data="shop=90")],
        ])
    )

@dp.callback_query(F.data.startswith("shop="))
async def cb_shop(call: CallbackQuery):
    kun = int(call.data.replace("shop=", ""))
    narx = db_get("vip_narx"); valyuta = db_get("valyuta")
    jami = int(narx) * (kun // 30)
    await call.message.edit_text(
        f"<b>💳 To'lov\n\n"
        f"Muddat: {kun} kun\n"
        f"Narx: {jami} {valyuta}\n\n"
        f"To'lov uchun admin bilan bog'laning:</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="☎️ Administrator", url=f"tg://user?id={ADMIN_ID}")]
        ])
    )

# ════════════════════════════════════════════════════════════════
#                  💰 HISOBIM (key3)
# ════════════════════════════════════════════════════════════════

@dp.message(F.text.func(lambda t: t == db_get("key3")))
async def key3_hisob(message: types.Message):
    uid = message.from_user.id
    if is_banned(uid): return
    if not await require_sub(bot, message): return

    k = get_kabinet(uid)
    valyuta = db_get("valyuta")
    pul = k["pul"] if k else 0
    odam = k["odam"] if k else 0
    await message.answer(
        f"<b>💰 Sizning hisobingiz\n\n"
        f"💵 Balans: {pul} {valyuta}\n"
        f"👥 Takliflar: {odam} ta</b>",
        parse_mode="HTML"
    )

# ════════════════════════════════════════════════════════════════
#                📚 QO'LLANMA (key5)
# ════════════════════════════════════════════════════════════════

@dp.message(F.text.func(lambda t: t == db_get("key5")))
async def key5_qollanma(message: types.Message):
    uid = message.from_user.id
    if is_banned(uid): return
    if not await require_sub(bot, message): return
    qollanma = db_get("qollanma")
    if not qollanma:
        await message.answer("<b>🙁 Qo'llanma qo'shilmagan!</b>", parse_mode="HTML")
    else:
        await message.answer(qollanma, parse_mode="HTML")

# ════════════════════════════════════════════════════════════════
#              💵 REKLAMA VA HOMIYLIK (key6)
# ════════════════════════════════════════════════════════════════

@dp.message(F.text.func(lambda t: t == db_get("key6")))
async def key6_homiy(message: types.Message):
    uid = message.from_user.id
    if is_banned(uid): return
    if not await require_sub(bot, message): return
    homiy = db_get("homiy")
    if not homiy:
        await message.answer("<b>🙁 Homiylik qo'shilmagan!</b>", parse_mode="HTML")
    else:
        await message.answer(
            homiy, parse_mode="HTML",
            reply_markup=InlineKeyboardMarkup(inline_keyboard=[
                [InlineKeyboardButton(text="☎️ Administrator", url=f"tg://user?id={ADMIN_ID}")]
            ])
        )

# ════════════════════════════════════════════════════════════════
#                    👑 ADMIN PANEL
# ════════════════════════════════════════════════════════════════

@dp.message(F.text.in_({"🗄 Boshqarish", "/panel"}))
async def admin_panel_entry(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id):
        return
    await state.clear()
    await message.answer(
        "<b>Admin paneliga xush kelibsiz!</b>",
        parse_mode="HTML",
        reply_markup=admin_panel_kb()
    )

@dp.message(F.text == "◀️ Orqaga")
async def back_to_main(message: types.Message, state: FSMContext):
    await state.clear()
    await message.answer("🏠 Asosiy menyu", reply_markup=main_menu(message.from_user.id))

# ─── Statistika ───
@dp.message(F.text == "📊 Statistika")
async def admin_stats(message: types.Message):
    if not is_admin(message.from_user.id): return
    st = count_users()
    await message.answer(
        f"<b>📊 Statistika</b>\n\n"
        f"👥 Jami foydalanuvchi: <b>{st['total']}</b>\n"
        f"💎 VIP: <b>{st['vip']}</b>\n"
        f"🚫 Banlangan: <b>{st['banned']}</b>\n"
        f"🎬 Animelar: <b>{st['animes']}</b>",
        parse_mode="HTML"
    )

# ─── Broadcast ───
@dp.message(F.text == "✉ Xabar Yuborish")
async def admin_broadcast_start(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    await state.set_state(S.broadcast)
    await message.answer(
        "<b>📢 Barcha foydalanuvchilarga yuboriladigan xabarni yuboring:</b>",
        parse_mode="HTML",
        reply_markup=manage_kb()
    )

@dp.message(S.broadcast)
async def admin_broadcast_send(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    await state.clear()
    users = get_all_users()
    sent = failed = 0
    msg = await message.answer(f"📤 Yuborilmoqda... 0/{len(users)}")
    for i, uid in enumerate(users):
        try:
            if message.text:
                await bot.send_message(uid, message.text, parse_mode="HTML")
            elif message.photo:
                await bot.send_photo(uid, message.photo[-1].file_id, caption=message.caption or "", parse_mode="HTML")
            elif message.video:
                await bot.send_video(uid, message.video.file_id, caption=message.caption or "", parse_mode="HTML")
            sent += 1
        except Exception:
            failed += 1
        if (i+1) % 20 == 0:
            try:
                await msg.edit_text(f"📤 Yuborilmoqda... {i+1}/{len(users)}")
            except Exception:
                pass
        await asyncio.sleep(0.05)
    await msg.edit_text(
        f"✅ Broadcast tugadi!\n✅ Muvaffaqiyatli: {sent}\n❌ Xato: {failed}",
    )

# ─── Bot holati ───
@dp.message(F.text == "🤖 Bot holati")
async def admin_bot_holat(message: types.Message):
    if not is_admin(message.from_user.id): return
    holat = db_get("bot_holat")
    btn_text = "O'chirish" if holat == "Yoqilgan" else "Yoqish"
    await message.answer(
        f"<b>Hozirgi holat:</b> {holat}",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text=btn_text, callback_data="toggle_holat")],
            [InlineKeyboardButton(text="Orqaga", callback_data="boshqarish_cb")],
        ])
    )

@dp.callback_query(F.data == "toggle_holat")
async def cb_toggle_holat(call: CallbackQuery):
    if not is_admin(call.from_user.id): return
    holat = db_get("bot_holat")
    new_holat = "O'chirilgan" if holat == "Yoqilgan" else "Yoqilgan"
    db_set("bot_holat", new_holat)
    await call.message.edit_text(
        f"<b>✅ Bot holati: {new_holat}</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="Orqaga", callback_data="boshqarish_cb")]
        ])
    )

@dp.callback_query(F.data == "boshqarish_cb")
async def cb_boshqarish(call: CallbackQuery):
    if not is_admin(call.from_user.id): return
    await call.message.delete()
    await call.message.answer("<b>Admin paneliga xush kelibsiz!</b>", parse_mode="HTML", reply_markup=admin_panel_kb())

# ─── Birlamchi sozlamalar ───
@dp.message(F.text == "*️⃣ Birlamchi sozlamalar")
async def admin_birlamchi(message: types.Message):
    if not is_admin(message.from_user.id): return
    valyuta   = db_get("valyuta")
    narx      = db_get("vip_narx")
    studio    = db_get("studio_name")
    content   = db_get("content")
    c_text    = "🔒 Kontent cheklash" if content == "false" else "🔓 Kontent ulashish"
    await message.answer(
        f"<b>Hozirgi birlamchi sozlamalar:</b>\n\n"
        f"<i>1. Valyuta - {valyuta}\n"
        f"2. VIP narxi - {narx} {valyuta}\n"
        f"3. Studia nomi - {studio}</i>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [
                InlineKeyboardButton(text="1 Valyuta", callback_data="set_valyuta"),
                InlineKeyboardButton(text="2 VIP narx", callback_data="set_vnarx"),
                InlineKeyboardButton(text="3 Studia", callback_data="set_studio"),
            ],
            [InlineKeyboardButton(text=c_text, callback_data="toggle_content")],
        ])
    )

@dp.callback_query(F.data == "toggle_content")
async def cb_toggle_content(call: CallbackQuery):
    if not is_admin(call.from_user.id): return
    c = db_get("content")
    db_set("content", "true" if c == "false" else "false")
    await call.answer("✅ O'zgartirildi!")

@dp.callback_query(F.data.in_({"set_valyuta", "set_vnarx", "set_studio"}))
async def cb_set_birlamchi(call: CallbackQuery, state: FSMContext):
    if not is_admin(call.from_user.id): return
    await call.message.delete()
    mapping = {
        "set_valyuta": (S.set_valyuta, "📝 Yangi valyutani kiriting:"),
        "set_vnarx":   (S.set_vip_narx, "📝 Yangi VIP narxni kiriting:"),
        "set_studio":  (S.set_studio, "📝 Yangi studia nomini kiriting:"),
    }
    st, prompt = mapping[call.data]
    await state.set_state(st)
    await call.message.answer(f"<b>{prompt}</b>", parse_mode="HTML", reply_markup=manage_kb())

@dp.message(S.set_valyuta)
async def save_valyuta(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    db_set("valyuta", message.text)
    await state.clear()
    await message.answer("<b>✅ Valyuta saqlandi.</b>", parse_mode="HTML", reply_markup=admin_panel_kb())

@dp.message(S.set_vip_narx)
async def save_vnarx(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    db_set("vip_narx", message.text)
    await state.clear()
    await message.answer("<b>✅ VIP narx saqlandi.</b>", parse_mode="HTML", reply_markup=admin_panel_kb())

@dp.message(S.set_studio)
async def save_studio(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    db_set("studio_name", message.text)
    await state.clear()
    await message.answer("<b>✅ Studia nomi saqlandi.</b>", parse_mode="HTML", reply_markup=admin_panel_kb())

# ─── Matnlar ───
@dp.message(F.text == "📃 Matnlar")
async def admin_matnlar(message: types.Message):
    if not is_admin(message.from_user.id): return
    await message.answer(
        "<b>Quyidagilardan birini tanlang:</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="Boshlang'ich matni", callback_data="matn1")],
            [InlineKeyboardButton(text="Qo'llanma", callback_data="matn2")],
            [InlineKeyboardButton(text="🔖 Homiy matni", callback_data="matn5")],
        ])
    )

@dp.callback_query(F.data.in_({"matn1", "matn2", "matn5"}))
async def cb_matn(call: CallbackQuery, state: FSMContext):
    if not is_admin(call.from_user.id): return
    await call.message.delete()
    mapping = {
        "matn1": (S.set_start_txt, "Boshlang'ich matnini yuboring:"),
        "matn2": (S.set_qollanma,  "Qo'llanma matnini yuboring:"),
        "matn5": (S.set_homiy,     "Homiy matnini yuboring:"),
    }
    st, prompt = mapping[call.data]
    await state.set_state(st)
    await call.message.answer(f"<b>{prompt}</b>", parse_mode="HTML", reply_markup=manage_kb())

@dp.message(S.set_start_txt)
async def save_start_txt(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    db_set("start_text", message.text)
    await state.clear()
    await message.answer("<b>✅ Saqlandi.</b>", parse_mode="HTML", reply_markup=admin_panel_kb())

@dp.message(S.set_qollanma)
async def save_qollanma(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    db_set("qollanma", message.text)
    await state.clear()
    await message.answer("<b>✅ Saqlandi.</b>", parse_mode="HTML", reply_markup=admin_panel_kb())

@dp.message(S.set_homiy)
async def save_homiy(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    db_set("homiy", message.text)
    await state.clear()
    await message.answer("<b>✅ Saqlandi.</b>", parse_mode="HTML", reply_markup=admin_panel_kb())

# ════════════════════════════════════════════════════════════════
#                  🎥 ANIMELAR SOZLASH
# ════════════════════════════════════════════════════════════════

@dp.message(F.text == "🎥 Animelar sozlash")
async def admin_animelar(message: types.Message):
    if not is_admin(message.from_user.id): return
    await message.answer(
        "<b>Quyidagilardan birini tanlang:</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="➕ Anime qo'shish",   callback_data="add-anime")],
            [InlineKeyboardButton(text="📥 Qism qo'shish",    callback_data="add-episode")],
            [InlineKeyboardButton(text="📝 Anime tahrirlash", callback_data="edit-anime")],
        ])
    )

# ── Anime qo'shish ──
@dp.callback_query(F.data == "add-anime")
async def cb_add_anime(call: CallbackQuery, state: FSMContext):
    if not is_admin(call.from_user.id): return
    await call.message.delete()
    await state.set_state(S.anime_name)
    await call.message.answer("<b>🍿 Anime nomini kiriting:</b>", parse_mode="HTML", reply_markup=manage_kb())

@dp.message(S.anime_name)
async def anime_get_name(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    if message.text == "🗄 Boshqarish":
        await state.clear()
        await message.answer("", reply_markup=admin_panel_kb())
        return
    await state.update_data(nom=message.text)
    await state.set_state(S.anime_qismi)
    await message.answer("<b>🎥 Jami qismlar sonini kiriting:</b>", parse_mode="HTML")

@dp.message(S.anime_qismi)
async def anime_get_qismi(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    await state.update_data(qismi=message.text)
    await state.set_state(S.anime_country)
    await message.answer("<b>🌍 Qaysi davlat ishlab chiqarganini kiriting:</b>", parse_mode="HTML")

@dp.message(S.anime_country)
async def anime_get_country(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    await state.update_data(davlat=message.text)
    await state.set_state(S.anime_lang)
    await message.answer("<b>🇺🇿 Qaysi tilda ekanligini kiriting:</b>", parse_mode="HTML")

@dp.message(S.anime_lang)
async def anime_get_lang(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    await state.update_data(tili=message.text)
    await state.set_state(S.anime_year)
    await message.answer("<b>📆 Qaysi yilda ishlab chiqarilganini kiriting:</b>", parse_mode="HTML")

@dp.message(S.anime_year)
async def anime_get_year(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    await state.update_data(yili=message.text)
    await state.set_state(S.anime_genre)
    await message.answer(
        "<b>🎞 Janrlarini kiriting:</b>\n\n<i>Na'muna: Drama, Fantastika, Sarguzash</i>",
        parse_mode="HTML"
    )

@dp.message(S.anime_genre)
async def anime_get_genre(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    await state.update_data(janri=message.text)
    await state.set_state(S.anime_fandub)
    await message.answer(
        "<b>🎙️ Fandub nomini kiriting:</b>\n\n<i>Na'muna: @AnimeLiveUz</i>",
        parse_mode="HTML"
    )

@dp.message(S.anime_fandub)
async def anime_get_fandub(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    await state.update_data(aniType=message.text)
    await state.set_state(S.anime_picture)
    await message.answer(
        "<b>🏞 Rasmini yoki 60 soniyadan oshmagan video yuboring:</b>",
        parse_mode="HTML"
    )

@dp.message(S.anime_picture)
async def anime_get_picture(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    file_id = None
    if message.photo:
        file_id = message.photo[-1].file_id
    elif message.video:
        if message.video.duration <= 60:
            file_id = message.video.file_id
        else:
            await message.answer("<b>⚠️ Video 60 soniyadan oshmasligi kerak!</b>", parse_mode="HTML")
            return
    else:
        await message.answer("<b>⚠️ Iltimos, rasm yoki 60 soniyadan oshmagan video yuboring!</b>", parse_mode="HTML")
        return

    data = await state.get_data()
    await state.clear()
    sana = datetime.now().strftime("%H:%M %d.%m.%Y")
    conn = get_db()
    try:
        conn.execute(
            "INSERT INTO animelar (nom,rams,qismi,davlat,tili,yili,janri,qidiruv,aniType,sana) "
            "VALUES (?,?,?,?,?,?,?,0,?,?)",
            (data["nom"], file_id, data["qismi"], data["davlat"],
             data["tili"], data["yili"], data["janri"], data["aniType"], sana)
        )
        conn.commit()
        code = conn.execute("SELECT last_insert_rowid() as lid").fetchone()["lid"]
        await message.answer(
            f"<b>✅ Anime qo'shildi!\n\nAnime kodi: <code>{code}</code></b>",
            parse_mode="HTML",
            reply_markup=admin_panel_kb()
        )
        logger.info(f"✅ Anime qo'shildi: {code} - {data['nom']}")
    except Exception as e:
        await message.answer(f"<b>⚠️ Xatolik!</b>\n<code>{e}</code>", parse_mode="HTML")
    finally:
        conn.close()

# ── Qism qo'shish ──
@dp.callback_query(F.data == "add-episode")
async def cb_add_episode(call: CallbackQuery, state: FSMContext):
    if not is_admin(call.from_user.id): return
    await call.message.delete()
    await state.set_state(S.ep_code)
    await call.message.answer("<b>🔢 Anime kodini kiriting:</b>", parse_mode="HTML", reply_markup=manage_kb())

@dp.message(S.ep_code)
async def ep_get_code(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    if not message.text.isdigit():
        await message.answer("<b>❗ Faqat raqam kiriting!</b>", parse_mode="HTML")
        return
    rew = get_anime_by_id(message.text)
    if not rew:
        await message.answer("<b>❗ Bu ID li anime topilmadi!</b>", parse_mode="HTML")
        return
    await state.update_data(ep_anime_id=message.text)
    await state.set_state(S.ep_video)
    await message.answer(
        f"<b>✅ Topildi: {rew['nom']}\n🎥 Ushbu kodga tegishlik anime qismini yuboring:</b>",
        parse_mode="HTML"
    )

@dp.message(S.ep_video)
async def ep_get_video(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    if not message.video:
        await message.answer("<b>❗ Faqat video yuboring!</b>", parse_mode="HTML")
        return
    data = await state.get_data()
    anime_id = data["ep_anime_id"]
    file_id = message.video.file_id

    conn = get_db()
    count = conn.execute("SELECT COUNT(*) as c FROM anime_datas WHERE id=?", (anime_id,)).fetchone()["c"]
    qism = count + 1
    sana = datetime.now().strftime("%H:%M:%S %d.%m.%Y")
    conn.execute("INSERT INTO anime_datas (id,file_id,qism,sana) VALUES (?,?,?,?)",
                 (anime_id, file_id, qism, sana))
    conn.commit()
    conn.close()
    await message.answer(
        f"<b>✅ {anime_id} raqamli animega {qism}-qism yuklandi!\n\n"
        f"<i>Yana yuklash uchun keyingi qismni yuborsangiz bo'ldi</i></b>",
        parse_mode="HTML"
    )
    # Holatni o'zgartirmaymiz — davom etish mumkin

# ── Anime tahrirlash ──
@dp.callback_query(F.data == "edit-anime")
async def cb_edit_anime(call: CallbackQuery):
    if not is_admin(call.from_user.id): return
    await call.message.edit_text(
        "<b>Tahrirlamoqchi bo'lgan animeni tanlang:</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="Anime ma'lumotlarini", callback_data="editType=animes")],
            [InlineKeyboardButton(text="Anime qismini",        callback_data="editType=anime_datas")],
        ])
    )

@dp.callback_query(F.data.startswith("editType="))
async def cb_edit_type(call: CallbackQuery, state: FSMContext):
    if not is_admin(call.from_user.id): return
    tip = call.data.replace("editType=", "")
    await state.update_data(edit_type=tip)
    await call.message.delete()
    await state.set_state(S.edit_code)
    await call.message.answer("<b>Anime kodini kiriting:</b>", parse_mode="HTML", reply_markup=manage_kb())

@dp.message(S.edit_code)
async def edit_get_code(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    data = await state.get_data()
    tip = data.get("edit_type", "animes")
    rew = get_anime_by_id(message.text.strip())

    if not rew:
        await message.answer("<b>❗ Anime mavjud emas, qayta urinib ko'ring!</b>", parse_mode="HTML")
        return

    if tip == "animes":
        await state.clear()
        await message.answer(
            "<b>❓ Nimani tahrirlamoqchisiz?</b>",
            parse_mode="HTML",
            reply_markup=InlineKeyboardMarkup(inline_keyboard=[
                [InlineKeyboardButton(text="Nomini tahrirlash",      callback_data=f"editAnime=nom={rew['id']}")],
                [InlineKeyboardButton(text="Qismini tahrirlash",     callback_data=f"editAnime=qismi={rew['id']}")],
                [InlineKeyboardButton(text="Davlatini tahrirlash",   callback_data=f"editAnime=davlat={rew['id']}")],
                [InlineKeyboardButton(text="Tilini tahrirlash",      callback_data=f"editAnime=tili={rew['id']}")],
                [InlineKeyboardButton(text="Yilini tahrirlash",      callback_data=f"editAnime=yili={rew['id']}")],
                [InlineKeyboardButton(text="Janrini tahrirlash",     callback_data=f"editAnime=janri={rew['id']}")],
                [InlineKeyboardButton(text="Anime rasmini tahrirlash", callback_data=f"editAnime=image={rew['id']}")],
                [InlineKeyboardButton(text="Animeni o'chirish",      callback_data=f"confirm-delete={rew['id']}")],
            ])
        )
    else:
        await state.update_data(edit_anime_id=str(rew["id"]))
        await state.set_state(S.edit_ep_num)
        await message.answer("<b>Qism raqamini yuboring:</b>", parse_mode="HTML")

@dp.message(S.edit_ep_num)
async def edit_ep_num_input(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    data = await state.get_data()
    anime_id = data.get("edit_anime_id")
    ep = get_episode(anime_id, message.text.strip())
    if not ep:
        await message.answer(f"<b>❗ Ushbu animeda {message.text}-qism mavjud emas.</b>", parse_mode="HTML")
        return
    await state.clear()
    await message.answer(
        "<b>❓ Nimani tahrirlamoqchisiz?</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="Qismini tahrirlash", callback_data=f"editEpisode=qism={anime_id}={message.text}")],
            [InlineKeyboardButton(text="Videoni tahrirlash",  callback_data=f"editEpisode=file_id={anime_id}={message.text}")],
        ])
    )

@dp.callback_query(F.data.startswith("editAnime="))
async def cb_edit_anime_field(call: CallbackQuery, state: FSMContext):
    if not is_admin(call.from_user.id): return
    parts = call.data.split("=")
    field, anime_id = parts[1], parts[2]
    await state.update_data(edit_field=field, edit_anime_id=anime_id)
    await state.set_state(S.edit_field)
    await call.message.delete()
    await call.message.answer("<b>Yangi qiymatini kiriting:</b>", parse_mode="HTML", reply_markup=manage_kb())

@dp.message(S.edit_field)
async def save_edit_field(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    data = await state.get_data()
    field    = data.get("edit_field")
    anime_id = data.get("edit_anime_id")

    if field == "image":
        file_id = None
        if message.photo:
            file_id = message.photo[-1].file_id
        elif message.video and message.video.duration <= 60:
            file_id = message.video.file_id
        if not file_id:
            await message.answer("<b>⚠️ Rasm yoki ≤60s video yuboring!</b>", parse_mode="HTML")
            return
        conn = get_db()
        conn.execute("UPDATE animelar SET rams=? WHERE id=?", (file_id, int(anime_id)))
        conn.commit()
        conn.close()
        await state.clear()
        await message.answer("<b>✅ Rasm yangilandi!</b>", parse_mode="HTML", reply_markup=admin_panel_kb())
        return

    if field in ("qismi", "yili") and not message.text.isdigit():
        await message.answer("<b>❗ Faqat raqamlardan foydalaning.</b>", parse_mode="HTML")
        return

    conn = get_db()
    conn.execute(f"UPDATE animelar SET {field}=? WHERE id=?", (message.text, int(anime_id)))
    conn.commit()
    conn.close()
    await state.clear()
    await message.answer("<b>✅ Saqlandi.</b>", parse_mode="HTML", reply_markup=admin_panel_kb())

@dp.callback_query(F.data.startswith("confirm-delete="))
async def cb_confirm_delete(call: CallbackQuery):
    if not is_admin(call.from_user.id): return
    anime_id = call.data.replace("confirm-delete=", "")
    await call.message.edit_text(
        f"❗ Ushbu animeni va uning barcha qismlarini o'chirishni istaysizmi?\nID: <b>{anime_id}</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [
                InlineKeyboardButton(text="✅ Ha",   callback_data=f"do-delete={anime_id}"),
                InlineKeyboardButton(text="❌ Yo'q", callback_data="cancel-delete"),
            ]
        ])
    )

@dp.callback_query(F.data.startswith("do-delete="))
async def cb_do_delete(call: CallbackQuery):
    if not is_admin(call.from_user.id): return
    anime_id = call.data.replace("do-delete=", "")
    conn = get_db()
    conn.execute("DELETE FROM animelar WHERE id=?",    (int(anime_id),))
    conn.execute("DELETE FROM anime_datas WHERE id=?", (str(anime_id),))
    conn.commit()
    conn.close()
    await call.message.edit_text("<b>✅ Anime va barcha qismlari o'chirildi!</b>", parse_mode="HTML")

@dp.callback_query(F.data == "cancel-delete")
async def cb_cancel_delete(call: CallbackQuery):
    await call.message.edit_text("<b>❌ O'chirish so'rovi bekor qilindi.</b>", parse_mode="HTML")

@dp.callback_query(F.data.startswith("editEpisode="))
async def cb_edit_episode(call: CallbackQuery, state: FSMContext):
    if not is_admin(call.from_user.id): return
    parts = call.data.split("=")
    field, anime_id, ep_num = parts[1], parts[2], parts[3]
    await state.update_data(ep_field=field, ep_anime_id=anime_id, ep_num=ep_num)
    await state.set_state(S.edit_ep_field)
    await call.message.delete()
    await call.message.answer("<b>Yangi qiymatini kiriting:</b>", parse_mode="HTML", reply_markup=manage_kb())

@dp.message(S.edit_ep_field)
async def save_ep_field(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    data = await state.get_data()
    field    = data.get("ep_field")
    anime_id = data.get("ep_anime_id")
    ep_num   = data.get("ep_num")

    if field == "file_id":
        if not message.video:
            await message.answer("<b>❗ Faqat videodan foydalaning.</b>", parse_mode="HTML")
            return
        conn = get_db()
        conn.execute("UPDATE anime_datas SET file_id=? WHERE id=? AND qism=?",
                     (message.video.file_id, str(anime_id), int(ep_num)))
        conn.commit()
        conn.close()
    else:
        if not message.text.isdigit():
            await message.answer("<b>❗ Faqat raqamlardan foydalaning.</b>", parse_mode="HTML")
            return
        conn = get_db()
        conn.execute(f"UPDATE anime_datas SET {field}=? WHERE id=? AND qism=?",
                     (message.text, str(anime_id), int(ep_num)))
        conn.commit()
        conn.close()

    await state.clear()
    await message.answer("<b>✅ Saqlandi.</b>", parse_mode="HTML", reply_markup=admin_panel_kb())

# ════════════════════════════════════════════════════════════════
#                📬 POST TAYYORLASH
# ════════════════════════════════════════════════════════════════

@dp.message(F.text == "📬 Post tayyorlash")
async def admin_post(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    await state.set_state(S.post_code)
    await message.answer("<b>🆔 Anime kodini kiriting:</b>", parse_mode="HTML", reply_markup=manage_kb())

@dp.message(S.post_code)
async def post_choose_channel(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    rew = get_anime_by_id(message.text.strip())
    if not rew:
        await message.answer("❌ Anime topilmadi!", reply_markup=admin_panel_kb())
        await state.clear()
        return
    await state.clear()
    kanallar = get_anime_kanallar()
    btns = [[InlineKeyboardButton(text=f"📤 {k} ga yuborish", callback_data=f"sendto={k}|{rew['id']}")]
            for k in kanallar]
    btns.append([InlineKeyboardButton(text="📡 BARCHA kanallarga yuborish",
                                      callback_data=f"sendto=ALL|{rew['id']}")])
    await message.answer(
        "📬 Qaysi kanalga yuborilsin?",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=btns)
    )

@dp.callback_query(F.data.startswith("sendto="))
async def cb_sendto(call: CallbackQuery):
    if not is_admin(call.from_user.id): return
    rest = call.data.replace("sendto=", "")
    kanal, anime_id = rest.split("|")
    rew = get_anime_by_id(anime_id)
    if not rew:
        await call.message.answer("❌ Anime topilmadi!")
        return
    await call.message.delete()
    kanallar = get_anime_kanallar()
    if kanal == "ALL":
        for k in kanallar:
            try:
                await send_anime_post(bot, k, rew)
            except Exception as e:
                logger.error(f"Post yuborishda xato {k}: {e}")
        await call.message.answer("✅ Postingiz barcha kanallarga yuborildi!", reply_markup=admin_panel_kb())
    else:
        try:
            await send_anime_post(bot, kanal, rew)
            await call.message.answer(f"✅ Postingiz {kanal} ga yuborildi!", reply_markup=admin_panel_kb())
        except Exception as e:
            await call.message.answer(f"❌ Xato: {e}")
    # Admin o'ziga ham yuborsin
    await send_anime_post(bot, call.from_user.id, rew)

# ════════════════════════════════════════════════════════════════
#              🔎 FOYDALANUVCHINI BOSHQARISH
# ════════════════════════════════════════════════════════════════

@dp.message(F.text == "🔎 Foydalanuvchini boshqarish")
async def admin_user_manage(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    await state.set_state(S.user_id_input)
    await message.answer(
        "<b>Kerakli foydalanuvchining ID raqamini kiriting:</b>",
        parse_mode="HTML",
        reply_markup=manage_kb()
    )

@dp.message(S.user_id_input)
async def user_id_received(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    tid = message.text.strip()
    row = get_user(tid)
    if not row:
        await message.answer("<b>Foydalanuvchi topilmadi.\n\nQayta urinib ko'ring:</b>", parse_mode="HTML")
        return
    await state.clear()
    await show_user_panel(message, tid)

async def show_user_panel(message: types.Message, tid: str):
    k   = get_kabinet(tid)
    st  = get_status_row(tid)
    pul = k["pul"] if k else 0
    odam = k["odam"] if k else 0
    ban  = k["ban"] if k else "unban"
    is_vip = st and st.get("kun", 0) > 0
    valyuta = db_get("valyuta")

    vip_btn  = "❌ VIP dan olish" if is_vip else "💎 VIP ga qo'shish"
    ban_btn  = "🔕 Bandan olish" if ban == "ban" else "🔔 Banlash"

    await message.answer(
        f"<b>Foydalanuvchi topildi!\n\n"
        f"ID:</b> <a href='tg://user?id={tid}'>{tid}</a>\n"
        f"<b>Balans: {pul} {valyuta}\n"
        f"Takliflar: {odam} ta</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text=ban_btn,  callback_data=f"ban-{tid}")],
            [InlineKeyboardButton(text=vip_btn,  callback_data=f"addvip-{tid}")],
            [
                InlineKeyboardButton(text="➕ Pul qo'shish", callback_data=f"plus-{tid}"),
                InlineKeyboardButton(text="➖ Pul ayirish",  callback_data=f"minus-{tid}"),
            ],
        ])
    )

@dp.callback_query(F.data.startswith("ban-"))
async def cb_ban(call: CallbackQuery):
    if not is_admin(call.from_user.id): return
    tid = call.data.replace("ban-", "")
    if str(call.from_user.id) == str(ADMIN_ID) and tid == str(ADMIN_ID):
        await call.answer("Asosiy adminlarni blocklash mumkin emas!", show_alert=True)
        return
    k = get_kabinet(tid)
    ban = k["ban"] if k else "unban"
    new_ban = "unban" if ban == "ban" else "ban"
    conn = get_db()
    conn.execute("UPDATE kabinet SET ban=? WHERE user_id=?", (new_ban, tid))
    conn.commit()
    conn.close()
    text = f"Foydalanuvchi ({tid}) {'bandan olindi' if new_ban=='unban' else 'banlandi'}!"
    await call.message.edit_text(
        f"<b>{text}</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="◀️ Orqaga", callback_data=f"foyda-{tid}")]
        ])
    )

@dp.callback_query(F.data.startswith("foyda-"))
async def cb_foyda(call: CallbackQuery):
    if not is_admin(call.from_user.id): return
    tid = call.data.replace("foyda-", "")
    await call.message.delete()
    await show_user_panel(call.message, tid)

@dp.callback_query(F.data.startswith("addvip-"))
async def cb_addvip(call: CallbackQuery):
    if not is_admin(call.from_user.id): return
    tid = call.data.replace("addvip-", "")
    st  = get_status_row(tid)
    is_vip = st and st.get("kun", 0) > 0
    conn = get_db()
    if is_vip:
        conn.execute("UPDATE status SET kun=0 WHERE user_id=?", (tid,))
        text = f"Foydalanuvchi ({tid}) VIP dan olindi!"
    else:
        conn.execute("UPDATE status SET kun=30 WHERE user_id=?", (tid,))
        text = f"Foydalanuvchi ({tid}) VIP ga qo'shildi!"
    conn.commit()
    conn.close()
    await call.message.edit_text(
        f"<b>{text}</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="◀️ Orqaga", callback_data=f"foyda-{tid}")]
        ])
    )
    try:
        msg = "🎉 Siz VIP ga qo'shildingiz!" if not is_vip else "❌ VIP statusingiz olib tashlandi."
        await bot.send_message(int(tid), f"<b>{msg}</b>", parse_mode="HTML")
    except Exception:
        pass

@dp.callback_query(F.data.startswith("plus-"))
async def cb_plus(call: CallbackQuery, state: FSMContext):
    if not is_admin(call.from_user.id): return
    tid = call.data.replace("plus-", "")
    await state.update_data(balance_uid=tid, balance_op="plus")
    await state.set_state(S.add_balance)
    valyuta = db_get("valyuta")
    await call.message.edit_text(
        f"<a href='tg://user?id={tid}'>{tid}</a> <b>ning hisobiga qancha pul qo'shmoqchisiz? ({valyuta})</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="◀️ Orqaga", callback_data=f"foyda-{tid}")]
        ])
    )

@dp.message(S.add_balance)
async def process_add_balance(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    data = await state.get_data()
    tid = data["balance_uid"]
    if not message.text.isdigit():
        await message.answer("<b>Faqat raqamlardan foydalaning!</b>", parse_mode="HTML")
        return
    amount = int(message.text)
    conn = get_db()
    conn.execute("UPDATE kabinet SET pul=pul+?, pul2=pul2+? WHERE user_id=?", (amount, amount, tid))
    conn.commit()
    conn.close()
    valyuta = db_get("valyuta")
    await state.clear()
    await message.answer(f"<b>✅ {amount} {valyuta} qo'shildi!</b>", parse_mode="HTML", reply_markup=admin_panel_kb())
    try:
        await bot.send_message(int(tid), f"<b>✅ Adminlar tomonidan hisobingiz {amount} {valyuta} to'ldirildi!</b>", parse_mode="HTML")
    except Exception:
        pass

@dp.callback_query(F.data.startswith("minus-"))
async def cb_minus(call: CallbackQuery, state: FSMContext):
    if not is_admin(call.from_user.id): return
    tid = call.data.replace("minus-", "")
    await state.update_data(balance_uid=tid, balance_op="minus")
    await state.set_state(S.sub_balance)
    valyuta = db_get("valyuta")
    await call.message.edit_text(
        f"<a href='tg://user?id={tid}'>{tid}</a> <b>ning hisobidan qancha pul ayirmoqchisiz? ({valyuta})</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="◀️ Orqaga", callback_data=f"foyda-{tid}")]
        ])
    )

@dp.message(S.sub_balance)
async def process_sub_balance(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    data = await state.get_data()
    tid = data["balance_uid"]
    if not message.text.isdigit():
        await message.answer("<b>Faqat raqamlardan foydalaning!</b>", parse_mode="HTML")
        return
    amount = int(message.text)
    conn = get_db()
    conn.execute("UPDATE kabinet SET pul=pul-? WHERE user_id=?", (amount, tid))
    conn.commit()
    conn.close()
    valyuta = db_get("valyuta")
    await state.clear()
    await message.answer(f"<b>✅ {amount} {valyuta} ayirildi!</b>", parse_mode="HTML", reply_markup=admin_panel_kb())
    try:
        await bot.send_message(int(tid), f"<b>Adminlar tomonidan hisobingizdan {amount} {valyuta} olib tashlandi!</b>", parse_mode="HTML")
    except Exception:
        pass

# ════════════════════════════════════════════════════════════════
#                  📢 KANALLAR SOZLASH
# ════════════════════════════════════════════════════════════════

@dp.message(F.text == "📢 Kanallar")
async def admin_kanallar(message: types.Message):
    if not is_admin(message.from_user.id): return
    await message.answer(
        "<b>Kanallar sozlash bo'limidasiz:</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="🔐 Majburiy obuna",  callback_data="majburiy")],
            [InlineKeyboardButton(text="🎥 Anime kanallar",  callback_data="anime-kanal")],
        ])
    )

# ── Majburiy obuna ──
@dp.callback_query(F.data == "majburiy")
async def cb_majburiy(call: CallbackQuery):
    if not is_admin(call.from_user.id): return
    await call.message.edit_text(
        "<b>🔐 Majburiy obunalarni sozlash:</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="➕ Qo'shish",  callback_data="qoshish")],
            [
                InlineKeyboardButton(text="📑 Ro'yxat",  callback_data="royxat"),
                InlineKeyboardButton(text="🗑 O'chirish", callback_data="ochirish"),
            ],
            [InlineKeyboardButton(text="🔙 Ortga", callback_data="kanallar_cb")],
        ])
    )

@dp.callback_query(F.data == "kanallar_cb")
async def cb_kanallar(call: CallbackQuery):
    if not is_admin(call.from_user.id): return
    await call.message.edit_text(
        "<b>Kanallar sozlash:</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="🔐 Majburiy obuna", callback_data="majburiy")],
            [InlineKeyboardButton(text="🎥 Anime kanallar", callback_data="anime-kanal")],
        ])
    )

@dp.callback_query(F.data == "qoshish")
async def cb_qoshish(call: CallbackQuery, state: FSMContext):
    if not is_admin(call.from_user.id): return
    await call.message.delete()
    await state.set_state(S.ch_add_id)
    await call.message.answer("<b>💬 Kanal IDsini yuboring!</b>\nNamuna: <code>-1001234567890</code>", parse_mode="HTML")

@dp.message(S.ch_add_id)
async def ch_add_id(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    cid = message.text.strip()
    if not (cid.lstrip("-").isdigit() or cid.startswith("@")):
        await message.answer("<b>❗ Noto'g'ri format! -100... yoki @username kiriting.</b>", parse_mode="HTML")
        return
    await state.update_data(ch_id=cid)
    await state.set_state(S.ch_add_link)
    await message.answer("<b>🔗 Kanal havolasini kiriting!</b>\nNamuna: <code>https://t.me/kanalim</code>", parse_mode="HTML")

@dp.message(S.ch_add_link)
async def ch_add_link(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    link = message.text.strip()
    if "t.me" not in link and "telegram" not in link:
        await message.answer("<b>❗ Faqat Telegram havolasi! Namuna: https://t.me/kanal</b>", parse_mode="HTML")
        return
    await state.update_data(ch_link=link)
    await state.set_state(S.ch_add_type)
    await message.answer(
        "<b>⚠️ Bu kanal zayafka (join request) kanal sifatida qo'shilsinmi?</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [
                InlineKeyboardButton(text="✅ Ha (request)", callback_data="addChannel=request"),
                InlineKeyboardButton(text="❌ Yo'q (lock)",  callback_data="addChannel=lock"),
            ],
            [InlineKeyboardButton(text="🚫 Bekor qilish", callback_data="cancel")],
        ])
    )

@dp.message(S.ch_add_type)
async def ch_add_type_msg(message: types.Message, state: FSMContext):
    pass  # Inline tugma orqali

@dp.callback_query(F.data.startswith("addChannel="))
async def cb_add_channel(call: CallbackQuery, state: FSMContext):
    if not is_admin(call.from_user.id): return
    ch_type = call.data.replace("addChannel=", "")
    data = await state.get_data()
    await state.clear()
    ch_id   = data.get("ch_id", "")
    ch_link = data.get("ch_link", "")
    conn = get_db()
    conn.execute("INSERT INTO channels (channelId,channelType,channelLink) VALUES (?,?,?)",
                 (ch_id, ch_type, ch_link))
    conn.commit()
    conn.close()
    await call.message.delete()
    await call.message.answer("<b>✅ Majburiy obunaga kanal ulandi!</b>", parse_mode="HTML", reply_markup=admin_panel_kb())

@dp.callback_query(F.data == "cancel")
async def cb_cancel(call: CallbackQuery, state: FSMContext):
    await state.clear()
    await call.message.delete()
    await call.message.answer("<b>✅ Bekor qilindi!</b>", parse_mode="HTML", reply_markup=admin_panel_kb())

@dp.callback_query(F.data == "royxat")
async def cb_royxat(call: CallbackQuery):
    if not is_admin(call.from_user.id): return
    channels = get_channels()
    if not channels:
        await call.answer("Hech qanday kanallar ulanmagan!", show_alert=True)
        return
    text = "<b>📢 Kanallar ro'yxati:</b>\n"
    for i, ch in enumerate(channels, 1):
        text += f"\n<b>{i}.</b> {ch['channelLink']} | {ch['channelType']}"
    text += f"\n\n<b>Ulangan kanallar soni:</b> {len(channels)} ta"
    await call.message.edit_text(
        text, parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="🔙 Ortga", callback_data="majburiy")]
        ])
    )

@dp.callback_query(F.data == "ochirish")
async def cb_ochirish(call: CallbackQuery):
    if not is_admin(call.from_user.id): return
    channels = get_channels()
    if not channels:
        await call.answer("Hech qanday kanallar ulanmagan!", show_alert=True)
        return
    text = "<b>✂️ Kanalni uzish uchun raqam ustiga bosing!</b>\n"
    btns = []
    for i, ch in enumerate(channels, 1):
        text += f"\n<b>{i}.</b> {ch['channelLink']} | {ch['channelType']}"
        btns.append(InlineKeyboardButton(text=f"🗑️{i}", callback_data=f"channelDelete={ch['id']}"))
    rows = [btns[i:i+5] for i in range(0, len(btns), 5)]
    rows.append([InlineKeyboardButton(text="🔙 Ortga", callback_data="majburiy")])
    await call.message.edit_text(
        text, parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=rows)
    )

@dp.callback_query(F.data.startswith("channelDelete="))
async def cb_channel_delete(call: CallbackQuery):
    if not is_admin(call.from_user.id): return
    cid_row = int(call.data.replace("channelDelete=", ""))
    conn = get_db()
    conn.execute("DELETE FROM channels WHERE id=?", (cid_row,))
    conn.commit()
    conn.close()
    await call.answer("✅ Kanal uzildi")
    await cb_ochirish(call)

# ── Anime kanallar ──
@dp.callback_query(F.data == "anime-kanal")
async def cb_anime_kanal(call: CallbackQuery):
    if not is_admin(call.from_user.id): return
    await call.message.edit_text(
        "<b>📢 Anime kanal ustida qanday amal bajaramiz?</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="➕ Qo'shish",   callback_data="add_anime_channel")],
            [
                InlineKeyboardButton(text="📃 Ro'yhat",  callback_data="list_anime_channel"),
                InlineKeyboardButton(text="🗑 O'chirish", callback_data="delete_anime_channel"),
            ],
        ])
    )

@dp.callback_query(F.data == "add_anime_channel")
async def cb_add_anime_ch(call: CallbackQuery, state: FSMContext):
    if not is_admin(call.from_user.id): return
    await call.message.delete()
    await state.set_state(S.anime_ch_add)
    await call.message.answer(
        "<b>📨 Kanal usernamesini yuboring</b>\nNamuna: <code>@kanal_username</code>",
        parse_mode="HTML"
    )

@dp.message(S.anime_ch_add)
async def save_anime_channel(message: types.Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    ch = message.text.strip()
    if not ch.startswith("@"):
        await message.answer("❗ To'g'ri formatda yuboring: <code>@kanalim</code>", parse_mode="HTML")
        return
    conn = get_db()
    try:
        conn.execute("INSERT OR IGNORE INTO anime_kanallar (channel_id) VALUES (?)", (ch,))
        conn.commit()
        await message.answer(f"✅ <b>Kanal qo'shildi:</b> <code>{ch}</code>", parse_mode="HTML", reply_markup=admin_panel_kb())
    except Exception as e:
        await message.answer(f"❌ Xato: {e}")
    finally:
        conn.close()
    await state.clear()

@dp.callback_query(F.data == "list_anime_channel")
async def cb_list_anime_ch(call: CallbackQuery):
    kanallar = get_anime_kanallar()
    if not kanallar:
        await call.answer("Ro'yxatda kanal yo'q.", show_alert=True)
        return
    text = "<b>📃 Anime kanallar ro'yxati:</b>\n\n"
    for i, k in enumerate(kanallar, 1):
        text += f"{i}. <code>{k}</code>\n"
    await call.message.edit_text(text, parse_mode="HTML",
                                  reply_markup=InlineKeyboardMarkup(inline_keyboard=[
                                      [InlineKeyboardButton(text="🔙 Ortga", callback_data="anime-kanal")]
                                  ]))

@dp.callback_query(F.data == "delete_anime_channel")
async def cb_del_anime_ch(call: CallbackQuery):
    kanallar = get_anime_kanallar()
    if not kanallar:
        await call.answer("Ro'yxatda kanal yo'q.", show_alert=True)
        return
    btns = [[InlineKeyboardButton(text=str(i+1), callback_data=f"del_anime_ch_{k}")]
            for i, k in enumerate(kanallar)]
    await call.message.edit_text(
        "<b>🗑 O'chirmoqchi bo'lgan kanal raqamini tanlang:</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=btns)
    )

@dp.callback_query(F.data.startswith("del_anime_ch_"))
async def cb_del_anime_ch_confirm(call: CallbackQuery):
    ch = call.data.replace("del_anime_ch_", "")
    conn = get_db()
    conn.execute("DELETE FROM anime_kanallar WHERE channel_id=?", (ch,))
    conn.commit()
    conn.close()
    await call.message.edit_text(f"✅ <b>{ch}</b> o'chirildi.", parse_mode="HTML")

# ════════════════════════════════════════════════════════════════
#                    📋 ADMINLAR
# ════════════════════════════════════════════════════════════════

@dp.message(F.text == "📋 Adminlar")
async def admin_adminlar(message: types.Message):
    if not is_admin(message.from_user.id): return
    btns = []
    if message.from_user.id == ADMIN_ID:
        btns = [
            [InlineKeyboardButton(text="➕ Yangi admin qo'shish", callback_data="add_admin_cb")],
            [
                InlineKeyboardButton(text="📑 Ro'yxat",  callback_data="list_admins"),
                InlineKeyboardButton(text="🗑 O'chirish", callback_data="remove_admin_cb"),
            ],
            [InlineKeyboardButton(text="Orqaga", callback_data="boshqarish_cb")],
        ]
    else:
        btns = [
            [InlineKeyboardButton(text="📑 Ro'yxat", callback_data="list_admins")],
            [InlineKeyboardButton(text="Orqaga",     callback_data="boshqarish_cb")],
        ]
    await message.answer(
        "<b>Quyidagilardan birini tanlang:</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=btns)
    )

@dp.callback_query(F.data == "list_admins")
async def cb_list_admins(call: CallbackQuery):
    conn = get_db()
    rows = conn.execute("SELECT user_id FROM admins").fetchall()
    conn.close()
    if not rows:
        text = "<b>Yordamchi adminlar topilmadi!</b>"
    else:
        text = "<b>👮 Adminlar ro'yxati:</b>\n"
        for r in rows:
            text += f"\n• <code>{r['user_id']}</code>"
    await call.message.edit_text(text, parse_mode="HTML",
                                  reply_markup=InlineKeyboardMarkup(inline_keyboard=[
                                      [InlineKeyboardButton(text="Orqaga", callback_data="boshqarish_cb")]
                                  ]))

@dp.callback_query(F.data == "add_admin_cb")
async def cb_add_admin(call: CallbackQuery, state: FSMContext):
    if call.from_user.id != ADMIN_ID: return
    await call.message.delete()
    await state.set_state(S.add_admin)
    await call.message.answer("<b>Kerakli foydalanuvchi ID raqamini yuboring:</b>", parse_mode="HTML", reply_markup=manage_kb())

@dp.message(S.add_admin)
async def save_add_admin(message: types.Message, state: FSMContext):
    if message.from_user.id != ADMIN_ID: return
    tid = message.text.strip()
    if not get_user(tid):
        await message.answer("<b>Ushbu foydalanuvchi botdan foydalanmaydi!\n\nBoshqa ID raqamni kiriting:</b>", parse_mode="HTML")
        return
    conn = get_db()
    conn.execute("INSERT OR IGNORE INTO admins (user_id) VALUES (?)", (tid,))
    conn.commit()
    conn.close()
    await state.clear()
    await message.answer(f"<code>{tid}</code> <b>adminlar ro'yxatiga qo'shildi!</b>", parse_mode="HTML", reply_markup=admin_panel_kb())
    try:
        await bot.send_message(int(tid), "<b>🎉 Siz admin qilib tayinlandingiz!</b>", parse_mode="HTML")
    except Exception:
        pass

@dp.callback_query(F.data == "remove_admin_cb")
async def cb_remove_admin(call: CallbackQuery, state: FSMContext):
    if call.from_user.id != ADMIN_ID: return
    await call.message.delete()
    await state.set_state(S.remove_admin)
    await call.message.answer("<b>O'chiriladigan admin ID raqamini yuboring:</b>", parse_mode="HTML", reply_markup=manage_kb())

@dp.message(S.remove_admin)
async def save_remove_admin(message: types.Message, state: FSMContext):
    if message.from_user.id != ADMIN_ID: return
    tid = message.text.strip()
    conn = get_db()
    conn.execute("DELETE FROM admins WHERE user_id=?", (tid,))
    conn.commit()
    conn.close()
    await state.clear()
    await message.answer(f"<code>{tid}</code> <b>adminlar ro'yxatidan olib tashlandi!</b>", parse_mode="HTML", reply_markup=admin_panel_kb())

# ════════════════════════════════════════════════════════════════
#              🔢 RAQAM YUBORILGANDA (anime kodi)
# ════════════════════════════════════════════════════════════════

@dp.message(F.text.regexp(r'^\d+$'))
async def handle_anime_code(message: types.Message, state: FSMContext):
    uid = message.from_user.id
    if is_banned(uid): return
    if db_get("bot_holat") == "O'chirilgan" and not is_admin(uid):
        await message.answer("⛔️ <b>Bot vaqtinchalik o'chirilgan!</b>", parse_mode="HTML")
        return

    if not await require_sub(bot, message, message.text.strip()):
        return

    rew = get_anime_by_id(message.text.strip())
    if rew:
        increment_views(rew["id"])
        await send_anime(bot, uid, rew)
    else:
        await message.answer(
            f"<b>[ {message.text} ] kodiga tegishli anime topilmadi😔\n\n• Boshqa Kod yuboring</b>",
            parse_mode="HTML"
        )

# ════════════════════════════════════════════════════════════════
#              🔤 MATN QIDIRISH (anime nomi orqali)
# ════════════════════════════════════════════════════════════════

@dp.message(F.text)
async def handle_text_search(message: types.Message, state: FSMContext):
    """Holatda bo'lmagan matnni qidirish sifatida qabul qilish (PHP oxiridagi qidiruv)"""
    uid = message.from_user.id
    if is_banned(uid): return

    current_state = await state.get_state()
    if current_state is not None:
        return  # FSM holat allaqachon boshqaradi

    results = search_anime_by_name(message.text)
    if not results:
        return
    btns = [[InlineKeyboardButton(text=f"{i+1}. {a['nom']}", callback_data=f"loadAnime={a['id']}")]
            for i, a in enumerate(results)]
    await message.reply(
        "<b>⬇️ Qidiruv natijalari:</b>",
        parse_mode="HTML",
        reply_markup=InlineKeyboardMarkup(inline_keyboard=btns)
    )


# ════════════════════════════════════════════════════════════════
#                    🚀 MAIN
# ════════════════════════════════════════════════════════════════

async def main():
    logger.info("🚀 Anime Bot ishga tushmoqda...")
    init_db()

    try:
        bot_info = await bot.get_me()
        logger.info(f"✅ Bot: @{bot_info.username} ({bot_info.full_name})")
    except Exception as e:
        logger.error(f"❌ Token xato: {e}")
        return

    logger.info("🎌 Polling boshlandi!")
    await dp.start_polling(bot, allowed_updates=dp.resolve_used_update_types())


if __name__ == "__main__":
    asyncio.run(main())
