# -*- coding: utf-8 -*-
"""
ربات تلگرام «تریدر برتر»
فروش اشتراک کانال سیگنال و اندیکاتورها با پرداخت تومان (درگاه) و تتر (USDT).

اجرا:  python bot.py
پیش‌نیاز:  pip install "python-telegram-bot>=22"
"""
import logging
import os

from telegram import (
    Update,
    InlineKeyboardButton,
    InlineKeyboardMarkup,
    InputFile,
)
from telegram.constants import ParseMode
from telegram.ext import (
    Application,
    CommandHandler,
    CallbackQueryHandler,
    MessageHandler,
    ContextTypes,
    filters,
)

import config
import db
import payments
from utils import fa_num, en_num, format_toman, toman_to_usdt

logging.basicConfig(
    format="%(asctime)s | %(name)s | %(levelname)s | %(message)s",
    level=logging.INFO,
)
log = logging.getLogger("traderbartar")

# وضعیت کاربر که منتظر ارسال TXID است: {user_id: order_id}
AWAITING_TXID: dict[int, int] = {}


# ══════════════════════════════════════════════════════════════
#  کیبوردها
# ══════════════════════════════════════════════════════════════
def kb_main() -> InlineKeyboardMarkup:
    return InlineKeyboardMarkup(
        [
            [InlineKeyboardButton("🛒 خرید اشتراک و اندیکاتور", callback_data="menu:products")],
            [
                InlineKeyboardButton("📦 خریدهای من", callback_data="menu:orders"),
                InlineKeyboardButton("ℹ️ راهنما", callback_data="menu:help"),
            ],
            [InlineKeyboardButton("💬 پشتیبانی", url=f"https://t.me/{config.SUPPORT_USERNAME.lstrip('@')}")],
        ]
    )


def kb_products() -> InlineKeyboardMarkup:
    rows = []
    for key in config.PRODUCT_ORDER:
        p = config.PRODUCTS[key]
        star = " ⭐" if p.get("popular") else ""
        title = p["title"].replace(" ⭐", "")
        price = fa_num(f"{p['price_toman']:,}")
        label = f"{title}{star} — {price}ت"
        rows.append([InlineKeyboardButton(label, callback_data=f"product:{key}")])
    rows.append([InlineKeyboardButton("« بازگشت", callback_data="menu:home")])
    return InlineKeyboardMarkup(rows)


def kb_product_detail(key: str) -> InlineKeyboardMarkup:
    return InlineKeyboardMarkup(
        [
            [InlineKeyboardButton("💳 پرداخت تومانی (درگاه)", callback_data=f"pay:toman:{key}")],
            [InlineKeyboardButton("💵 پرداخت با تتر (USDT)", callback_data=f"pay:usdt:{key}")],
            [InlineKeyboardButton("« بازگشت به لیست", callback_data="menu:products")],
        ]
    )


def kb_simulate_pay(order_id: int) -> InlineKeyboardMarkup:
    return InlineKeyboardMarkup(
        [
            [InlineKeyboardButton("✅ پرداخت کردم (شبیه‌سازی)", callback_data=f"simok:{order_id}")],
            [InlineKeyboardButton("✖️ انصراف", callback_data="menu:products")],
        ]
    )


def kb_admin_review(order_id: int) -> InlineKeyboardMarkup:
    return InlineKeyboardMarkup(
        [
            [
                InlineKeyboardButton("✅ تأیید", callback_data=f"admin:ok:{order_id}"),
                InlineKeyboardButton("❌ رد", callback_data=f"admin:no:{order_id}"),
            ]
        ]
    )


# ══════════════════════════════════════════════════════════════
#  متن‌ها
# ══════════════════════════════════════════════════════════════
WELCOME = (
    f"👋 به ربات <b>{config.BRAND}</b> خوش آمدید.\n\n"
    "از اینجا می‌توانید اشتراک <b>کانال سیگنال طلا و نفت</b> یا "
    "<b>پکیج اندیکاتورهای اختصاصی</b> را تهیه کنید.\n\n"
    "پرداخت به دو روش امکان‌پذیر است:\n"
    "• 💳 تومانی از طریق درگاه بانکی\n"
    "• 💵 تتر (USDT) روی شبکهٔ TRC20\n\n"
    "برای شروع یکی از گزینه‌ها را انتخاب کنید:"
)

HELP = (
    f"ℹ️ <b>راهنمای {config.BRAND}</b>\n\n"
    "۱) روی «خرید اشتراک و اندیکاتور» بزنید.\n"
    "۲) محصول موردنظر را انتخاب کنید.\n"
    "۳) روش پرداخت (تومان یا تتر) را انتخاب کنید.\n"
    "۴) پس از پرداخت موفق، لینک کانال یا فایل اندیکاتورها "
    "به‌صورت خودکار برای شما ارسال می‌شود.\n\n"
    "• پرداخت تومانی: از طریق درگاه امن بانکی انجام می‌شود.\n"
    "• پرداخت تتر: مبلغ را واریز کرده و هش تراکنش (TXID) را ارسال می‌کنید؛ "
    "پس از تأیید، محصول ارسال می‌شود.\n\n"
    f"سؤالی داشتید؟ پشتیبانی: {config.SUPPORT_USERNAME}"
)


def product_text(key: str) -> str:
    p = config.PRODUCTS[key]
    lines = [f"<b>{p['title']}</b>", ""]
    lines.append(f"💰 قیمت: <b>{format_toman(p['price_toman'])}</b>")
    if p.get("discount"):
        lines.append(f"🎯 {p['per_month']}")
    else:
        lines.append(f"• {p['per_month']}")
    lines.append(f"💵 معادل تتر: <b>{toman_to_usdt(p['price_toman'])} USDT</b>")
    lines.append("")
    lines.append("<b>این پلن شامل:</b>")
    for f in p["features"]:
        lines.append(f"  ✅ {f}")
    lines.append("")
    lines.append("روش پرداخت را انتخاب کنید:")
    return "\n".join(lines)


# ══════════════════════════════════════════════════════════════
#  هندلرهای دستور
# ══════════════════════════════════════════════════════════════
async def cmd_start(update: Update, context: ContextTypes.DEFAULT_TYPE):
    u = update.effective_user
    db.upsert_user(u.id, u.username or "", u.first_name or "")
    await update.message.reply_text(WELCOME, parse_mode=ParseMode.HTML, reply_markup=kb_main())


async def cmd_help(update: Update, context: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text(HELP, parse_mode=ParseMode.HTML, reply_markup=kb_main())


# ══════════════════════════════════════════════════════════════
#  هندلر دکمه‌های inline
# ══════════════════════════════════════════════════════════════
async def on_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
    q = update.callback_query
    await q.answer()
    data = q.data
    uid = q.from_user.id

    # ── منوها ──
    if data == "menu:home":
        return await q.edit_message_text(WELCOME, parse_mode=ParseMode.HTML, reply_markup=kb_main())
    if data == "menu:products":
        return await q.edit_message_text(
            "🛒 <b>محصولات تریدر برتر</b>\nیکی را انتخاب کنید:",
            parse_mode=ParseMode.HTML, reply_markup=kb_products(),
        )
    if data == "menu:help":
        return await q.edit_message_text(HELP, parse_mode=ParseMode.HTML, reply_markup=kb_main())
    if data == "menu:orders":
        return await show_orders(q, uid)

    # ── جزئیات محصول ──
    if data.startswith("product:"):
        key = data.split(":", 1)[1]
        if key in config.PRODUCTS:
            return await q.edit_message_text(
                product_text(key), parse_mode=ParseMode.HTML,
                reply_markup=kb_product_detail(key),
            )

    # ── شروع پرداخت ──
    if data.startswith("pay:"):
        _, method, key = data.split(":", 2)
        return await start_payment(q, context, uid, method, key)

    # ── تأیید پرداخت شبیه‌سازی‌شدهٔ تومانی ──
    if data.startswith("simok:"):
        order_id = int(data.split(":", 1)[1])
        return await confirm_toman(q, context, order_id)

    # ── اکشن‌های ادمین ──
    if data.startswith("admin:"):
        return await admin_action(q, context, data)


# ══════════════════════════════════════════════════════════════
#  جریان پرداخت
# ══════════════════════════════════════════════════════════════
async def start_payment(q, context, uid, method, key):
    if key not in config.PRODUCTS:
        return await q.answer("محصول یافت نشد.", show_alert=True)
    p = config.PRODUCTS[key]

    if method == "toman":
        order_id = db.create_order(uid, key, p["title"], p["price_toman"], "toman")
        res = payments.request_payment(order_id, p["price_toman"], p["title"])
        if not res["ok"]:
            return await q.edit_message_text("⚠️ خطا در ایجاد تراکنش. بعداً تلاش کنید.")

        if res["pay_url"]:  # درگاه واقعی
            kb = InlineKeyboardMarkup(
                [[InlineKeyboardButton("🔗 پرداخت در درگاه", url=res["pay_url"])],
                 [InlineKeyboardButton("« بازگشت", callback_data="menu:products")]]
            )
            txt = (
                f"💳 <b>پرداخت تومانی</b>\n\n"
                f"محصول: {p['title']}\n"
                f"مبلغ: <b>{format_toman(p['price_toman'])}</b>\n\n"
                "برای پرداخت روی دکمهٔ زیر بزنید. پس از پرداخت موفق، "
                "محصول به‌صورت خودکار ارسال می‌شود."
            )
            return await q.edit_message_text(txt, parse_mode=ParseMode.HTML, reply_markup=kb)

        # حالت شبیه‌سازی
        txt = (
            f"💳 <b>پرداخت تومانی (حالت آزمایشی)</b>\n\n"
            f"محصول: {p['title']}\n"
            f"مبلغ: <b>{format_toman(p['price_toman'])}</b>\n"
            f"شمارهٔ سفارش: <code>{fa_num(order_id)}</code>\n\n"
            "در نسخهٔ واقعی اینجا به درگاه بانکی هدایت می‌شوید.\n"
            "برای شبیه‌سازی پرداخت موفق، دکمهٔ زیر را بزنید:"
        )
        return await q.edit_message_text(
            txt, parse_mode=ParseMode.HTML, reply_markup=kb_simulate_pay(order_id)
        )

    if method == "usdt":
        order_id = db.create_order(uid, key, p["title"], p["price_toman"], "usdt")
        db.set_order_status(order_id, "awaiting_review")
        AWAITING_TXID[uid] = order_id
        amount_usdt = toman_to_usdt(p["price_toman"])
        txt = (
            f"🧾 محصول: <b>{p['title']}</b>\n"
            f"شمارهٔ سفارش: <code>{fa_num(order_id)}</code>\n\n"
            + payments.usdt_instructions(amount_usdt)
        )
        kb = InlineKeyboardMarkup(
            [[InlineKeyboardButton("✖️ انصراف", callback_data="menu:products")]]
        )
        return await q.edit_message_text(txt, parse_mode=ParseMode.HTML, reply_markup=kb)


async def confirm_toman(q, context, order_id):
    """تأیید پرداخت تومانی (شبیه‌سازی یا بازگشت از درگاه)."""
    order = db.get_order(order_id)
    if not order:
        return await q.answer("سفارش یافت نشد.", show_alert=True)
    if order["status"] == "paid":
        return await q.answer("این سفارش قبلاً پرداخت شده.", show_alert=True)

    ok = payments.verify_payment(order_id, f"SIM-{order_id}", order["amount_toman"])
    if not ok:
        db.set_order_status(order_id, "rejected")
        return await q.edit_message_text("❌ پرداخت تأیید نشد. دوباره تلاش کنید.")

    db.set_order_status(order_id, "paid")
    await q.edit_message_text("✅ پرداخت شما با موفقیت تأیید شد!", parse_mode=ParseMode.HTML)
    await deliver(context, order["user_id"], order)


# ══════════════════════════════════════════════════════════════
#  دریافت TXID برای پرداخت تتر
# ══════════════════════════════════════════════════════════════
async def on_text(update: Update, context: ContextTypes.DEFAULT_TYPE):
    uid = update.effective_user.id
    if uid not in AWAITING_TXID:
        # پیام نامرتبط → راهنمایی به منو
        return await update.message.reply_text(
            "برای شروع خرید از دکمه‌های زیر استفاده کنید:", reply_markup=kb_main()
        )

    order_id = AWAITING_TXID.pop(uid)
    txid = en_num(update.message.text.strip())
    order = db.get_order(order_id)
    if not order:
        return await update.message.reply_text("سفارش یافت نشد. دوباره تلاش کنید.")

    db.set_order_status(order_id, "awaiting_review", txid=txid)
    await update.message.reply_text(
        "✅ هش تراکنش شما دریافت شد.\n"
        "پس از بررسی توسط تیم ما (معمولاً کمتر از ۳۰ دقیقه)، "
        "محصول برای شما ارسال می‌شود. 🙏",
        parse_mode=ParseMode.HTML,
    )
    # اعلان به ادمین‌ها
    amount_usdt = toman_to_usdt(order["amount_toman"])
    u = update.effective_user
    admin_txt = (
        "🔔 <b>درخواست تأیید پرداخت تتر</b>\n\n"
        f"سفارش: <code>{fa_num(order_id)}</code>\n"
        f"محصول: {order['title']}\n"
        f"مبلغ: {format_toman(order['amount_toman'])} (~{amount_usdt} USDT)\n"
        f"کاربر: {u.mention_html()} (<code>{u.id}</code>)\n"
        f"TXID:\n<code>{txid}</code>"
    )
    for admin_id in config.ADMIN_IDS:
        try:
            await context.bot.send_message(
                admin_id, admin_txt, parse_mode=ParseMode.HTML,
                reply_markup=kb_admin_review(order_id),
            )
        except Exception as e:
            log.warning("ارسال به ادمین %s ناموفق: %s", admin_id, e)


# ══════════════════════════════════════════════════════════════
#  اکشن ادمین (تأیید / رد پرداخت تتر)
# ══════════════════════════════════════════════════════════════
async def admin_action(q, context, data):
    if q.from_user.id not in config.ADMIN_IDS:
        return await q.answer("شما دسترسی ادمین ندارید.", show_alert=True)

    _, action, order_id = data.split(":", 2)
    order_id = int(order_id)
    order = db.get_order(order_id)
    if not order:
        return await q.answer("سفارش یافت نشد.", show_alert=True)

    if action == "ok":
        db.set_order_status(order_id, "paid")
        await q.edit_message_text(
            q.message.text_html + "\n\n✅ <b>تأیید شد.</b>", parse_mode=ParseMode.HTML
        )
        await deliver(context, order["user_id"], order)
    else:  # no
        db.set_order_status(order_id, "rejected")
        await q.edit_message_text(
            q.message.text_html + "\n\n❌ <b>رد شد.</b>", parse_mode=ParseMode.HTML
        )
        try:
            await context.bot.send_message(
                order["user_id"],
                "❌ متأسفانه پرداخت شما تأیید نشد.\n"
                "اگر مبلغ را واریز کرده‌اید، لطفاً با پشتیبانی تماس بگیرید: "
                f"{config.SUPPORT_USERNAME}",
            )
        except Exception:
            pass


# ══════════════════════════════════════════════════════════════
#  تحویل محصول
# ══════════════════════════════════════════════════════════════
async def deliver(context, user_id: int, order: dict):
    p = config.PRODUCTS.get(order["product_key"], {})
    ptype = p.get("type")

    if ptype == "subscription":
        txt = (
            "🎉 <b>خرید شما تکمیل شد!</b>\n\n"
            f"محصول: {order['title']}\n\n"
            "لینک اختصاصی ورود به کانال سیگنال:\n"
            f"{config.SIGNAL_CHANNEL_LINK}\n\n"
            "به جمع اعضای تریدر برتر خوش آمدید! 📈"
        )
        await context.bot.send_message(user_id, txt, parse_mode=ParseMode.HTML)

    elif ptype == "indicator":
        caption = (
            "🎉 <b>خرید شما تکمیل شد!</b>\n\n"
            f"محصول: {order['title']}\n"
            "فایل اندیکاتورها به همراه راهنمای نصب پیوست شده است. 📊"
        )
        sent = False
        if os.path.exists(config.INDICATOR_FILE):
            try:
                with open(config.INDICATOR_FILE, "rb") as f:
                    await context.bot.send_document(
                        user_id, InputFile(f, filename="TraderBartar-Indicators.zip"),
                        caption=caption, parse_mode=ParseMode.HTML,
                    )
                sent = True
            except Exception as e:
                log.warning("ارسال فایل ناموفق: %s", e)
        if not sent:
            await context.bot.send_message(
                user_id,
                caption + "\n\n⚠️ فایل روی سرور تنظیم نشده است؛ "
                f"لطفاً با پشتیبانی تماس بگیرید: {config.SUPPORT_USERNAME}",
                parse_mode=ParseMode.HTML,
            )
        # پلن اندیکاتور اگر شامل کانال هم بود، اینجا اضافه می‌شد


async def show_orders(q, uid):
    orders = db.user_paid_orders(uid)
    if not orders:
        return await q.edit_message_text(
            "📦 شما هنوز خرید موفقی ندارید.",
            reply_markup=kb_main(),
        )
    lines = ["📦 <b>خریدهای شما:</b>", ""]
    for o in orders:
        method = "تتر" if o["method"] == "usdt" else "تومانی"
        lines.append(f"• {o['title']} — {format_toman(o['amount_toman'])} ({method}) ✅")
    kb = InlineKeyboardMarkup([[InlineKeyboardButton("« بازگشت", callback_data="menu:home")]])
    await q.edit_message_text("\n".join(lines), parse_mode=ParseMode.HTML, reply_markup=kb)


# ══════════════════════════════════════════════════════════════
#  راه‌اندازی
# ══════════════════════════════════════════════════════════════
def main():
    db.init_db()
    if config.BOT_TOKEN.startswith("PUT-YOUR"):
        raise SystemExit(
            "❌ توکن ربات تنظیم نشده. مقدار BOT_TOKEN را در فایل .env قرار دهید."
        )

    app = Application.builder().token(config.BOT_TOKEN).build()

    app.add_handler(CommandHandler("start", cmd_start))
    app.add_handler(CommandHandler("help", cmd_help))
    app.add_handler(CallbackQueryHandler(on_callback))
    app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, on_text))

    log.info("ربات تریدر برتر در حال اجراست…")
    app.run_polling(allowed_updates=Update.ALL_TYPES)


if __name__ == "__main__":
    main()
