# main.py - نسخه نهایی، فقط یک فایل، همه چیز داخلشه
from aiogram import Bot, Dispatcher, types, F
from aiogram.filters import Command
from aiogram.types import (
    ReplyKeyboardMarkup, KeyboardButton,
    InlineKeyboardMarkup, InlineKeyboardButton
)
import jdatetime
from aiogram.filters import StateFilter
from datetime import datetime, timedelta
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.client.default import DefaultBotProperties
from datetime import datetime
import sqlite3
import asyncio
import re
from aiogram.types import ReplyKeyboardRemove
from aiogram import F, Router
from aiogram.types import Message, ReplyKeyboardRemove
from aiogram.fsm.context import FSMContext
from aiogram.filters import Command
from aiogram.fsm.state import StatesGroup, State
from datetime import datetime
import asyncio
import sqlite3
# تنظیمات
from config import BOT_TOKEN, admin_ids, CHANNEL_ID, PRICE

# دیتابیس
DB_FILE = "ads.db"
current_price = PRICE

# ساخت دیتابیس (اولین بار)
def init_db():
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()
    c.execute('''
        CREATE TABLE IF NOT EXISTS ads (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            user_id INTEGER,
            username TEXT,
            full_name TEXT,
            role TEXT,
            ad_text TEXT,
            contact TEXT,
            status TEXT DEFAULT 'pending',
            created_at TEXT
        )
    ''')
    conn.commit()
    conn.close()
init_db()  # دیتابیس ساخته بشه


# تبدیل تاریخ میلادی به شمسی
def to_jalali(iso_string: str) -> str:
    try:
        # مثلاً: 2025-08-02T14:30:22.123456
        dt = datetime.fromisoformat(iso_string.replace("Z", "+00:00"))
        jdt = jdatetime.datetime.fromgregorian(datetime=dt)
        return f"{jdt.year}/{jdt.month:02d}/{jdt.day:02d} ساعت {jdt.hour:02d}:{jdt.minute:02d}"
    except:
        return "نامشخص"

# تابع ذخیره آگهی در انتظار
def save_pending_ad(user_id, username, full_name, role, ad_text, contact):
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()
    now = datetime.now().strftime("%Y-%m-%d %H:%M")
    c.execute("""
        INSERT INTO ads (user_id, username, full_name, role, text, contact, status, created_at)
        VALUES (?, ?, ?, ?, ?, ?, 'pending', ?)
    """, (user_id, username, full_name, role, ad_text, contact, now))
    ad_id = c.lastrowid
    conn.commit()
    conn.close()
    return ad_id

# تعداد آگهی‌ها
def get_total_ads():
    try:
        conn = sqlite3.connect(DB_FILE)
        c = conn.cursor()
        c.execute("SELECT COUNT(*) FROM ads")
        total = c.fetchone()[0]
        conn.close()
        return total
    except:
        return 0

# ربات
bot = Bot(token=BOT_TOKEN, default=DefaultBotProperties(parse_mode="HTML"))
dp = Dispatcher(storage=MemoryStorage())

# وضعیت‌ها
class States(StatesGroup):
    normal = State()
    choosing_role = State()
    registering_ad = State()
    waiting_contact = State()
    # --- کیف پول ---
    wallet_menu = State()
    wallet_deposit = State()        
    wallet_withdraw = State()
    #--- برای گرفتن مبلغ از ادمین---
    waiting_deposit_amount = State()
    # --- برداشت ---
    withdrawing = State()   

# کیبوردها
def main_menu():
    return ReplyKeyboardMarkup(keyboard=[
        [KeyboardButton(text="ثبت آگهی جدید"), KeyboardButton(text="آگهی‌های من")],
        [KeyboardButton(text="کیف پول"), KeyboardButton(text="راهنما")]
    ], resize_keyboard=True)

def cancel_kb():
    return ReplyKeyboardMarkup(keyboard=[[KeyboardButton(text="لغو")]], resize_keyboard=True, one_time_keyboard=True)

def role_kb():
    return ReplyKeyboardMarkup(keyboard=[
        [KeyboardButton(text="کارفرما"), KeyboardButton(text="کارجو")],
        [KeyboardButton(text="انجام‌دهنده"), KeyboardButton(text="درخواست‌کننده")],
        [KeyboardButton(text="لغو")]
    ], resize_keyboard=True)

# چک موجودی
async def has_enough_balance(user_id: int) -> bool:
    return current_price == 0

# شروع
def add_or_update_user(user: types.User):
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()
    now = datetime.now().strftime("%Y-%m-%d %H:%M")
    c.execute("""
        INSERT INTO users (user_id, username, full_name, joined_at, last_active)
        VALUES (?, ?, ?, ?, ?)
        ON CONFLICT(user_id) DO UPDATE 
        SET username = ?, full_name = ?, last_active = ?
    """, (
        user.id,
        user.username or "ندارد",
        user.full_name or "بدون نام",
        now, now,
        user.username or "ندارد",
        user.full_name or "بدون نام",
        now
    ))
    conn.commit()
    conn.close()

# کامند استارت 
@dp.message(Command("start"))
async def start(message: types.Message, state: FSMContext):
    add_or_update_user(message.from_user)  
    await state.set_state(States.normal)
    await message.answer(
        f"🎯 سلام، به ربات <b>پروژه دانشجویی</b> خوش آمدید\n\n"
        f"ثبت آگهی کار، پروژه و خدمات دانشجویی\n"
        f"💰 هزینه ثبت آگهی: <b>{current_price:,} تومان</b>\n\n"
        f"لطفاً گزینه مورد نظر را انتخاب کنید:",
        reply_markup=main_menu(),
        parse_mode="HTML"
    )

# گرفتن موجودی کاربر 
def get_balance(user_id: int) -> int:
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()
    c.execute("SELECT balance FROM users WHERE user_id = ?", (user_id,))
    row = c.fetchone()
    conn.close()
    return row[0] if row else 0

# کسر موجودی کاربر برای ثبت آگهی 
def deduct_balance(user_id: int, amount: int) -> bool:
    """اگر موجودی کافی بود، کسر کنه و True برگردونه"""
    current = get_balance(user_id)
    if current >= amount:
        conn = sqlite3.connect(DB_FILE)
        c = conn.cursor()
        c.execute("UPDATE users SET balance = balance - ? WHERE user_id = ?", (amount, user_id))
        c.execute("UPDATE users SET ads_count = ads_count + 1 WHERE user_id = ?", (user_id,))
        conn.commit()
        conn.close()
        return True
    return False

# ثبت آگهی جدید 
@dp.message(F.text == "ثبت آگهی جدید", States.normal)
async def new_ad_start(message: types.Message, state: FSMContext):
    user_id = message.from_user.id
    balance = get_balance(user_id)  # موجودی از دیتابیس

    if balance >= current_price:
        # پول داره → برو انتخاب نقش 
        await state.set_state(States.choosing_role)
        await message.answer(
        f"لطفاً نقش خود را انتخاب کنید:",
        reply_markup=role_kb()
    )
    else:
        await message.answer(
            f"❌ موجودی کافی نیست\n\n"
            f"💰 موجودی فعلی: <b>{balance:,} تومان</b>\n"
            f"📋 هزینه آگهی: <b>{current_price:,} تومان</b>\n\n"
            f"لطفاً کیف پول خود را شارژ نمایید",
            reply_markup=main_menu()
        )
        
# انتخاب نقش
@dp.message(States.choosing_role)
async def role_selected(message: types.Message, state: FSMContext):
    if message.text == "لغو":
        await state.set_state(States.normal)
        await message.answer("لغو شد.", reply_markup=main_menu())
        return

    role_map = {
        "کارفرما": "کارفرما",
        "کارجو": "کارجو",
        "انجام‌دهنده": "انجام‌دهنده",
        "درخواست‌کننده": "درخواست‌کننده"
    }
    role = next((v for k, v in role_map.items() if k in message.text), None)
    
    # مثال مخصوص هر نقش
    examples = {
        "کارفرما": "مثال: به یک نیروی مسئولیت‌پذیر برای مدیریت سفارش‌ها و پاسخ‌گویی به مشتریان نیازمندیم. همکاری دورکاری است.",
        "کارجو": "مثال: سابقه ادمینی دارم، دوره‌های مرتبط را گذرانده‌ام و آماده همکاری با فروشگاه‌های آنلاین هستم.",
        "انجام‌دهنده": "مثال: مترجم زبان هستم و می‌توانم متن‌های عمومی و تخصصی را با کیفیت بالا ترجمه کنم.",
        "درخواست‌کننده": "مثال: به یک نفر جهت حل یک سؤال ریاضی و توضیح روش حل نیاز دارم."
    }

    example_text = examples.get(role, "")



    if not role:
        await message.answer("لطفاً یکی از دکمه‌ها را انتخاب کنید.")
        return

    await state.update_data(role=role)
    await state.set_state(States.registering_ad)
    await message.answer(
    f"نقش: <b>{role}</b>\n\n{example_text}\n\nحالا متن آگهی خود را ارسال کنید:",
    reply_markup=cancel_kb()
)

# دریافت متن آگهی
@dp.message(States.registering_ad)
async def receive_ad_text(message: types.Message, state: FSMContext):
    if message.photo:
        await message.answer("عکس مجاز نیست!")
        return
    if message.text == "لغو":
        await state.set_state(States.normal)
        await message.answer("لغو شد.", reply_markup=main_menu())
        return
    if len(message.text.strip()) < 50:
        await message.answer("متن خیلی کوتاه است! حداقل ۵۰ کاراکتر بنویسید.")
        return

    await state.update_data(ad_text=message.text.strip())
    await state.set_state(States.waiting_contact)
    await message.answer(
        "لطفاً شماره تلفن یا آیدی تلگرام خود را وارد کنید\n\n"
        "مثال:\n"
        "09123456789\n"
        "یا\n"
        "@username",
        reply_markup=cancel_kb()
    )

# دریافت شماره تلفن / آیدی 
@dp.message(States.waiting_contact)
async def receive_contact(message: types.Message, state: FSMContext):
    if message.text == "لغو":
        await state.set_state(States.normal)
        await message.answer("لغو شد.", reply_markup=main_menu())
        return

    contact = message.text.strip()

    # چک کردن وجود شماره و آیدی در متن
    phone_match = re.search(r"09\d{9}", contact)
    username_match = re.search(r"@\w{5,}", contact)
    
    # اگر هیچ کدام پیدا نشد
    if not phone_match and not username_match:
        await message.answer(
            "لطفاً حداقل شماره تلفن یا آیدی تلگرام را وارد کنید\n\n"
            "مثال:\n"
            "09123456789\n"
            "یا\n"
            "@username\n"
            "یا هر دو با هم:\n"
            "09123456789 @username"
        )
        return

    # استخراج اطلاعات
    phone = phone_match.group() if phone_match else None
    username = username_match.group() if username_match else None
    
    # ترکیب اطلاعات تماس
    contact_info = ""
    if phone and username:
        contact_info = f"{phone} - {username}"
    elif phone:
        contact_info = phone
    elif username:
        contact_info = username

    data = await state.get_data()
    u = message.from_user

    # اگر قیمت صفر نباشه → چک کن و کسر کن موجودی
    if current_price > 0:
        if not deduct_balance(u.id, current_price):
            balance = get_balance(u.id)
            await message.answer(
                f"موجودی حساب شما کافی نمی‌باشد\n\n"
                f"موجودی فعلی: <b>{balance:,} تومان</b>\n"
                f"هزینه ثبت آگهی: <b>{current_price:,} تومان</b>\n\n"
                f"لطفاً نسبت به شارژ کیف پول اقدام نمایید",
                reply_markup=main_menu()
            )

            await state.set_state(States.normal)
            return
        else:
            # پیام مناسب بده 
            new_balance = get_balance(u.id)
            await message.answer(
                f"هزینه آگهی با موفقیت کسر شد\n"
                f"موجودی باقی‌مانده: <b>{new_balance:,} تومان</b>\n\n"
                f"آگهی شما ثبت شد و در انتظار تأیید ادمین است...",
                reply_markup=main_menu()
            )
            # --- ثبت تراکنش در حال انتظار ---
            conn = sqlite3.connect(DB_FILE)
            c = conn.cursor()
            c.execute("""
                INSERT INTO transactions 
                (user_id, type, amount, status, description, related_id, created_at)
                VALUES (?, 'ad_payment', ?, 'pending', ?, ?, ?)
            """, (
                u.id,
                current_price,
                f"پرداخت برای آگهی (در انتظار تأیید ادمین)",
                None,  # فعلاً ad_id نداریم
                datetime.now().isoformat()
            ))
            transaction_id = c.lastrowid
            conn.commit()
            conn.close()

            # ذخیره transaction_id موقت در state تا بعد از ذخیره آگهی ست کنیم
            await state.update_data(transaction_id=transaction_id)

    else:
        # قیمت صفر = رایگان
        await message.answer(
            "آگهی رایگان شما ثبت شد و در انتظار تأیید ادمین است...",
            reply_markup=main_menu()
        )

    # ذخیره آگهی در دیتابیس
    ad_id = save_pending_ad(
        user_id=u.id,
        username="@" + (u.username or "ندارد"),
        full_name=u.full_name or "بدون نام",
        role=data["role"],
        ad_text=data["ad_text"],
        contact=contact_info  # استفاده از contact_info ترکیبی
    )

    # ست کردن ad_id داخل تراکنش ثبت شده قبلی
    data = await state.get_data()
    if "transaction_id" in data:
        conn = sqlite3.connect(DB_FILE)
        c = conn.cursor()
        c.execute("UPDATE transactions SET related_id = ? WHERE id = ?", (ad_id, data["transaction_id"]))
        conn.commit()
        conn.close()

    # وضعیت رو برگردون به حالت عادی
    await state.set_state(States.normal)

    # پیام به ادمین‌ها
    text = f"""
آگهی جدید در انتظار تأیید

نقش: {data['role']}
کاربر: {u.full_name} (@{u.username or 'ندارد'})
آیدی عددی: <code>{u.id}</code>
تماس: {contact_info}

متن آگهی:
{data['ad_text']}

آیدی آگهی: <code>{ad_id}</code>
"""

    kb = InlineKeyboardMarkup(inline_keyboard=[[
        InlineKeyboardButton(text="تأیید و انتشار", callback_data=f"approve_{ad_id}"),
        InlineKeyboardButton(text="رد کردن", callback_data=f"reject_{ad_id}")
    ]])

    for admin_id in admin_ids:
        try:
            await bot.send_message(admin_id, text, reply_markup=kb, parse_mode="HTML")
        except:
            pass  # اگه بلاک کرده باشه، بی‌خیال
        
# تأیید آگهی
@dp.callback_query(F.data.startswith("approve_"))
async def approve_ad(call: types.CallbackQuery):
    if call.from_user.id not in admin_ids:
        await call.answer("شما ادمین نیستید!", show_alert=True)
        return

    try:
        ad_id = int(call.data.split("_")[1])
    except:
        await call.answer("آیدی نامعتبر!", show_alert=True)
        return

    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()

    # فقط اگه واقعاً pending باشه اجازه بده
    c.execute("SELECT user_id, status FROM ads WHERE id = ?", (ad_id,))
    row = c.fetchone()
    
    if not row:
        await call.answer("آگهی پیدا نشد!", show_alert=True)
        conn.close()
        return

    user_id, current_status = row

    if current_status != "pending":
        status_text = "تأیید شده" if current_status == "approved" else "رد شده"
        await call.answer(f"این آگهی قبلاً {status_text}!", show_alert=True)
        await call.message.edit_text(f"آگهی {ad_id} قبلاً {status_text}")
        conn.close()
        return

    # حالا اطلاعات آگهی رو بگیر
    c.execute("SELECT role, text, contact, username FROM ads WHERE id = ?", (ad_id,))
    row = c.fetchone()
    if not row:
        await call.answer("خطا در دریافت اطلاعات آگهی")
        conn.close()
        return

    role, ad_text, contact, username = row
    username = username or "ندارد"

    # ایموجی نقش
    role_emojis = {
        "کارفرما": "🔴",
        "کارجو": "🟡",
        "انجام‌دهنده": "🟢",
        "درخواست‌کننده": "🔵"
    }
    role_emoji = role_emojis.get(role, "آگهی")

    # پیام حرفه‌ای و زیبا برای کانال
    channel_text = f"""
{role_emoji} <b>{role}</b>

{ad_text.strip()}

🆔 {contact}
┄┄┄┄┄┄┄┄┄┄┄┄
@Coffinet_onlinee | پروژه دانشجویی
"""

    try:
        sent_msg = await bot.send_message(
            chat_id=CHANNEL_ID,
            text=channel_text,
            parse_mode="HTML",
            disable_web_page_preview=True,
            reply_markup=channel_kb   # ⭐ همین یک خط
        )

        # ساخت لینک عمومی
        if str(CHANNEL_ID).startswith("-100"):
            public_link = f"https://t.me/c/{str(CHANNEL_ID)[4:]}/{sent_msg.message_id}"
        else:
            public_link = f"https://t.me/{str(CHANNEL_ID).replace('@', '')}/{sent_msg.message_id}"

        # آپدیت دیتابیس: استاتوس + لینک + آیدی پیام
        c.execute("""
            UPDATE ads 
            SET status = 'approved',
                channel_message_id = ?,
                message_link = ?
            WHERE id = ?
        """, (sent_msg.message_id, public_link, ad_id))

        # --- آپدیت تراکنش به وضعیت موفق completed ---
        c.execute("""
            UPDATE transactions
            SET status = 'completed', processed_at = ?
            WHERE related_id = ? AND type = 'ad_payment' AND status = 'pending'
        """, (datetime.now().isoformat(), ad_id))


        conn.commit()
        conn.close()

        # دکمه برای کاربر
        user_kb = InlineKeyboardMarkup(inline_keyboard=[
            [InlineKeyboardButton(text="آگهی واگذار شد / واگذار شد", callback_data=f"expired_{ad_id}")]
        ])

        # پیام به کاربر
        try:
            await bot.send_message(
                user_id,
                f"✅ آگهی شما با موفقیت در کانال منتشر شد\n\n"
                f"🔗 لینک مستقیم آگهی:\n{public_link}\n\n"
                f"در صورت واگذاری یا اتمام پروژه، می‌توانید آگهی را واگذار نمایید:",
                reply_markup=user_kb
            )
        except:
            pass

        # پیام به ادمین
        try:
            await call.message.edit_text(
                f"آگهی {ad_id} با موفقیت منتشر شد\n\n"
                f"لینک: {public_link}",
                disable_web_page_preview=True
            )
        except:
            pass

        await call.answer("با موفقیت منتشر شد")

    except Exception as e:
        await call.answer("خطا در ارسال به کانال", show_alert=True)
        try:
            await call.message.edit_text(f"خطا در انتشار:\n<code>{str(e)[:200]}</code>")
        except:
            pass
        conn.close()

# --- دکمه زیر پست کانال ---
channel_kb = InlineKeyboardMarkup(inline_keyboard=[
    [
        InlineKeyboardButton(
            text="📨 ثبت آگهی شما", 
            url=f"https://t.me/{'prozheh_daneshjuyibot'}?start=add_ad"
        )
    ]
])


# رد آگهی
@dp.callback_query(F.data.startswith("reject_"))
async def reject_ad(call: types.CallbackQuery):
    if call.from_user.id not in admin_ids:
        await call.answer("شما ادمین نیستید!", show_alert=True)
        return

    ad_id = int(call.data.split("_")[1])

    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()

    # فقط اگه pending باشه
    c.execute("SELECT user_id FROM ads WHERE id = ? AND status = 'pending'", (ad_id,))
    row = c.fetchone()
    if not row:
        await call.message.edit_text(f"آگهی {ad_id} قبلاً بررسی شده")
        conn.close()
        return

    user_id = row[0]

    # استاتوس به rejected + پول برگردونده شد
    c.execute("UPDATE ads SET status = 'rejected' WHERE id = ?", (ad_id,))
    c.execute("UPDATE users SET balance = balance + ? WHERE user_id = ?", (current_price, user_id))

    # --- آپدیت تراکنش به رد شده ---
    c.execute("""
        UPDATE transactions
        SET status = 'rejected', processed_at = ?
        WHERE related_id = ? AND type = 'ad_payment' AND status = 'pending'
    """, (datetime.now().isoformat(), ad_id))


    conn.commit()
    conn.close()

    # پیام به کاربر
    try:
        await bot.send_message(
            user_id,
            f"❌ آگهی شما تأیید نشد\n\n"
            f"مبلغ <b>{current_price:,} تومان</b> به کیف پول شما بازگردانده شد\n"
            f"موجودی جدید: <b>{get_balance(user_id):,} تومان</b>\n\n"
            f"لطفاً قوانین را رعایت کرده و مجدداً اقدام نمایید",
            parse_mode="HTML"
        )
    except:
        pass

    await call.message.edit_text(f"آگهی {ad_id} رد شد\nمبلغ به کاربر بازگشت")
    await call.answer("رد شد")

# دکمه "آگهی واگذار شد / واگذار شد"
@dp.callback_query(F.data.startswith("expired_"))
async def mark_ad_as_expired(call: types.CallbackQuery):
    try:
        ad_id = int(call.data.split("_")[1])
    except:
        await call.answer("خطا در آیدی آگهی", show_alert=True)
        return

    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()

    # اطلاعات آگهی: آیدی پیام کانال + وضعیت
    c.execute("SELECT channel_message_id, status FROM ads WHERE id = ?", (ad_id,))
    row = c.fetchone()

    if not row:
        await call.answer("آگهی پیدا نشد!", show_alert=True)
        conn.close()
        return

    channel_msg_id, current_status = row

    if current_status != "approved":
        await call.answer("این آگهی قبلاً واگذار یا رد شده!", show_alert=True)
        conn.close()
        return

    # اطلاعات قبلی برای ادیت
    c.execute("SELECT role, text FROM ads WHERE id = ?", (ad_id,))
    row2 = c.fetchone()
    role = row2[0] if row2 else "آگهی"
    ad_text = row2[1] if row2 else ""


    # پیام جدید: تماس حذف شد + واگذار شد
    expired_text = f"""
    <b>{role}</b>

{ad_text.strip()}

آگهی واگذار شد ❌
┄┄┄┄┄┄┄┄┄┄┄┄
@Coffinet_onlinee | پروژه دانشجویی
"""

    try:
        # ادیت پیام در کانال
        await bot.edit_message_text(
            chat_id=CHANNEL_ID,
            message_id=channel_msg_id,
            text=expired_text,
            parse_mode="HTML",
            disable_web_page_preview=True,
            reply_markup=channel_kb  
        )


        # آپدیت دیتابیس که دیگه تکرار نشه
        c.execute("UPDATE ads SET status = 'expired' WHERE id = ?", (ad_id,))
        conn.commit()

        # پیام به کاربر
        await call.answer("آگهی با موفقیت واگذار شد", show_alert=True)
        await call.message.edit_text("آگهی شما با موفقیت به عنوان «واگذار شده» علامت‌گذاری شد")

    except Exception as e:
        if "message is not modified" in str(e):
            await call.answer("این آگهی قبلاً واگذار شده!", show_alert=True)
        else:
            await call.answer("خطا در واگذار کردن آگهی", show_alert=True)
            print(f"خطا در expired: {e}")
    finally:
        conn.close()

# کیبرد کیف پول 
def wallet_menu_kb():
    return ReplyKeyboardMarkup(
        keyboard=[
            [KeyboardButton(text="برداشت از کیف پول"), KeyboardButton(text="واریز به کیف پول")],
            [KeyboardButton(text="تراکنش‌های من")],
            [KeyboardButton(text="بازگشت به منوی اصلی")]
        ],
        resize_keyboard=True
    )

# نمایش منوی کیف پول
@dp.message(F.text == "کیف پول", States.normal)
async def wallet_main(message: types.Message, state: FSMContext):
    balance = get_balance(message.from_user.id)  # تابعتو داری دیگه؟
    await state.set_state(States.wallet_menu)
    await message.answer(
        f"💰 کیف پول شما\n\n"
        f"موجودی فعلی: <b>{balance:,} تومان</b>\n\n"
        f"چه کاری می‌خواهید انجام دهید؟",
        reply_markup=wallet_menu_kb(),
        parse_mode="HTML"
    )

# دکمه بازگشت به منوی اصلی
@dp.message(F.text == "بازگشت به منوی اصلی", States.wallet_menu)
async def back_to_main(message: types.Message, state: FSMContext):
    await state.set_state(States.normal)
    await message.answer("به منوی اصلی برگشتید", reply_markup=main_menu())

# نمایش همه تراکنش های کاربر
@dp.message(F.text == "تراکنش‌های من", States.wallet_menu)
async def show_transactions(message: types.Message):
    user_id = message.from_user.id
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()
    c.execute("""
        SELECT type, amount, status, description, created_at 
        FROM transactions 
        WHERE user_id = ? 
        ORDER BY id DESC LIMIT 20
    """, (user_id,))
    rows = c.fetchall()
    conn.close()

    if not rows:
        return await message.answer("💼 هنوز تراکنشی نداری")

    text = "📋 تراکنش‌های شما:\n\n"

    for typ, amount, status, desc, created in rows:
        # مپینگ کامل انواع تراکنش
        type_map = {
            "ad_payment": {"emoji": "📢", "text": "ثبت آگهی"},
            "withdraw": {"emoji": "💳", "text": "درخواست برداشت"},
            "deposit": {"emoji": "💰", "text": "واریز به کیف پول"}, 
            "refund": {"emoji": "↩️", "text": "بازگشت وجه"},
            "admin_adjust": {"emoji": "👨‍💼", "text": "تنظیم توسط ادمین"}
        }
        
        type_info = type_map.get(typ, {"emoji": "🔧", "text": typ})
        
        # وضعیت
        status_map = {
            "completed": "✅ تأیید شده",
            "rejected": "❌ رد شده",
            "approved": "✅ تأیید شده", 
            "pending": "⏳ در انتظار"
        }
        status_text = status_map.get(status, status)

        # علامت مبلغ
        if typ == "withdraw":
            amount_display = f"{-amount:,}"  
        elif typ == "ad_payment":  
            amount_display = f"{-amount:,}" 
        elif typ == "deposit":
            amount_display = f"+{amount:,}" 
        elif typ == "refund":
            amount_display = f"+{amount:,}" 
        elif typ == "admin_adjust":
            # تنظیم دستی توسط ادمین
            if amount > 0:
                amount_display = f"+{amount:,}"  
            else:
                amount_display = f"{amount:,}"   
        else:
            amount_display = f"{amount:,}"  
                

        jalali_date = to_jalali(created)

        text += f"{type_info['emoji']} {type_info['text']}\n"
        text += f"{status_text} • مبلغ: <b>{amount_display}</b> تومان\n"
        text += f"📅 {jalali_date}\n\n"

    await message.answer(text, reply_markup=wallet_menu_kb(), parse_mode="HTML")

# منوی مخصوص حالت انتظار عکس (فقط یه دکمه لغو)
def deposit_cancel_kb():
    return ReplyKeyboardMarkup(
        keyboard=[
            [KeyboardButton(text="لغو واریز و بازگشت")]
        ],
        resize_keyboard=True
    )

# شروع واریز
@dp.message(F.text == "واریز به کیف پول", States.wallet_menu)
async def wallet_deposit_start(message: types.Message, state: FSMContext):
    text = (
    "💳 واریز به کیف پول\n\n"
    "درگاه پرداخت:\n"
    "نام گیرنده: <b>شهریار عدالتی</b>\n"
    "شماره کارت: <code>6280231552094947</code>\n"
    "بانک: بانک مسکن\n\n"
    "پس از واریز، عکس فیش را ارسال کنید\n"
    "فقط عکس قابل قبول می‌باشد"
)
    await state.set_state(States.wallet_deposit)
    
    # یه پیام + کیبورد جدید
    await message.answer(
        text,
        parse_mode="HTML",
        reply_markup=deposit_cancel_kb(),
        disable_web_page_preview=True
    )

# فقط عکس قبول کن، بقیه چیزها رو نادیده بگیر
@dp.message(States.wallet_deposit)
async def wallet_deposit_receive_photo(message: types.Message, state: FSMContext):
    # دکمه لغو
    if message.text == "لغو واریز و بازگشت":
        await state.set_state(States.wallet_menu)
        await message.answer(
            "عملیات واریز لغو شد\nبرگشتید به منوی کیف پول",
            reply_markup=wallet_menu_kb()
        )
        return

    # اگه چیزی غیر از عکس بود → هیچی نگو
    if not message.photo:
        return
    
    photo = message.photo[-1]

    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()

    c.execute("""
        INSERT INTO transactions 
        (user_id, type, amount, status, screenshot_message_id, created_at) 
        VALUES (?, 'deposit', 0, 'pending', ?, ?)
    """, (message.from_user.id, message.message_id, datetime.now().isoformat())) 
    
    transaction_id = c.lastrowid
    conn.commit()
    conn.close()

    admin_text = (
        f"درخواست واریز جدید\n\n"
        f"کاربر: <a href='tg://user?id={message.from_user.id}'>{message.from_user.full_name}</a>\n"
        f"آیدی عددی: <code>{message.from_user.id}</code>\n"
        f"تاریخ: {message.date.strftime('%Y-%m-%d %H:%M')}\n\n"
        f"عکس فیش واریزی:"
    )

    # ۱) دکمه تأیید رو برگردون (فقط این قسمت رو تو admin_kb عوض کن)
    admin_kb = InlineKeyboardMarkup(inline_keyboard=[
        [
            InlineKeyboardButton(text="تأیید واریز", callback_data=f"deposit_approve_{transaction_id}_{message.from_user.id}"),
            InlineKeyboardButton(text="رد واریز", callback_data=f"deposit_reject_{transaction_id}_{message.from_user.id}")
        ]
    ])

    for admin_id in admin_ids:
        try:
            await bot.send_photo(
                chat_id=admin_id,
                photo=photo.file_id,
                caption=admin_text,
                parse_mode="HTML",
                reply_markup=admin_kb
            )
        except:
            pass

    await message.answer(
        "عکس فیش شما با موفقیت ارسال شد!\n"
        "در حال بررسی توسط ادمین...\n"
        "به محض بررسی، بهت خبر میدم",
        reply_markup=wallet_menu_kb()
    )
    await state.set_state(States.wallet_menu)

# تأیید واریز 
@dp.callback_query(F.data.startswith("deposit_approve_"))
async def deposit_approve_start(call: types.CallbackQuery, state: FSMContext):
    if call.from_user.id not in admin_ids:
        await call.answer("شما ادمین نیستید!", show_alert=True)
        return

    try:
        _, _, transaction_id, user_id = call.data.split("_")
        transaction_id = int(transaction_id)
        user_id = int(user_id)
    except:
        await call.answer("خطا در پردازش", show_alert=True)
        return

    # ذخیره اطلاعات
    await state.update_data(
        deposit_trans_id=transaction_id,
        deposit_user_id=user_id
    )
    await state.set_state(States.waiting_deposit_amount)

    # حذف دکمه‌ها از پیام اصلی
    await call.message.edit_reply_markup(reply_markup=None)

    # پیام جدید به ادمین
    await bot.send_message(
        chat_id=call.from_user.id,
        text=(
            f"تأیید واریز کاربر:\n"
            f"<a href='tg://user?id={user_id}'>مشاهده پروفایل</a>\n\n"
            f"مبلغ واریزی رو به تومان وارد کن:\n"
            f"(مثلاً: 50000)"
        ),
        parse_mode="HTML"
    )
    await call.answer("مبلغ رو وارد کن")

# دریافت مبلغ از ادمین 
@dp.message(F.text.regexp(r"^\d{4,10}$"), States.waiting_deposit_amount)
async def deposit_amount_received(message: types.Message, state: FSMContext):
    if message.from_user.id not in admin_ids:
        return

    data = await state.get_data()
    if "deposit_trans_id" not in data:
        return

    try:
        amount = int(message.text.replace(",", "").strip())
        if amount < 1000:
            await message.answer("مبلغ خیلی کمه! حداقل ۱۰۰۰ تومان")
            return
    except:
        await message.answer("فقط عدد وارد کن! (مثلاً 50000)")
        return

    trans_id = data["deposit_trans_id"]
    user_id = data["deposit_user_id"]
    admin_id = message.from_user.id

    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()

    # ثبت مبلغ + تأیید
    c.execute("""
        UPDATE transactions 
        SET amount = ?, status = 'approved', processed_by = ?, processed_at = CURRENT_TIMESTAMP 
        WHERE id = ?
    """, (amount, admin_id, trans_id))

    # شارژ کیف پول
    c.execute("UPDATE users SET balance = balance + ? WHERE user_id = ?", (amount, user_id))
    conn.commit()
    conn.close()

    # پیام به کاربر
    try:
        await bot.send_message(
            user_id,
            f"✅ واریز {amount:,} تومان با موفقیت تأیید شد\n\n"
            f"موجودی کیف پول شما شارژ شد",
            parse_mode="HTML",
            reply_markup=wallet_menu_kb()
        )
    except:
        pass

    # پیام به ادمین
    await message.answer(
        f"موفقیت‌آمیز!\n"
        f"{amount:,} تومان به کیف پول کاربر اضافه شد",
        parse_mode="HTML"
    )

    await state.clear()

# رد واریز
@dp.callback_query(F.data.startswith("deposit_reject_"))
async def deposit_reject(call: types.CallbackQuery):
    if call.from_user.id not in admin_ids:
        await call.answer("شما ادمین نیستید!", show_alert=True)
        return

    try:
        _, _, transaction_id, user_id = call.data.split("_")
        transaction_id = int(transaction_id)
        user_id = int(user_id)
    except:
        await call.answer("خطا در پردازش", show_alert=True)
        return

    # آپدیت تراکنش
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()
    c.execute("UPDATE transactions SET status = 'rejected', processed_by = ?, processed_at = CURRENT_TIMESTAMP WHERE id = ?", 
              (call.from_user.id, transaction_id))
    conn.commit()
    conn.close()

    # پیام به کاربر
    try:
        await bot.send_message(
            user_id,
            "❌ فیش واریزی شما تأیید نشد\n\n"
            "در صورت اعتراض، مستقیم به ادمین پیام ارسال کنید",
            reply_markup=wallet_menu_kb()
        )
    except:
        pass

    await call.message.edit_caption(
        caption=call.message.caption + "\n\nرد شده توسط ادمین",
        reply_markup=None
    )
    await call.answer("رد شد")

# کیبورد لغو برداشت
def withdraw_cancel_kb():
    return ReplyKeyboardMarkup(
        keyboard=[[KeyboardButton(text="لغو برداشت")]],
        resize_keyboard=True
    )

# برداشت از کیف پول مرحله 1 
@dp.message(F.text == "برداشت از کیف پول", States.wallet_menu)
async def withdraw_enter(message: types.Message, state: FSMContext):
    user_id = message.from_user.id
    balance = get_balance(user_id)

    if balance < 20000:
        await message.answer(
            "موجودی شما کمتر از ۲۰,۰۰۰ تومان است\n\n"
            "امکان برداشت وجود ندارد",
            reply_markup=wallet_menu_kb()
        ) 
        return

    # چک قفل ۲۴ ساعته
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()
    c.execute("SELECT card_holder, card_number, last_withdraw_request FROM users WHERE user_id = ?", (user_id,))
    row = c.fetchone()
    conn.close()

    card_holder = row[0] if row else None
    card_number = row[1] if row else None
    last_req = row[2] if row and len(row) > 2 else None

    if last_req:
            try:
                last_time = datetime.fromisoformat(last_req)
            except:
                last_time = None  
            if last_time:
                time_limit = timedelta(hours=24)        ################################## ۲۴ ساعت اصلی

                time_passed = datetime.now() - last_time

                if time_passed < time_limit:
                    remaining = time_limit - time_passed
                    hours = remaining.seconds // 3600
                    minutes = (remaining.seconds % 3600) // 60
                    seconds = remaining.seconds % 60

                    if hours > 0:
                        remain_text = f"{hours} ساعت و {minutes} دقیقه"
                    elif minutes > 0:
                        remain_text = f"{minutes} دقیقه و {seconds} ثانیه"
                    else:
                        remain_text = f"{seconds} ثانیه"

                    await message.answer(
                        f"امکان برداشت تنها هر ۲۴ ساعت یکبار وجود دارد\n\n"
                        f"می‌توانید پس از {remain_text} مجدداً اقدام نمایید",
                        reply_markup=wallet_menu_kb()
                    )
                    return

    # متن حرفه‌ای و واضح
    if card_holder and card_number:
        text = (
            f"کارت ثبت‌شده شما:\n\n"
            f"نام صاحب کارت: <b>{card_holder}</b>\n"
            f"شماره کارت: <code>{card_number}</code>\n\n"
            f"اگه با همین کارت موافقی → فقط مبلغ برداشت رو وارد کن\n"
            f"اگه می‌خوای کارت جدید ثبت کنی → نام و شماره کارت جدید رو در دو خط بفرست\n\n"
            f"برای انصراف → دکمه «لغو برداشت» رو بزن"
        )
    else:
        text = (
            "برای برداشت باید شماره کارت ثبت کنی\n\n"
            "لطفاً اطلاعات کارت رو به این صورت بفرست:\n\n"
            "<code>نام صاحب کارت\nشماره کارت ۱۶ رقمی</code>\n\n"
            "مثال:\n"
            "<code>علی احمدی\n6037991234567890</code>\n\n"
            "برای انصراف → دکمه «لغو برداشت» رو بزن"
        )

    await message.answer(text, parse_mode="HTML", reply_markup=withdraw_cancel_kb())
    await state.set_state(States.withdrawing)

# لغو برداشت 
@dp.message(States.withdrawing, F.text == "لغو برداشت")
async def withdraw_cancel(message: types.Message, state: FSMContext):
    await state.clear()
    await state.set_state(States.wallet_menu)   # این خط طلاییه!

    await message.answer("برداشت لغو شد", reply_markup=wallet_menu_kb())

# دریافت شماره کارت یا مبلغ 
@dp.message(States.withdrawing)
async def withdraw_process(message: types.Message, state: FSMContext):
    user_id = message.from_user.id
    text = message.text.strip()

    # ۱- لغو 
    if text == "لغو برداشت":
        await state.clear()
        await state.set_state(States.wallet_menu)
        await message.answer("برداشت لغو شد", reply_markup=wallet_menu_kb())
        return

    # ۲- کاربر عدد فرستاده (یعنی مبلغ می‌خواد)
    if text.replace(",", "").isdigit():
        amount = int(text.replace(",", ""))

        # چک محدوده مبلغ
        if amount < 20000:
            await message.answer("حداقل مبلغ برداشت: ۲۰,۰۰۰ تومان")            
            return
        if amount > 1000000:
            await message.answer("حداکثر مبلغ برداشت: ۱,۰۰۰,۰۰۰ تومان")
            return

        balance = get_balance(user_id)
        if amount > balance:
            await message.answer("موجودی شما کافی نمی‌باشد")
            return

        # چک کنه کارت داره یا نه
        conn = sqlite3.connect(DB_FILE)
        c = conn.cursor()
        c.execute("SELECT card_holder, card_number FROM users WHERE user_id = ?", (user_id,))
        row = c.fetchone()
        conn.close()

        if not row or not row[0] or not row[1]:
            await message.answer(
                "برای برداشت باید شماره کارت خود را ثبت کنید\n\n"
                "لطفاً اطلاعات کارت را به صورت زیر ارسال کنید:\n\n"
                "نام صاحب کارت\n"
                "شماره کارت ۱۶ رقمی\n\n"
                "مثال:\n"
                "علی احمدی\n"
                "6037991234567890"
            )
            return

        card_holder, card_number = row[0], row[1]

        # ثبت درخواست + کسر فوری از کیف پول + قفل زمانی
        conn = sqlite3.connect(DB_FILE)
        c = conn.cursor()

        # ۱- کسر فوری از کیف پول 
        c.execute("UPDATE users SET balance = balance - ? WHERE user_id = ?", (amount, user_id))

        # ۲- ثبت تراکنش با وضعیت "در انتظار"
        c.execute("""
            INSERT INTO transactions 
            (user_id, type, amount, status, created_at) 
            VALUES (?, 'withdraw', ?, 'pending', ?)
        """, (user_id, amount, datetime.now().isoformat()))

        trans_id = c.lastrowid

        # ۳- قفل زمانی 
        c.execute("UPDATE users SET last_withdraw_request = ? WHERE user_id = ?",
                (datetime.now().isoformat(), user_id))

        conn.commit()
        conn.close()

        # ارسال به ادمین
        admin_text = (
            f"درخواست برداشت جدید\n\n"
            f"کاربر: <a href='tg://user?id={user_id}'>{message.from_user.full_name}</a>\n"
            f"آیدی: <code>{user_id}</code>\n"
            f"مبلغ: <b>{amount:,} تومان</b>\n"
            f"نام صاحب کارت: <b>{card_holder}</b>\n"
            f"شماره کارت: <code>{card_number}</code>\n"
            f"موجودی فعلی: {balance:,} تومان"
        )

        kb = InlineKeyboardMarkup(inline_keyboard=[[
            InlineKeyboardButton(text="تأیید و واریز", callback_data=f"withdraw_approve_{trans_id}"),
            InlineKeyboardButton(text="رد درخواست", callback_data=f"withdraw_reject_{trans_id}")
        ]])

        for admin_id in admin_ids:
            try:
                await bot.send_message(admin_id, admin_text, parse_mode="HTML", reply_markup=kb)
            except:
                pass

        await message.answer(
            f"درخواست برداشت {amount:,} تومان ثبت شد\n\n"
            "در حال بررسی توسط ادمین",
            reply_markup=wallet_menu_kb()
        )
        await state.set_state(States.wallet_menu)
        return

    # ۳- کاربر دو خط فرستاده (یعنی کارت جدید)
    lines = [l.strip() for l in text.split("\n") if l.strip()]
    if len(lines) == 2:
        holder = lines[0]
        number_raw = lines[1].replace(" ", "").replace("-", "")
        
        if not (number_raw.isdigit() and len(number_raw) == 16):
            await message.answer(
                "شماره کارت باید دقیقاً ۱۶ رقم و فقط عدد باشد\n\n"
                "لطفاً مجدداً ارسال کنید"
            )
            return

        # ذخیره کارت جدید
        conn = sqlite3.connect(DB_FILE)
        c = conn.cursor()
        c.execute("UPDATE users SET card_holder = ?, card_number = ? WHERE user_id = ?", 
                  (holder, number_raw, user_id))
        conn.commit()
        conn.close()

        await message.answer(
            f"شماره کارت با موفقیت ثبت شد\n\n"
            f"صاحب کارت: <b>{holder}</b>\n"
            f"شماره کارت: <code>{number_raw}</code>\n\n"
            f"لطفاً مبلغ برداشت را وارد کنید\n"
            f"(۲۰,۰۰۰ تا ۱,۰۰۰,۰۰۰ تومان)",
            parse_mode="HTML",
            reply_markup=withdraw_cancel_kb()
        )
        return

    # ۴- هر چیز دیگه (بدون واکنش)
    return

# تأیید برداشت (ادمین)
@dp.callback_query(F.data.startswith("withdraw_approve_"))
async def approve_withdraw(call: types.CallbackQuery):
    if call.from_user.id not in admin_ids:
        await call.answer("فقط ادمین می‌تونه!", show_alert=True)
        return

    trans_id = int(call.data.split("_")[2])

    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()

    # تغییر وضعیت تراکنش به تأیید شده
    c.execute("""
        UPDATE transactions 
        SET status = 'approved', processed_at = ?, processed_by = ? 
        WHERE id = ?
    """, (datetime.now().isoformat(), call.from_user.id, trans_id))

    # پیدا کردن کاربر و مبلغ
    c.execute("SELECT user_id, amount FROM transactions WHERE id = ?", (trans_id,))
    user_id, amount = c.fetchone()

    conn.commit()
    conn.close()

    # ویرایش پیام ادمین
    await call.message.edit_text(
        f"درخواست برداشت تأیید شد\n"
        f"مبلغ: {amount:,} تومان\n"
        f"واریز انجام شد",
        reply_markup=None
    )
    # پیام به کاربر
    await bot.send_message(
        user_id,
        f"✅ درخواست برداشت {amount:,} تومان شما تأیید شد\n\n"
        f"مبلغ به حساب شما واریز گردید\n\n"
        f"از اعتماد شما سپاسگزاریم",
        reply_markup=wallet_menu_kb()
    )

# رد درخواست (ادمین)
@dp.callback_query(F.data.startswith("withdraw_reject_"))
async def reject_withdraw(call: types.CallbackQuery):
    if call.from_user.id not in admin_ids:
        await call.answer("فقط ادمین می‌تونه!", show_alert=True)
        return

    trans_id = int(call.data.split("_")[2])

    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()

    # پیدا کردن کاربر و مبلغ
    c.execute("SELECT user_id, amount FROM transactions WHERE id = ?", (trans_id,))
    user_id, amount = c.fetchone()

    # برگردوندن پول به کیف پول
    c.execute("UPDATE users SET balance = balance + ? WHERE user_id = ?", (amount, user_id))

    # تغییر وضعیت تراکنش به ناموفق
    c.execute("""
        UPDATE transactions 
        SET status = 'rejected', processed_at = ?, processed_by = ? 
        WHERE id = ?
    """, (datetime.now().isoformat(), call.from_user.id, trans_id))

    conn.commit()
    conn.close()

    # ویرایش پیام ادمین
    await call.message.edit_text(
        f"درخواست برداشت رد شد\n"
        f"مبلغ: {amount:,} تومان\n"
        f"پول به کیف پول کاربر برگشت",
        reply_markup=None
    )

    # پیام به کاربر
    await bot.send_message(
        user_id,
        f"❌ درخواست برداشت {amount:,} تومان شما رد شد\n\n"
        f"مبلغ به کیف پول شما بازگردانده شد\n\n"
        f"در صورت اعتراض، مستقیم به ادمین پیام ارسال کنید",
        reply_markup=wallet_menu_kb()
    )

# راهنما
@dp.message(F.text == "راهنما")
async def help_command(message: types.Message):
    help_text = """
🤖 <b>این ربات چه می‌کند؟</b>

سلام به ربات درج آگهی به کانال پروژه دانشجویی خوش آمدید

کافیه قدم به قدم با ربات پیش برید

تا آگهی تون ثبت کنید

سوالی هم داشتید درخدمتم 👇
@Cafinetttt

آدرس کانال  👇
@Coffinet_onlinee

برای شروع استارت بزن 🌹

👤 <b>سازنده:</b>
@Dotfar1207
""".strip()

    await message.answer(
        help_text,
        parse_mode="HTML",
        disable_web_page_preview=True
    )

# دکمه اگهی های من
@dp.message(F.text == "آگهی‌های من", States.normal)
async def my_ads(message: types.Message):
    user_id = message.from_user.id
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()
    c.execute("""
        SELECT id, role, status, text, message_link
        FROM ads WHERE user_id = ?
        ORDER BY id DESC
    """, (user_id,))
    ads = c.fetchall()
    conn.close()

    if not ads:
        await message.answer("هنوز آگهی ثبت نکرده‌اید", reply_markup=main_menu())
        return

    expired = []
    pending = []
    active = []

    for ad in ads:
        ad_id, role, status, text, link = ad

        # پیش‌نمایش امن
        if not text or not text.strip():
            preview = "(متن آگهی موجود نیست)"
        else:
            words = text.strip().split()
            preview = " ".join(words[:8])
            if len(words) > 8:
                preview += " ..."

        if status == "expired":
            expired.append((ad_id, role, preview, link))
        elif status == "pending":
            pending.append((ad_id, role, preview))
        elif status == "approved":
            active.append((ad_id, role, preview, link or "https://t.me/Coffinet_onlinee"))

    # ۱) آگهی‌های واگذار شده — لینک دارن
    if expired:
        msg = "آگهی‌های واگذار شده شما:\n\n"
        for ad_id, role, preview, link in expired:
            msg += f"• [{role} — {preview}]({link})\n"
        await message.answer(msg, parse_mode="Markdown", disable_web_page_preview=True)

    # ۲) آگهی‌های در انتظار تأیید — بدون لینک، فقط متن
    if pending:
        msg = "آگهی‌های در انتظار تأیید ادمین:\n\n"
        for ad_id, role, preview in pending:
            msg += f"• {role} — {preview}\n"
        await message.answer(msg, disable_web_page_preview=True)

    # ۳) آگهی‌های فعال — هر کدوم یه پیام جدا + دکمه واگذار کردن (وصل به همون هندلر قبلی!)
    for ad_id, role, preview, link in active:
        kb = InlineKeyboardMarkup(inline_keyboard=[[
            InlineKeyboardButton(
                text="واگذار شد",
                callback_data=f"expired_{ad_id}"  # دقیقاً همون قبلی!
            )
        ]])

        caption = f"آگهی فعال شما:\n\n" \
                  f"نقش: {role}\n" \
                  f"{preview}\n\n" \
                  f"[مشاهده در کانال]({link})"

        await message.answer(
            caption,
            parse_mode="Markdown",
            reply_markup=kb,
            disable_web_page_preview=True
        )

    await message.answer("پایان لیست آگهی‌های شما", reply_markup=main_menu())



# ====================== پنل ادمین ======================
router = Router()

# وضعیت های مخصوص ادمین 
class AdminStates(StatesGroup):
    waiting_user_id = State()           # برای همه عملیات که نیاز به آیدی کاربر دارن
    waiting_amount = State()            # برای افزایش/کاهش موجودی
    waiting_broadcast = State()         # پیام همگانی
    waiting_pm_id = State()             # پیام خصوصی — مرحله اول
    waiting_pm_text = State()           # پیام خصوصی — مرحله دوم
    waiting_new_price = State()         # تغییر قیمت آگهی

# اآیا کاربر ادمین هست؟ 
def is_admin(user_id: int) -> bool:
    return user_id in admin_ids

# مشخص کردن ادمین اصلی 
def is_main_admin(user_id: int) -> bool:
    return user_id == admin_ids[0]  # اولین نفر تو لیست = ادمین اصلی 

# پیام پنل ادمینی 
ADMIN_HELP = """
🎛️ <b>پنل مدیریت ربات — پروژه دانشجویی</b>

سلام مدیر عزیز 🌹  
از اینجا می‌تونی همه بخش‌های ربات رو مدیریت کنی:

<b>👤 مدیریت ادمین‌ها (فقط برای ادمین اصلی)</b>
/add_admin        افزودن ادمین جدید  
/remove_admin     حذف یک ادمین  

<b>💰 مدیریت کیف پول کاربران</b>
/add_balance      افزایش موجودی  
/reduce_balance   کاهش موجودی  

<b>📢 پیام‌رسانی</b>
/broadcast        ارسال پیام همگانی  
/pm               ارسال پیام خصوصی به کاربر  

<b>⚙️ تنظیمات ربات</b>
/set_price        تنظیم هزینه ثبت آگهی  

<b>📄 درخواست‌ها و آگهی‌ها</b>
/pending_ads      مشاهده آگهی‌های در انتظار تأیید  
/withdraw_req     درخواست‌های برداشت  
/deposit_req      درخواست‌های واریز  

<b>📊 گزارش‌گیری و خروجی</b>
/export_db        خروجی کامل دیتابیس (اکسل)  
/admin_stats      گزارش آماری کامل ربات  

<b>/admin</b> → نمایش مجدد همین منو  
<b>/cancel</b> → بازگشت به حالت عادی
"""

# هندلر بازگشت به منوی عادی 
@router.message(Command("cancel"))
async def admin_cancel(message: Message, state: FSMContext):
    user_id = message.from_user.id

    # اگر ادمین نبود → هیچ کاری نکن
    if not is_admin(user_id):
        return 

    # اگر ادمین بود → همه استیت‌ها را پاک کن و ببر به حالت عادی
    await state.clear()
    await state.set_state(States.normal)

    await message.answer(
        "❎ عملیات لغو شد.\n"
        "🔧 به حالت عادی ادمین برگشتی.\n"
        "برای مشاهده پنل:\n/admin"
    )

# ورود به پنل 
@router.message(Command("admin"))
async def admin_panel(message: Message):
    if not is_admin(message.from_user.id):
        return await message.answer("دسترسی به پنل ادمین ندارید!")
    
    await message.answer(ADMIN_HELP.strip())

#افزودن ادمین (فقط ادمین اصلی) 
@router.message(Command("add_admin"))
async def add_admin_start(message: Message, state: FSMContext):
    if not is_main_admin(message.from_user.id):
        return await message.answer("فقط ادمین اصلی می‌تونه ادمین اضافه کنه!")
    await message.answer("آیدی عددی ادمین جدید رو بفرست:")
    await state.set_state(AdminStates.waiting_user_id)
    await state.set_data({"action": "add_admin"})

# حذف ادمین (فقط ادمین اصلی)
@router.message(Command("remove_admin"))
async def remove_admin_start(message: Message, state: FSMContext):
    if not is_main_admin(message.from_user.id):
        return await message.answer("فقط ادمین اصلی می‌تونه ادمین حذف کنه!")
    await message.answer("آیدی عددی ادمینی که می‌خوای حذف کنی رو بفرست:")
    await state.set_state(AdminStates.waiting_user_id)
    await state.set_data({"action": "remove_admin"})

# پردازش آیدی برای ادمین
@router.message(AdminStates.waiting_user_id)
async def process_admin_change(message: Message, state: FSMContext):
    if not message.text or not message.text.isdigit():
        return await message.answer("لطفاً فقط عدد بفرست!")
    
    target_id = int(message.text)
    data = await state.get_data()
    action = data.get("action")

    if target_id == message.from_user.id:
        return await message.answer("نمی‌تونی خودتو اضافه یا حذف کنی!")

    if action == "add_admin":
        if target_id in admin_ids:
            await message.answer(f"این کاربر قبلاً ادمینه!\n<code>{target_id}</code>", parse_mode="HTML")
        else:
            admin_ids.append(target_id)
            await message.answer(f"ادمین جدید اضافه شد:\n<code>{target_id}</code>", parse_mode="HTML")
    
    elif action == "remove_admin":
        if target_id not in admin_ids:
            await message.answer("این آیدی ادمین نیست!")
        elif target_id == admin_ids[0]:
            await message.answer("نمی‌تونی ادمین اصلی رو حذف کنی!")
        else:
            admin_ids.remove(target_id)
            await message.answer(f"ادمین حذف شد:\n<code>{target_id}</code>", parse_mode="HTML")
    
    await state.clear()

# آمارگیری کلی از وضعیت کاربران 
@router.message(Command("admin_stats"))
async def admin_stats(message: Message):
    if not is_admin(message.from_user.id):
        return await message.answer("❌ دسترسی ندارید!")

    try:
        conn = sqlite3.connect(DB_FILE)
        c = conn.cursor()

        # تعداد کاربران
        c.execute("SELECT COUNT(*) FROM users")
        total_users = c.fetchone()[0]

        # مجموع موجودی کاربران
        c.execute("SELECT SUM(balance) FROM users")
        total_balance = c.fetchone()[0] or 0

        # آمار آگهی‌ها
        c.execute("SELECT COUNT(*) FROM ads")
        total_ads = c.fetchone()[0]

        c.execute("SELECT COUNT(*) FROM ads WHERE status='pending'")
        pending_ads = c.fetchone()[0]

        c.execute("SELECT COUNT(*) FROM ads WHERE status='approved'")
        approved_ads = c.fetchone()[0]

        c.execute("SELECT COUNT(*) FROM ads WHERE status='rejected'")
        rejected_ads = c.fetchone()[0]

        # درخواست‌های واریز / برداشت
        c.execute("SELECT COUNT(*) FROM transactions WHERE type='withdraw' AND status='pending'")
        withdraw_pending = c.fetchone()[0]

        c.execute("SELECT COUNT(*) FROM transactions WHERE type='deposit' AND status='pending'")
        deposit_pending = c.fetchone()[0]

        conn.close()

        report = f"""
        📈 <b>گزارش مدیریتی</b>

        👥 <b>کاربران:</b>
        کل کاربران: <b>{total_users:,}</b>
        مجموع موجودی: <b>{total_balance:,} تومان</b>

        📄 <b>آگهی‌ها:</b>
        کل آگهی‌ها: <b>{total_ads:,}</b>
        در انتظار تأیید: <b>{pending_ads:,}</b>
        تأیید شده: <b>{approved_ads:,}</b>
        رد شده: <b>{rejected_ads:,}</b>

        💳 <b>درخواست‌های مالی:</b>
        برداشت در انتظار: <b>{withdraw_pending:,}</b>
        واریز در انتظار: <b>{deposit_pending:,}</b>

        ✅ گزارش به روز رسانی شده
        """


        await message.answer(report, parse_mode="HTML")

    except Exception as e:
        await message.answer(f"❌ خطا:\n<code>{e}</code>", parse_mode="HTML")

# افزایش موجودی 
@router.message(Command("add_balance", ignore_mention=True))
async def add_balance_oneline(message: Message):
    if not is_admin(message.from_user.id):
        return await message.answer("دسترسی به پنل ادمین ندارید!")

    # جدا کردن آرگومان‌ها
    try:
        parts = message.text.split()
        if len(parts) != 3:
            return await message.answer(
                "فرمت دستور صحیح نمی‌باشد\n\n"
                "لطفاً از فرمت زیر استفاده کنید:\n"
                "<code>/add_balance 123456789 50000</code>",
                parse_mode="HTML"
            )

        user_id = int(parts[1])
        amount = int(parts[2])

        if amount <= 0:
            return await message.answer("مبلغ باید مثبت باشد")

    except ValueError:
        return await message.answer("آیدی و مبلغ باید عدد باشند")

    # اعمال افزایش موجودی
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()
    c.execute("UPDATE users SET balance = balance + ? WHERE user_id = ?", (amount, user_id))
    
    c.execute("""INSERT INTO transactions 
                 (user_id, type, amount, status, description, created_at) 
                 VALUES (?, 'admin_adjust', ?, 'completed', ?, ?)""",
              (user_id, amount, f"افزایش {amount:,} تومان توسط ادمین", datetime.now().isoformat()))
    conn.commit()
    conn.close()

    # پیام موفقیت به ادمین
    await message.answer(
        f"✅ موجودی کاربر با موفقیت افزایش یافت\n\n"
        f"کاربر: <code>{user_id}</code>\n"
        f"مبلغ اضافه شده: <b>{amount:,}</b> تومان\n"
        f"موجودی جدید: <b>{get_balance(user_id):,}</b> تومان",
        parse_mode="HTML"
    )

    # اطلاع به کاربر
    try:
        await bot.send_message(
            user_id,
            f"✅ موجودی کیف پول شما <b>{amount:,} تومان</b> افزایش یافت\n\n"
            f"موجودی جدید: <b>{get_balance(user_id):,}</b> تومان",
            parse_mode="HTML"
        )
    except:
        await message.answer("⚠️ کاربر پیام را دریافت نکرد")

# کاهش موجودی 
@router.message(Command("reduce_balance", ignore_mention=True))
async def reduce_balance_oneline(message: Message):
    if not is_admin(message.from_user.id):
        return await message.answer("دسترسی ندارید!")

    try:
        parts = message.text.split()
        if len(parts) != 3:
            return await message.answer(
            "فرمت دستور صحیح نمی‌باشد\n\n"
            "لطفاً از فرمت زیر استفاده کنید:\n"
            "<code>/reduce_balance 123456789 30000</code>",
            parse_mode="HTML"
        )

        user_id = int(parts[1])
        amount = int(parts[2])

        if amount <= 0:
            return await message.answer("مبلغ باید مثبت باشد")

        current = get_balance(user_id)
        if amount > current:
            return await message.answer(f"موجودی کاربر کافی نمی‌باشد\nموجودی فعلی: {current:,} تومان")

    except ValueError:
        return await message.answer("آیدی و مبلغ باید عدد باشند")

    # اعمال کاهش
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()
    c.execute("UPDATE users SET balance = balance - ? WHERE user_id = ?", (amount, user_id))
    c.execute("""INSERT INTO transactions 
                 (user_id, type, amount, status, description, created_at) 
                 VALUES (?, 'admin_adjust', ?, 'completed', ?, ?)""",
              (user_id, -amount, f"کاهش {amount:,} تومان توسط ادمین", datetime.now().isoformat()))
    conn.commit()
    conn.close()

    await message.answer(
        f"موفقیت!\n"
        f"کاربر: <code>{user_id}</code>\n"
        f"مبلغ کسر شده: <b>{amount:,}</b> تومان\n"
        f"موجودی جدید: <b>{get_balance(user_id):,}</b> تومان",
        parse_mode="HTML"
    )

    try:
        await bot.send_message(
            user_id,
            f"❌ از کیف پول شما <b>{amount:,} تومان</b> کسر شد\n\n"
            f"موجودی جدید: <b>{get_balance(user_id):,}</b> تومان",
            parse_mode="HTML"
        )
    except:
        pass

# ارسال پیام همگانی 
@router.message(Command("broadcast"))
async def broadcast_start(message: Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    await message.answer("لطفاً پیام همگانی را ارسال کنید\n\nمتن، عکس، ویدیو یا فوروارد قابل قبول می‌باشد")
    await state.set_state(AdminStates.waiting_broadcast)

# ارسال برادکست + گزارش دقیق 
@router.message(AdminStates.waiting_broadcast)
async def broadcast_send(message: Message, state: FSMContext):
    sent = failed = 0
    await message.answer("در حال ارسال به همه کاربران...")
    
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()
    c.execute("SELECT user_id FROM users")
    users = [row[0] for row in c.fetchall()]
    conn.close()

    for uid in users:
        try:
            await message.copy_to(uid)
            sent += 1
        except:
            failed += 1
        await asyncio.sleep(0.04)  # ضد بن
    
    await message.answer(f"✅ ارسال پیام همگانی به پایان رسید\n\nموفق: {sent}\nناموفق: {failed}")
    await state.clear()

#  پیام خصوصی 
@router.message(Command("pm"))
async def pm_start(message: Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    await message.answer("آیدی عددی کاربر رو بفرست:")
    await state.set_state(AdminStates.waiting_pm_id)

# دریافت آیدی عددی کاربر که قراره براش پیام خصوصی بفرستیم 
@router.message(AdminStates.waiting_pm_id)
async def pm_get_id(message: Message, state: FSMContext):
    if not message.text.isdigit(): return await message.answer("فقط عدد!")
    await state.update_data(target_id=int(message.text))
    await message.answer("پیام رو بفرست:")
    await state.set_state(AdminStates.waiting_pm_text)

# ارسال نهایی 
@router.message(AdminStates.waiting_pm_text)
async def pm_send(message: Message, state: FSMContext):
    data = await state.get_data()
    try:
        await message.copy_to(data["target_id"])
        await message.answer("پیام ارسال شد")
    except:
        await message.answer("ارسال نشد — کاربر بلاک کرده یا وجود نداره")
    await state.clear()

# تنظیم هزینه ثبت آگهی 
@router.message(Command("set_price"))
async def set_price_start(message: Message, state: FSMContext):
    if not is_admin(message.from_user.id): return
    await message.answer(f"💰 هزینه فعلی ثبت آگهی: {current_price:,} تومان\n\nلطفاً مبلغ جدید را وارد کنید:")
    await state.set_state(AdminStates.waiting_new_price)

# تنظیم هزینه 
@router.message(AdminStates.waiting_new_price)
async def set_price_done(message: Message, state: FSMContext):
    global current_price
    if not message.text.isdigit(): return await message.answer("فقط عدد!")
    current_price = int(message.text)
    await message.answer(f"✅ هزینه ثبت آگهی به {current_price:,} تومان تغییر یافت")
    await state.clear()

# آگهی های در انتظار تایید 
@router.message(Command("pending_ads"))
async def pending_ads(message: Message):
    if not is_admin(message.from_user.id):
        return await message.answer("دسترسی به پنل ادمین ندارید!")

    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()
    
    # فقط ستون‌های موجود تو دیتابیست
    c.execute("""SELECT id, user_id, text, photo, status, created_at 
                 FROM ads 
                 WHERE status = 'pending' 
                 ORDER BY id DESC""")
    pending_ads = c.fetchall()
    conn.close()

    if not pending_ads:
        return await message.answer("هیچ آگهی در انتظاری وجود ندارد")

    await message.answer(f"<b>آگهی‌های در انتظار تأیید ({len(pending_ads)} تا)</b>\nدکمه‌ها رو بزن:", parse_mode="HTML")

    for ad in pending_ads:
        ad_id, user_id, text, photo_file_id, status, created_at = ad

        # تاریخ قشنگ
        date = created_at.split("T")[0].replace("-", "/") if "T" in created_at else created_at[:10]

        caption = f"""
آگهی #{ad_id}
کاربر: <code>{user_id}</code>
تاریخ: {date}

{text}
        """.strip()

        # دکمه‌های تأیید و رد
        kb = InlineKeyboardMarkup(inline_keyboard=[
            [
                InlineKeyboardButton(text="تأیید و انتشار", callback_data=f"approve_{ad_id}"),
                InlineKeyboardButton(text="رد کردن", callback_data=f"reject_{ad_id}")
            ]
        ])

        try:
            if photo_file_id and photo_file_id.strip():
                await bot.send_photo(
                    chat_id=message.chat.id,
                    photo=photo_file_id,
                    caption=caption,
                    parse_mode="HTML",
                    reply_markup=kb
                )
            else:
                await message.answer(caption, parse_mode="HTML", reply_markup=kb)
        except Exception as e:
            await message.answer(f"خطا در ارسال آگهی #{ad_id}\nمتن:\n{text}", reply_markup=kb)

    await message.answer("✅ تمام آگهی‌های در انتظار تأیید نمایش داده شد")

#   درخواست‌های برداشت
@router.message(Command("withdraw_req"))
async def withdraw_requests(message: Message):
    if not is_admin(message.from_user.id):
        return await message.answer("دسترسی به پنل ادمین ندارید")

    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()
    
    c.execute("""
        SELECT t.id, t.user_id, t.amount, t.created_at,
               u.full_name, u.card_holder, u.card_number
        FROM transactions t
        JOIN users u ON t.user_id = u.user_id
        WHERE t.type = 'withdraw' AND t.status = 'pending'
        ORDER BY t.id DESC
    """)
    requests = c.fetchall()
    conn.close()

    if not requests:
        return await message.answer("در حال حاضر هیچ درخواست برداشتی وجود ندارد")

    await message.answer(f"<b>درخواست‌های برداشت در انتظار ({len(requests)} تا)</b>", parse_mode="HTML")

    for req in requests:
        trans_id, user_id, amount, created_at, full_name, card_holder, card_number = req

        # تاریخ قشنگ
        date = created_at.split("T")[0].replace("-", "/") if "T" in created_at else created_at[:10]

        caption = f"""
            <b>درخواست برداشت #{trans_id}</b>

            <b>اطلاعات کاربر:</b>
            نام: <a href="tg://user?id={user_id}">{full_name or 'بدون نام'}</a>
            آیدی: <code>{user_id}</code>

            <b>مبلغ درخواستی:</b>
            {amount:,} تومان

            <b>اطلاعات کارت:</b>
            صاحب کارت: <b>{card_holder or 'ثبت نشده'}</b>
            شماره کارت: <code>{card_number or 'ثبت نشده'}</code>

            <b>تاریخ درخواست:</b>
            {date}

            ✅ مبلغ از کیف پول کاربر کسر شده است
            """.strip()
        
        # دکمه‌های همون قبلی (دقیقاً همونی که تو کد اصلی داری!)
        kb = InlineKeyboardMarkup(inline_keyboard=[[
            InlineKeyboardButton(text="تأیید و واریز", callback_data=f"withdraw_approve_{trans_id}"),
            InlineKeyboardButton(text="رد درخواست", callback_data=f"withdraw_reject_{trans_id}")
        ]])

        await message.answer(caption, parse_mode="HTML", reply_markup=kb, disable_web_page_preview=True)

    await message.answer("✅ تمام درخواست‌های برداشت نمایش داده شد")

#  درخواست های واریزی کاربران 
@router.message(Command("deposit_req"))
async def deposit_req(message: Message): 
    if not is_admin(message.from_user.id):
        return await message.answer("دسترسی به پنل ادمین ندارید!")

    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()
    
    # حالا می‌تونیم از screenshot_message_id استفاده کنیم
    c.execute("""
        SELECT t.id, t.user_id, t.created_at, t.screenshot_message_id,
               u.full_name, u.username
        FROM transactions t
        JOIN users u ON t.user_id = u.user_id
        WHERE t.type = 'deposit' AND t.status = 'pending'
        ORDER BY t.id DESC
    """)
    requests = c.fetchall()
    conn.close()

    if not requests:
        return await message.answer("✅ هیچ درخواست واریزی در انتظار نیست")

    await message.answer(f"<b>درخواست‌های واریز در انتظار ({len(requests)} تا)</b>", parse_mode="HTML")

    for req in requests:
        trans_id, user_id, created_at, screenshot_id, full_name, username = req

        date = created_at.split("T")[0].replace("-", "/") if "T" in created_at else created_at[:10]

        caption = f"""
🏦 درخواست واریز #{trans_id}
━━━━━━━━━━━━
👤 کاربر: <a href="tg://user?id={user_id}">{full_name or 'بدون نام'}</a>
🆔 آیدی: <code>{user_id}</code>
📱 یوزرنیم: @{username or 'ندارد'}
📅 تاریخ: {date}
        """.strip()

        kb = InlineKeyboardMarkup(inline_keyboard=[[
            InlineKeyboardButton(text="✅ تأیید واریز", callback_data=f"deposit_approve_{trans_id}_{user_id}"),
            InlineKeyboardButton(text="❌ رد واریز", callback_data=f"deposit_reject_{trans_id}_{user_id}")
        ]])

        # اگر عکس فیش وجود داره
        if screenshot_id:
            try:
                await bot.forward_message(
                    chat_id=message.chat.id,
                    from_chat_id=user_id,
                    message_id=screenshot_id
                )
                await message.answer(caption, parse_mode="HTML", reply_markup=kb)
            except:
                await message.answer(f"{caption}\n\n⚠️ خطا در نمایش فیش", parse_mode="HTML", reply_markup=kb)
        else:
            await message.answer(f"{caption}\n\n📎 فیش واریز موجود نیست", parse_mode="HTML", reply_markup=kb)

    await message.answer("✅ لیست درخواست‌های واریز به پایان رسید.")

# خروجی از کل دیتابیس 
@router.message(Command("export_db"))
async def export_db(message: Message):
    if not is_admin(message.from_user.id):
        return await message.answer("❌ دسترسی به پنل ادمین ندارید!")

    try:
        import pandas as pd
        from io import BytesIO
        import datetime

        conn = sqlite3.connect(DB_FILE)
        cursor = conn.cursor()

        # دریافت لیست تمام جدول‌ها
        cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
        tables = [row[0] for row in cursor.fetchall()]

        if not tables:
            return await message.answer("❌ دیتابیس خالی است!")

        excel_buffer = BytesIO()

        # نوشتن هر جدول در یک شیت
        with pd.ExcelWriter(excel_buffer, engine="xlsxwriter") as writer:
            for table in tables:
                try:
                    df = pd.read_sql_query(f"SELECT * FROM {table}", conn)
                    sheet_name = table[:31]  # محدودیت نام شیت
                    df.to_excel(writer, sheet_name=sheet_name, index=False)
                except Exception as e:
                    print(f"خطا در جدول {table}: {e}")

        conn.close()

        excel_buffer.seek(0)

        timestamp = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
        filename = f"database_export_{timestamp}.xlsx"

        # ارسال فایل — نسخه سازگار با Aiogram v3
        await message.answer_document(
            types.BufferedInputFile(
                excel_buffer.getvalue(),
                filename=filename
            ),
            caption=f"📊 خروجی کامل دیتابیس\n\nتاریخ: {timestamp}\nتعداد جدول‌ها: {len(tables)}"
        )

    except Exception as e:
        await message.answer(f"❌ خطا در ایجاد خروجی:\n<code>{e}</code>", parse_mode="HTML")

# ثبت روتر در دیسپچر اصلی
dp.include_router(router)

#  گزارش گیری کلی و آمار دهی 
@router.message(Command("full_stats"))
async def show_full_stats(message: Message):
    if not is_admin(message.from_user.id):
        return await message.answer("دسترسی به پنل ادمین ندارید!")
    
    try:
        conn = sqlite3.connect(DB_FILE)
        c = conn.cursor()
        
        # آمار کاربران جدید در ۳۰ روز گذشته
        c.execute("""
            SELECT DATE(joined_at), COUNT(*) 
            FROM users 
            WHERE joined_at >= date('now', '-30 days')
            GROUP BY DATE(joined_at) 
            ORDER BY DATE(joined_at) DESC 
            LIMIT 10
        """)
        recent_users = c.fetchall()
        
        # آمار آگهی‌های روزانه
        c.execute("""
            SELECT DATE(created_at), COUNT(*), status
            FROM ads 
            WHERE created_at >= date('now', '-7 days')
            GROUP BY DATE(created_at), status
            ORDER BY DATE(created_at) DESC
        """)
        daily_ads = c.fetchall()
        
        conn.close()
        
        # ساخت نمودار متنی برای کاربران
        users_chart = ""
        if recent_users:
            users_chart = "\n📈 **کاربران جدید (۱۰ روز اخیر):**\n"
            for date_str, count in recent_users:
                users_chart += f"├ {date_str}: {'▰' * min(count, 10)} {count} نفر\n"
        
        # ساخت گزارش آگهی‌های روزانه
        ads_chart = "\n📅 **آگهی‌های ۷ روز گذشته:**\n"
        daily_stats = {}
        
        for date_str, count, status in daily_ads:
            if date_str not in daily_stats:
                daily_stats[date_str] = {'total': 0, 'approved': 0, 'pending': 0}
            daily_stats[date_str]['total'] += count
            if status == 'approved':
                daily_stats[date_str]['approved'] += count
            elif status == 'pending':
                daily_stats[date_str]['pending'] += count
        
        for date_str, stats in list(daily_stats.items())[:7]:
            ads_chart += f"├ {date_str}: ✅{stats['approved']} ⏳{stats['pending']} 📊{stats['total']}\n"
        
        full_stats_text = f"""
📈 **گزارش پیشرفته ربات**

{users_chart}
{ads_chart}
        """.strip()
        
        await message.answer(full_stats_text, parse_mode="Markdown")
        
    except Exception as e:
        await message.answer(f"خطا در دریافت گزارش پیشرفته: {str(e)}")

# ==================================================

# اجرا
async def main():
    print("ربات روشن شد!")
    await dp.start_polling(bot)

if __name__ == "__main__":
    asyncio.run(main())