# -*- coding: utf-8 -*-
"""هندلرهای مربوط به کاربر عادی: شروع کار، کیف پول، کسب کوین، دعوت دوستان."""

import html
from datetime import datetime

import telebot
from telebot import types

import database as db
import keyboards as kb
import utils
from handlers import campaign as campaign_mod


def register(bot: telebot.TeleBot):

    # -----------------------------------------------------------------
    # /start
    # -----------------------------------------------------------------
    @bot.message_handler(commands=["start"])
    def start_handler(message):
        user_id = message.from_user.id
        username = message.from_user.username or ""
        first_name = message.from_user.first_name or ""

        referred_by = None
        parts = message.text.split(maxsplit=1)
        if len(parts) > 1 and parts[1].isdigit():
            ref_id = int(parts[1])
            if ref_id != user_id and db.get_user(ref_id):
                referred_by = ref_id

        existing = db.get_user(user_id)
        if not existing:
            db.create_user(user_id, username, first_name, referred_by)
            if referred_by:
                bonus = db.get_int_setting("referral_bonus", 2)
                db.add_coins(referred_by, bonus)
                try:
                    bot.send_message(
                        referred_by,
                        f"🎉 یک نفر با لینک دعوت تو وارد ربات شد و {bonus} کوین جایزه گرفتی!",
                    )
                except Exception:
                    pass
        else:
            db.update_username(user_id, username, first_name)

        if db.is_banned(user_id):
            bot.send_message(message.chat.id, "⛔️ شما از استفاده از ربات مسدود شدید.")
            return

        _send_welcome_or_force(bot, message.chat.id, user_id)

    def _send_welcome_or_force(bot, chat_id, user_id):
        missing = utils.missing_force_channels(bot, user_id)
        if missing:
            bot.send_message(
                chat_id,
                utils.render_text("force_join_prompt"),
                reply_markup=kb.force_join_kb(missing),
            )
            return
        bot.send_message(chat_id, utils.render_text("welcome"), reply_markup=kb.main_menu(user_id))

    # -----------------------------------------------------------------
    # تایید عضویت در کانال‌های اجباری
    # -----------------------------------------------------------------
    @bot.callback_query_handler(func=lambda c: c.data == "check_force_join")
    def check_force_join(call):
        user_id = call.from_user.id
        missing = utils.missing_force_channels(bot, user_id)
        if missing:
            bot.answer_callback_query(
                call.id, "هنوز توی همه‌ی کانال‌ها عضو نشدی!", show_alert=True
            )
            return
        bot.answer_callback_query(call.id, "✅ عضویت تایید شد")
        try:
            bot.delete_message(call.message.chat.id, call.message.message_id)
        except Exception:
            pass
        bot.send_message(
            call.message.chat.id, utils.render_text("welcome"), reply_markup=kb.main_menu(user_id)
        )

    # -----------------------------------------------------------------
    # کیف پول
    # -----------------------------------------------------------------
    @bot.message_handler(func=lambda m: utils.is_button(m.text, "wallet"))
    def wallet_handler(message):
        user_id = message.from_user.id
        coins = db.get_coins(user_id)
        unit = db.get_int_setting("coins_unit", 10)
        price = db.get_int_setting("price_per_unit", 4000)
        toman_value = int(coins / unit * price) if unit else 0
        text = utils.render_text(
            "wallet_view",
            coins=utils.fmt_num(coins),
            toman_value=utils.toman(toman_value),
            unit=unit,
            price=utils.toman(price),
        )
        bot.send_message(message.chat.id, text)

    # -----------------------------------------------------------------
    # لینک دعوت
    # -----------------------------------------------------------------
    @bot.message_handler(func=lambda m: utils.is_button(m.text, "referral"))
    def referral_handler(message):
        user_id = message.from_user.id
        bot_username = bot.get_me().username
        link = f"https://t.me/{bot_username}?start={user_id}"
        bonus = db.get_setting("referral_bonus")
        text = utils.render_text("referral", link=link, bonus=bonus)
        bot.send_message(message.chat.id, text)

    # -----------------------------------------------------------------
    # پیگیری سفارش (جایگزین دکمه‌ی راهنمای قبلی)
    # -----------------------------------------------------------------
    @bot.message_handler(func=lambda m: utils.is_button(m.text, "help"))
    def track_order_handler(message):
        utils.set_state(message.from_user.id, "awaiting_order_code")
        bot.send_message(
            message.chat.id,
            "🔍 کد سفارشت رو بفرست تا جزئیاتش رو نشونت بدم:",
            reply_markup=kb.cancel_kb(),
        )

    @bot.message_handler(
        func=lambda m: utils.get_state(m.from_user.id)
        and utils.get_state(m.from_user.id)["state"] == "awaiting_order_code"
        and m.text != "❌ انصراف"
    )
    def receive_order_code(message):
        user_id = message.from_user.id
        utils.clear_state(user_id)
        code = message.text.strip().upper()
        campaign = db.get_campaign_by_order_code(code)
        if not campaign:
            bot.send_message(
                message.chat.id,
                "سفارشی با این کد پیدا نشد. مطمئن شو درست وارد کردی.",
                reply_markup=kb.main_menu(user_id),
            )
            return

        done = campaign["total_coins"] - campaign["remaining"]
        status_fa = {
            "active": "⏳️ در حال انجام",
            "finished": "✅ تکمیل‌شده",
            "stopped": "⛔️ متوقف‌شده",
        }
        link_display = (
            campaign["channel_id"]
            if campaign["channel_id"].startswith("@")
            else (campaign["channel_title"] or campaign["channel_id"])
        )
        created = datetime.fromtimestamp(campaign["created_at"]).strftime("%Y-%m-%d | %H:%M")
        text = (
            "📋 اطلاعات سفارش\n\n"
            f"🆔 کد سفارش: <code>{campaign['order_code']}</code>\n"
            f"🔗 لینک: {html.escape(link_display)}\n"
            f"👥 تعداد درخواستی: {utils.fmt_num(campaign['total_coins'])}\n"
            f"✅ انجام شده: {utils.fmt_num(done)}\n"
            f"⏳ باقی‌مانده: {utils.fmt_num(campaign['remaining'])}\n"
            f"📊 وضعیت: {status_fa.get(campaign['status'], campaign['status'])}\n"
            f"📅 زمان ثبت: {created}"
        )
        bot.send_message(message.chat.id, text, parse_mode="HTML", reply_markup=kb.main_menu(user_id))

    # -----------------------------------------------------------------
    # کسب کوین -> نمایش یه کانال در هر لحظه (مثل کارت)، با ناوبری قبلی/بعدی
    # -----------------------------------------------------------------
    def _available_campaigns(user_id):
        return db.list_available_campaigns_for_user(user_id, limit=500)

    def _send_earn_item(chat_id, user_id, index, message_id=None):
        campaigns = _available_campaigns(user_id)
        if not campaigns:
            text = utils.render_text("earn_empty")
            if message_id:
                try:
                    bot.edit_message_text(text, chat_id, message_id, reply_markup=None)
                    return
                except Exception:
                    pass
            bot.send_message(chat_id, text)
            return

        total = len(campaigns)
        index = max(0, min(index, total - 1))
        c = campaigns[index]

        coin_per_join = db.get_int_setting("coin_per_join", 1)
        title = c["channel_title"] or c["channel_id"]
        header = f"({index + 1} از {total})" if total > 1 else ""
        text = (
            f"{utils.render_text('earn_list_header', count=total)} {header}\n\n"
            f"{utils.render_text('earn_item', title=title, remaining=c['remaining'], coin_per_join=coin_per_join)}"
        )
        markup = kb.earn_single_kb(c, index, total)

        if message_id:
            try:
                bot.edit_message_text(text, chat_id, message_id, reply_markup=markup)
                return
            except Exception:
                pass
        bot.send_message(chat_id, text, reply_markup=markup)

    @bot.message_handler(func=lambda m: utils.is_button(m.text, "earn"))
    def earn_coin_handler(message):
        _send_earn_item(message.chat.id, message.from_user.id, 0)

    @bot.callback_query_handler(func=lambda c: c.data.startswith("earnnav_"))
    def earn_nav(call):
        index = int(call.data.split("_", 1)[1])
        bot.answer_callback_query(call.id)
        _send_earn_item(call.message.chat.id, call.from_user.id, index, message_id=call.message.message_id)

    @bot.callback_query_handler(func=lambda c: c.data == "earn_home")
    def earn_go_home(call):
        user_id = call.from_user.id
        bot.answer_callback_query(call.id)
        try:
            bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id, reply_markup=None)
        except Exception:
            pass
        bot.send_message(call.message.chat.id, "منوی اصلی:", reply_markup=kb.main_menu(user_id))

    # -----------------------------------------------------------------
    # تایید عضویت در یک کمپین خاص و اعطای کوین
    # -----------------------------------------------------------------
    @bot.callback_query_handler(func=lambda c: c.data.startswith("verify_"))
    def verify_campaign_join(call):
        user_id = call.from_user.id
        campaign_id = int(call.data.split("_", 1)[1])
        campaign = db.get_campaign(campaign_id)

        # اگه کاربر مستقیم از کانال اومده و هیچ‌وقت /start رو نزده، هنوز
        # توی دیتابیس ثبت نشده - همینجا ثبتش میکنیم تا کوینش گم نشه.
        if not db.get_user(user_id):
            db.create_user(user_id, call.from_user.username or "", call.from_user.first_name or "")

        if not campaign or campaign["status"] != "active" or campaign["remaining"] <= 0:
            bot.answer_callback_query(call.id, "این کمپین دیگه فعال نیست.", show_alert=True)
            return

        if campaign["owner_id"] == user_id:
            bot.answer_callback_query(
                call.id, "نمیتونی از کانال خودت کوین بگیری!", show_alert=True
            )
            return

        if db.has_joined_campaign(campaign_id, user_id):
            bot.answer_callback_query(call.id, "قبلا کوینش رو گرفتی ✅", show_alert=True)
            return

        # اگه این کاربر قبلا (حتی از یه کمپین دیگه) از همین کانال کوین گرفته،
        # دیگه بار دوم کوین نمیگیره - تا نشه با گذاشتن چندبارهٔ یه کانال کوین تقلبی گرفت
        if db.has_earned_from_channel(campaign["channel_id"], user_id):
            bot.answer_callback_query(
                call.id, "قبلا از این کانال کوین گرفتی، حتی اگه یه‌جای دیگه هم تبلیغ شده باشه ✅",
                show_alert=True,
            )
            return

        if not utils.is_member(bot, campaign["channel_id"], user_id):
            bot.answer_callback_query(
                call.id, "هنوز عضو کانال نشدی! اول عضو شو بعد دکمه رو بزن.", show_alert=True
            )
            return

        result = db.record_campaign_join(campaign_id, user_id)
        if not result:
            bot.answer_callback_query(call.id, "قبلا کوینش رو گرفتی ✅", show_alert=True)
            return

        db.record_channel_earning(campaign["channel_id"], user_id)
        coin_per_join = db.get_int_setting("coin_per_join", 1)
        db.add_coins(user_id, coin_per_join)
        bot.answer_callback_query(
            call.id, f"🎉 {coin_per_join} کوین به موجودیت اضافه شد!", show_alert=True
        )
        # پیام پست کانال لاگ رو به‌روز میکنیم (تعداد «انجام شده» رو بالا
        # میبره؛ اگه سفارش تکمیل شده باشه، پیام رو از کانال حذف میکنه)
        try:
            campaign_mod.update_log_message(bot, campaign_id)
        except Exception:
            pass
        # اگه این پیام توی چت خصوصی خود ربات بوده (نه یه پست کانال که چند نفر
        # جدا باهاش کار میکنن)، خودکار می‌ریم سراغ کانال بعدی که هنوز کوینش
        # رو نگرفته - تجربه‌ی کاربری روون‌تر میشه.
        if call.message and call.message.chat.type == "private":
            try:
                _send_earn_item(call.message.chat.id, user_id, 0, message_id=call.message.message_id)
            except Exception:
                pass

        # اگه کمپین همین الان تکمیل شد، به صاحبش خبر بده
        if result.get("finished"):
            try:
                bot.send_message(
                    campaign["owner_id"],
                    utils.render_text(
                        "campaign_finished_owner",
                        channel_title=campaign["channel_title"],
                        total=utils.fmt_num(campaign["total_coins"]),
                    ),
                )
            except Exception:
                pass

    # -----------------------------------------------------------------
    # پاداش روزانه
    # -----------------------------------------------------------------
    @bot.message_handler(func=lambda m: utils.is_button(m.text, "daily"))
    def daily_bonus_handler(message):
        user_id = message.from_user.id
        amount = db.get_int_setting("daily_bonus", 3)
        left = db.daily_seconds_left(user_id)
        if left > 0:
            bot.send_message(message.chat.id, utils.render_text("daily_cooldown", time_left=utils.fmt_hms(left)))
            return
        claimed = db.claim_daily(user_id, amount)
        if not claimed:
            # احتمالاً هم‌زمان از یه پیام دیگه (مثلا دابل‌کلیک سریع) قبلش گرفته شده
            left = db.daily_seconds_left(user_id)
            bot.send_message(message.chat.id, utils.render_text("daily_cooldown", time_left=utils.fmt_hms(left)))
            return
        bot.send_message(message.chat.id, utils.render_text("daily_success", amount=utils.fmt_num(amount)))

    # -----------------------------------------------------------------
    # آمار من
    # -----------------------------------------------------------------
    @bot.message_handler(func=lambda m: utils.is_button(m.text, "mystats"))
    def my_stats_handler(message):
        user_id = message.from_user.id
        coins = db.get_coins(user_id)
        joins = db.get_join_count(user_id)
        refs = db.get_referral_count(user_id)
        campaigns = db.list_campaigns_by_owner(user_id)
        total_members_received = sum(c["total_coins"] - c["remaining"] for c in campaigns)
        name = html.escape(message.from_user.first_name or "-")
        username = f"@{message.from_user.username}" if message.from_user.username else "-"
        text = (
            "📊 آمار شخصی شما\n\n"
            f"👤 نام: {name}\n"
            f"🆔 آیدی عددی: <code>{user_id}</code>\n"
            f"🔗 یوزرنیم: {username}\n\n"
            f"💰 موجودی فعلی: {utils.fmt_num(coins)} کوین\n"
            f"🎯 تعداد جوین‌های موفق: {utils.fmt_num(joins)}\n"
            f"👥 تعداد زیرمجموعه: {utils.fmt_num(refs)}\n"
            f"📢 کمپین‌های ثبت‌شده: {utils.fmt_num(len(campaigns))}\n"
            f"✅ ممبر واقعی دریافت‌شده: {utils.fmt_num(total_members_received)}"
        )
        bot.send_message(message.chat.id, text, parse_mode="HTML")

    # -----------------------------------------------------------------
    # پشتیبانی
    # -----------------------------------------------------------------
    @bot.message_handler(func=lambda m: utils.is_button(m.text, "support"))
    def support_handler(message):
        user_id = message.from_user.id
        support_username = db.get_setting("support_username")
        if support_username:
            text = utils.render_text("support_prompt_with_id", support_username=support_username)
        else:
            text = utils.render_text("support_prompt_without_id")
        bot.send_message(message.chat.id, text, reply_markup=kb.cancel_kb())
        utils.set_state(user_id, "awaiting_ticket_message")

    @bot.message_handler(
        func=lambda m: utils.get_state(m.from_user.id)
        and utils.get_state(m.from_user.id)["state"] == "awaiting_ticket_message"
        and m.text != "❌ انصراف"
    )
    def receive_ticket_message(message):
        user_id = message.from_user.id
        utils.clear_state(user_id)
        ticket_id = db.create_ticket(user_id, message.text)
        bot.send_message(
            message.chat.id, utils.render_text("ticket_sent"), reply_markup=kb.main_menu(user_id)
        )
        first_name = html.escape(message.from_user.first_name or "-")
        username = f"@{message.from_user.username}" if message.from_user.username else "-"
        for admin_id in db.list_admins():
            try:
                bot.send_message(
                    admin_id,
                    f"🎫 تیکت جدید #{ticket_id}\n\n"
                    f"👤 کاربر : {first_name} | {html.escape(username)}\n"
                    f"🆔️ آیدی عددی : <code>{user_id}</code>\n\n"
                    f"{html.escape(message.text)}",
                    parse_mode="HTML",
                    reply_markup=kb.ticket_reply_kb(ticket_id, user_id),
                )
            except Exception:
                pass


def register_custom_buttons(bot: telebot.TeleBot):
    """
    هندلر دکمه‌های سفارشی که ادمین از پنل ساخته - عمداً از register() اصلی
    جداست و باید بعد از ثبتِ همه‌ی هندلرهای دیگه (کاربر/پرداخت/کمپین/ادمین)
    صدا زده بشه. اگه زودتر ثبت میشد، ممکن بود برچسب یه دکمه‌ی سفارشی
    (مثلا اگه ادمین اسمش رو "50" یا "100" میذاشت) با ورودی متنیِ وسط یه
    مرحله‌ی دیگه (مثل مبلغ خرید یا آیدی کانال) قاطی بشه.
    """
    @bot.message_handler(
        func=lambda m: (btn := db.get_menu_button_by_label(m.text)) is not None
        and btn["kind"] == "custom"
    )
    def custom_button_handler(message):
        btn = db.get_menu_button_by_label(message.text)
        bot.send_message(message.chat.id, btn["custom_text"] or "—")
