import sys, os, json, time, datetime, re, requests, urllib3, uuid, subprocess, socket, base64, random, string, traceback, urllib.parse

old_getaddrinfo = socket.getaddrinfo
def new_getaddrinfo(*args, **kwargs):
    responses = old_getaddrinfo(*args, **kwargs)
    return [response for response in responses if response[0] == socket.AF_INET]
socket.getaddrinfo = new_getaddrinfo

try: import pymysql
except Exception as e: pass

from flask import Flask, request

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
if BASE_DIR not in sys.path: sys.path.insert(0, BASE_DIR)

SESSION_FILE = os.path.join(BASE_DIR, 'bot_sessions.json')
DATE_TIME_FILE = os.path.join(BASE_DIR, 'date-time.json')
WORKER_SCRIPT = os.path.join(BASE_DIR, 'worker.py')
BINANCE_WORKER_SCRIPT = os.path.join(BASE_DIR, 'payment', 'Binance', 'binance_worker.py')

def load_tz_config():
    offset_str = "+04:30"
    h, m = 4, 30
    if os.path.exists(DATE_TIME_FILE):
        try:
            with open(DATE_TIME_FILE, 'r') as f:
                dt_cfg = json.load(f)
                offset_str = dt_cfg.get('db_offset', '+04:30')
                sign = -1 if offset_str.startswith('-') else 1
                parts = offset_str.replace('+', '').replace('-', '').split(':')
                h = sign * int(parts[0])
                m = sign * int(parts[1]) if len(parts) > 1 else 0
        except: pass
    return offset_str, datetime.timezone(datetime.timedelta(hours=h, minutes=m))

DB_TZ_OFFSET, LOCAL_TZ = load_tz_config()

def gen_track_id(prefix):
    chars = string.ascii_lowercase + string.digits
    return f"{prefix}-" + ''.join(random.choices(chars, k=6))

try: from checkers import generic
except: pass

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

DB_CFG = {'host': 'localhost', 'user': 'evisuyfj_GlobalDeviceCheckerBot', 'password': 'GlobalDeviceCheckerBot', 'database': 'evisuyfj_GlobalDeviceCheckerBot', 'cursorclass': pymysql.cursors.DictCursor, 'autocommit': True, 'charset': 'utf8mb4'}
TG_URL = "https://api.telegram.org/bot8690070480:AAHfl0bPp7XIEBXCxz07fIsHU3t0hCn29eY"
CHANNEL_USERNAME = "@RaminGsmOfficial"

BINANCE_ID = "1221235491"
BINANCE_NICK = "Dear Nazari"

try: 
    from payment.Crypto.crypto_config import CRYPTO_WALLETS, MIN_DEPOSIT
except:
    CRYPTO_WALLETS = {"BEP20": "0x3f6e93c8d205a3d3d25cb3734e4515bf1bcba772", "TRC20": "TFmtEfUAAipoPcJ1PT77QrZKoUjNmykro9"}
    MIN_DEPOSIT = 5.00

TEXTS = {
    'menu_tree': "👋 <b>Welcome to Global Device Checker!</b>\n\n🔍 <b>How to use:</b>\nJust send me a 15-digit <b>IMEI</b> or Apple <b>SN</b>.\n\n🛠 <b>Commands:</b>\n   ├ /start - Main Menu\n   ├ /payment - Add Funds / Top-up\n   ├ /Reports - My Account Status\n   ├ /api - Developer API & Credit\n   └ /help - Bot Instructions",
    'help': "📚 <b>Bot Instructions</b>\nJust type your IMEI or Apple SN.",
    'force_join': "❗️ <b>You must join the developer's channel.</b>", 'not_member': "You must be a member.",
    'err_len': "❌ <b>Invalid Format</b>", 'invalid_imei': "❌ <b>Invalid IMEI</b>"
}

force_kb = {"inline_keyboard": [[{"text": "📢 Join Channel", "url": "https://t.me/RaminGsmOfficial"}], [{"text": "✅ Check Membership", "callback_data": "check_join"}]]}
MAIN_KB = {"keyboard": [[{"text": "📊 Reports"}, {"text": "💳 Payment"}], [{"text": "📚 Help"}]], "resize_keyboard": True, "is_persistent": False}

def get_conn():
    try:
        conn = pymysql.connect(**DB_CFG)
        conn.set_charset('utf8mb4')
        conn.cursor().execute(f"SET time_zone = '{DB_TZ_OFFSET}'")
        return conn
    except Exception as e:
        return None

def sync_ifree_prices():
    c = get_conn()
    if not c: return
    try:
        cur = c.cursor()
        cur.execute("SELECT setting_value FROM settings WHERE setting_key='ifree_api_key'")
        row = cur.fetchone()
        api_key = row['setting_value'] if row else "2JE-6C0-BLR-7WI-QVB-ZHZ-3GV-6ZI"
        
        resp = requests.post("https://api.ifreeicloud.co.uk", data={"accountinfo": "servicelist", "key": api_key}, timeout=4)
        data = resp.json()
        if data.get('success'):
            services = data.get('object', {})
            for sid, sinfo in services.items():
                api_price = float(sinfo.get('price', 0))
                user_price = api_price * 2.0
                reseller_price = api_price * 1.5
                cur.execute("UPDATE services SET price=%s, price_reseller=%s WHERE api_code=%s AND status=1 AND api_code LIKE 'IFREE-%'", (user_price, reseller_price, f"IFREE-{sid}"))
            c.commit()
    except: pass
    finally: c.close()

def register_user(uid, uname, fname, is_prem):
    c = get_conn()
    if c:
        try:
            cur = c.cursor()
            cur.execute("INSERT INTO users (user_id, username, fullname, is_premium, joined_at) VALUES (%s, %s, %s, %s, NOW()) ON DUPLICATE KEY UPDATE username=%s, fullname=%s, is_premium=%s", (uid, uname, fname, 1 if is_prem else 0, uname, fname, 1 if is_prem else 0))
            cur.execute("SELECT is_blocked, block_reason, role, auto_captcha, discount_percent FROM users WHERE user_id=%s", (uid,))
            return cur.fetchone()
        except: pass
        finally: c.close()
    return None

def get_user_credits(uid):
    c = get_conn()
    if c:
        try:
            cur = c.cursor()
            cur.execute("SELECT credit, api_token FROM users WHERE user_id=%s", (uid,))
            return cur.fetchone()
        except: pass
        finally: c.close()
    return None

def generate_api_token(uid):
    new_token = str(uuid.uuid4()).replace('-', '')
    c = get_conn()
    if c:
        try:
            c.cursor().execute("UPDATE users SET api_token=%s WHERE user_id=%s", (new_token, uid))
            return new_token
        except: pass
        finally: c.close()
    return None

def check_channel_member(uid):
    try:
        r = requests.post(f"{TG_URL}/getChatMember", json={"chat_id": CHANNEL_USERNAME, "user_id": int(uid)}, verify=False, timeout=5).json()
        if r.get('ok'): return r['result']['status'] in ['creator', 'administrator', 'member']
        return False
    except: return False

def get_or_create_ticket(uid):
    c = get_conn()
    ticket_id = None
    is_new = True
    if c:
        try:
            cur = c.cursor()
            cur.execute("SELECT ticket_id FROM bot_messages WHERE user_id=%s AND direction='in' AND status='pending' ORDER BY created_at DESC LIMIT 1", (uid,))
            row = cur.fetchone()
            if row and row['ticket_id']:
                ticket_id = row['ticket_id']
                is_new = False
        except: pass
        finally: c.close()
    if not ticket_id: ticket_id = gen_track_id("SMS-Ticket")
    return ticket_id, is_new

def log_message(uid, dr, txt, msg_id=None, rep=None, ticket_id=None):
    c = get_conn()
    if c:
        try: 
            status = 'pending' if dr == 'in' else 'solved'
            c.cursor().execute("INSERT INTO bot_messages (user_id, direction, msg_id, text, reply_to_text, ticket_id, status, created_at) VALUES (%s, %s, %s, %s, %s, %s, %s, NOW())", (uid, dr, msg_id, txt, rep, ticket_id, status))
            c.commit()
        except: pass
        finally: c.close()

def send(c, t, k=None):
    try:
        d = {'chat_id':c, 'text':t, 'parse_mode':'HTML'}
        if k: d['reply_markup'] = json.dumps(k)
        r = requests.post(f"{TG_URL}/sendMessage", json=d, verify=False, timeout=5).json()
        if r.get('ok'): return r['result']['message_id']
    except: pass
    return None

def send_media(c, t, k, file_path):
    try:
        ext = file_path.lower().split('.')[-1]
        url = f"{TG_URL}/sendPhoto"
        file_key = 'photo'
        d = {'chat_id': c, 'caption': t, 'parse_mode': 'HTML'}
        if k: d['reply_markup'] = json.dumps(k)
        with open(file_path, 'rb') as f:
            requests.post(url, data=d, files={file_key: (os.path.basename(file_path), f)}, verify=False, timeout=15)
    except: send(c, t, k)

def edit_message(c, m, t, k=None):
    try:
        d = {'chat_id': c, 'message_id': m, 'text': t, 'parse_mode': 'HTML'}
        if k: d['reply_markup'] = json.dumps(k)
        requests.post(f"{TG_URL}/editMessageText", json=d, verify=False, timeout=5)
    except: pass

def delete_message(c, m):
    try: requests.post(f"{TG_URL}/deleteMessage", json={'chat_id': c, 'message_id': m}, verify=False, timeout=5)
    except: pass

def show_services_menu(cid, uid, brand, imei, mid=None, u_info=None):
    sync_ifree_prices()
    c = get_conn()
    srvs = []
    if c:
        try:
            cur = c.cursor()
            cur.execute("SELECT id, service_name, price, price_reseller FROM services WHERE status=1 AND UPPER(brand)=%s ORDER BY price ASC", (brand.upper(),))
            srvs = cur.fetchall()
        except: pass
        finally: c.close()

    role = u_info.get('role', 'user') if u_info else 'user'
    discount = float(u_info.get('discount_percent', 0.0)) if u_info else 0.0

    if not srvs:
        txt = f"❌ <b>No Active Services</b>\nThere are currently no active services for <b>{brand}</b>."
        if mid: edit_message(cid, mid, txt, {"inline_keyboard": [[{"text": "🔙 Back to Brands", "callback_data": f"backbrands_{imei}_{brand}"}]]})
        else: send(cid, txt, {"inline_keyboard": [[{"text": "🔙 Back to Brands", "callback_data": f"backbrands_{imei}_{brand}"}]]})
        return

    kb = {"inline_keyboard": []}
    for s in srvs:
        base_price = float(s['price_reseller']) if role in ['reseller', 'admin'] else float(s['price'])
        final_cost = base_price * (1 - (discount / 100))
        cost_str = f"${final_cost:.2f}" if final_cost > 0 else "FREE"
        name_clean = s['service_name'].replace(" - FREE", "")
        kb["inline_keyboard"].append([{"text": f"{name_clean} - {cost_str}", "callback_data": f"draftsrv_{s['id']}_{imei}"}])
    kb["inline_keyboard"].append([{"text": "🔙 Back to Brands", "callback_data": f"backbrands_{imei}_{brand}"}])
    
    txt = f"✅ <b>Device Registered</b>\n\n🆔 <b>IMEI/SN:</b> <code>{imei}</code>\n📱 <b>Brand:</b> {brand}\n\n👇 Please select a service from the list below:"
    if mid: edit_message(cid, mid, txt, kb)
    else: send(cid, txt, kb)

def trigger_worker():
    try: subprocess.Popen([sys.executable, WORKER_SCRIPT], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, close_fds=True, start_new_session=True)
    except: pass

def handle_report_command(cid, uid, cmd):
    c = get_conn()
    if not c: return
    cur = c.cursor()
    out = f"📋 <b>Report for {cmd}</b>\n\n"
    if cmd == '/Paid' or cmd == '/USED':
        cur.execute("SELECT id, track_id, imei, brand, cost, created_at FROM imei_logs WHERE user_id=%s AND status IN ('FULL', 'SUCCESS') AND cost > 0 ORDER BY created_at DESC LIMIT 20", (uid,))
        for r in cur.fetchall(): 
            dt = r['created_at'].strftime('%Y-%m-%d %H:%M') if isinstance(r['created_at'], datetime.datetime) else r['created_at']
            track_display = r['track_id'] if r['track_id'] else f"PAID_{r['id']}"
            out += f"🔹 <code>{r['imei']}</code> - {r['brand']} - ${r['cost']} ({track_display})\n   🕒 <i>{dt}</i>\n"
    elif cmd == '/FREE':
        cur.execute("SELECT id, track_id, imei, brand, created_at FROM imei_logs WHERE user_id=%s AND status IN ('FULL', 'SUCCESS', 'BASIC') AND cost = 0 ORDER BY created_at DESC LIMIT 20", (uid,))
        for r in cur.fetchall(): 
            dt = r['created_at'].strftime('%Y-%m-%d %H:%M') if isinstance(r['created_at'], datetime.datetime) else r['created_at']
            track_display = r['track_id'] if r['track_id'] else f"FREE_{r['id']}"
            out += f"🔹 <code>{r['imei']}</code> - {r['brand']} - FREE ({track_display})\n   🕒 <i>{dt}</i>\n"
    elif cmd == '/Total':
        cur.execute("SELECT id, track_id, imei, brand, cost, status, created_at FROM imei_logs WHERE user_id=%s AND status NOT IN ('PENDING', 'PROCESSING', 'DRAFT') ORDER BY created_at DESC LIMIT 20", (uid,))
        for r in cur.fetchall(): 
            dt = r['created_at'].strftime('%Y-%m-%d %H:%M') if isinstance(r['created_at'], datetime.datetime) else r['created_at']
            cst = f"${r['cost']}" if float(r['cost']) > 0 else "FREE"
            track_display = r['track_id'] if r['track_id'] else (f"PAID_{r['id']}" if float(r['cost']) > 0 else f"FREE_{r['id']}")
            out += f"🔹 <code>{r['imei']}</code> - {r['brand']} - {cst} ({track_display})\n   🕒 <i>{dt}</i>\n"
    elif cmd == '/Refund':
        cur.execute("SELECT amount, note, created_at FROM transactions WHERE user_id=%s AND type='REFUND' ORDER BY created_at DESC LIMIT 20", (uid,))
        for r in cur.fetchall():
            dt = r['created_at'].strftime('%Y-%m-%d %H:%M') if isinstance(r['created_at'], datetime.datetime) else r['created_at']
            note = r['note'][:40] + "..." if len(r['note']) > 40 else r['note']
            out += f"🔹 +${r['amount']} - <i>{note}</i>\n   🕒 <i>{dt}</i>\n"
    elif cmd == '/Credit':
        cur.execute("SELECT amount, note, created_at FROM transactions WHERE user_id=%s AND type='CREDIT_ADD' ORDER BY created_at DESC LIMIT 20", (uid,))
        for r in cur.fetchall():
            dt = r['created_at'].strftime('%Y-%m-%d %H:%M') if isinstance(r['created_at'], datetime.datetime) else r['created_at']
            note = r['note'][:40] + "..." if len(r['note']) > 40 else r['note']
            out += f"🔹 +${r['amount']} - <i>{note}</i>\n   🕒 <i>{dt}</i>\n"
    elif cmd in ['/Xiaomi', '/Apple', '/Transsion']:
        brand_map = {'/Xiaomi':'XIAOMI', '/Apple':'APPLE', '/Transsion':'TRANSSION'}
        b = brand_map[cmd]
        if b == 'TRANSSION':
            cur.execute("SELECT id, track_id, imei, status, cost, created_at FROM imei_logs WHERE user_id=%s AND brand IN ('Transsion', 'TECNO', 'Infinix', 'itel') ORDER BY created_at DESC LIMIT 20", (uid,))
        else:
            cur.execute("SELECT id, track_id, imei, status, cost, created_at FROM imei_logs WHERE user_id=%s AND UPPER(brand)=%s ORDER BY created_at DESC LIMIT 20", (uid, b))
        for r in cur.fetchall(): 
            dt = r['created_at'].strftime('%Y-%m-%d %H:%M') if isinstance(r['created_at'], datetime.datetime) else r['created_at']
            track_display = r['track_id'] if r['track_id'] else (f"PAID_{r['id']}" if float(r['cost']) > 0 else f"FREE_{r['id']}")
            out += f"🔹 <code>{r['imei']}</code> - {r['status']} ({track_display})\n   🕒 <i>{dt}</i>\n"
    elif cmd == '/Reports':
        cur.execute("SELECT COUNT(*) as c FROM imei_logs WHERE user_id=%s AND status IN ('FULL', 'SUCCESS') AND cost > 0", (uid,))
        paid_count = cur.fetchone()['c']
        cur.execute("SELECT COUNT(*) as c FROM imei_logs WHERE user_id=%s AND status IN ('FULL', 'SUCCESS', 'BASIC') AND cost = 0", (uid,))
        free_count = cur.fetchone()['c']
        total_count = paid_count + free_count
        cur.execute("SELECT credit FROM users WHERE user_id=%s", (uid,))
        ur = cur.fetchone()
        rem_credit = float(ur['credit']) if ur else 0.0
        cur.execute("SELECT SUM(cost) as s FROM imei_logs WHERE user_id=%s AND status IN ('FULL', 'SUCCESS') AND cost > 0", (uid,))
        ur = cur.fetchone()
        used_credit = float(ur['s'] or 0.0)
        cur.execute("SELECT SUM(amount) as s FROM transactions WHERE user_id=%s AND type='REFUND'", (uid,))
        ur = cur.fetchone()
        refund_credit = float(ur['s'] or 0.0)
        cur.execute("SELECT SUM(amount) as s FROM transactions WHERE user_id=%s AND type='CREDIT_ADD'", (uid,))
        ur = cur.fetchone()
        total_credit = float(ur['s'] or 0.0)
        cur.execute("SELECT brand, COUNT(*) as c FROM imei_logs WHERE user_id=%s AND status IN ('FULL', 'SUCCESS', 'BASIC') GROUP BY brand", (uid,))
        brands = cur.fetchall()
        xiaomi_c = sum([b['c'] for b in brands if b['brand'].upper() == 'XIAOMI'])
        apple_c = sum([b['c'] for b in brands if b['brand'].upper() == 'APPLE'])
        trans_c = sum([b['c'] for b in brands if b['brand'].upper() in ['TRANSSION', 'TECNO', 'INFINIX', 'ITEL']])
        out = "<b>Reports</b>\n<b>📂 Total Check Device</b>\n"
        out += f" ├ <b>/Paid</b>: {paid_count}\n ├ <b>/FREE</b>: {free_count}\n └ <b>/Total</b>: {total_count}\n\n"
        out += "<b>📂 Finance Details</b>\n"
        out += f" ├ <b>/Credit</b>: {total_credit:g}\n ├ <b>/USED</b>: {used_credit:g}\n ├ <b>/Refund</b>: {refund_credit:g}\n └ 📱 Remaining: {rem_credit:g}\n\n"
        out += "<b>📂 Brand Details</b>\n"
        out += f" ├ <b>/Xiaomi</b>: {xiaomi_c}\n ├ <b>/Apple</b>: {apple_c}\n └ <b>/Transsion</b>: {trans_c}\n"

    if out == f"📋 <b>Report for {cmd}</b>\n\n": out += "No records found."
    send(cid, out, MAIN_KB)
    c.close()

application = Flask(__name__)
class ForceRootRouter(object):
    def __init__(self, app): self.app = app
    def __call__(self, environ, start_response):
        environ['SCRIPT_NAME'] = ''; environ['PATH_INFO'] = '/'
        return self.app(environ, start_response)
application.wsgi_app = ForceRootRouter(application.wsgi_app)

@application.route('/', methods=['POST','GET'], strict_slashes=False)
@application.route('/<path:dummy>', methods=['POST','GET'], strict_slashes=False)
def index(dummy=None):
    try:
        if dummy == 'run_worker' or request.path.endswith('run_worker'):
            trigger_worker()
            return "Triggered", 200

        if request.method == 'GET': return "✅ GlobalDeviceCheckerBot is Running!"
        
        dt = request.get_json(force=True, silent=True)
        if not dt: return "ok", 200
        
        o = dt.get('callback_query') or dt.get('message')
        if not o: return "ok",200
        
        frm = o.get('from', {})
        uid, uname, fname, is_prem = str(frm.get('id')), frm.get('username', 'None'), frm.get('first_name', 'Unknown'), frm.get('is_premium', False) 
        cid, mid = o['message']['chat']['id'] if dt.get('callback_query') else o['chat']['id'], o['message']['message_id'] if dt.get('callback_query') else o.get('message_id')
        
        u_info = register_user(uid, uname, fname, is_prem)
        if u_info and u_info.get('is_blocked') == 1:
            if u_info.get('block_reason'): send(cid, "🚫 <b>Access Denied</b>\n\n"+u_info.get('block_reason'))
            return "ok", 200
        
        is_member = check_channel_member(uid)

        if 'callback_query' in dt:
            data, cq_id = dt['callback_query']['data'], dt['callback_query']['id']
            if data == 'addfunds_menu':
                txt = f"💳 <b>Select Payment Method</b>\n\nTo proceed, please select your preferred method:"
                kb = {"inline_keyboard": [
                    [{"text": "💳 S-PayWay (Secure Gateway)", "callback_data": "paym_spayway"}],
                    [{"text": "🪙 Crypto (USDT BEP20 / TRC20)", "callback_data": "paym_crypto_wallet"}],
                    [{"text": "🟨 Binance Pay (Automatic)", "callback_data": "paym_binpay_auto"}],
                    [{"text": "❌ Cancel", "callback_data": "cancel_draft"}]
                ]}
                edit_message(cid, mid, txt, kb)
                return "ok", 200

            if data == 'paym_spayway':
                safe_fname = urllib.parse.quote(fname)
                safe_uname = urllib.parse.quote(uname)
                url = f"https://extensions.evisatraveller-mfa.app/GlobalDeviceCheckerBot/payment.php?uid={uid}&username={safe_uname}&fullname={safe_fname}"
                txt = f"<b>💳 S-PayWay Payment</b>\n\nYour Identity:\n👤 Name: <b>{fname}</b>\n🆔 User ID: <code>{uid}</code>\n\nClick below to securely add funds."
                kb = {"inline_keyboard": [[{"text": "🌐 Open Secure Gateway", "web_app": {"url": url}}], [{"text": "🔙 Back", "callback_data": "addfunds_menu"}]]}
                edit_message(cid, mid, txt, kb)
                return "ok", 200

            if data == 'paym_crypto_wallet':
                txt = f"<b>🪙 Crypto Transfer (USDT)</b>\n\n<b>Deposit Addresses:</b>\n🔸 <b>BEP20 (BSC):</b>\n<code>{CRYPTO_WALLETS['BEP20']}</code>\n\n🔸 <b>TRC20 (Tron):</b>\n<code>{CRYPTO_WALLETS['TRC20']}</code>\n\n<i>⚠️ Please select the amount you want to deposit (Min ${MIN_DEPOSIT:g}):</i>"
                kb = {"inline_keyboard": [
                    [{"text": "$5", "callback_data": "crypamt_5"}, {"text": "$10", "callback_data": "crypamt_10"}, {"text": "$15", "callback_data": "crypamt_15"}],
                    [{"text": "$20", "callback_data": "crypamt_20"}, {"text": "$30", "callback_data": "crypamt_30"}, {"text": "$50", "callback_data": "crypamt_50"}],
                    [{"text": "$100", "callback_data": "crypamt_100"}, {"text": "$150", "callback_data": "crypamt_150"}, {"text": "$500", "callback_data": "crypamt_500"}],
                    [{"text": "$1000", "callback_data": "crypamt_1000"}, {"text": "More...", "callback_data": "crypamt_more"}],
                    [{"text": "🔙 Back", "callback_data": "addfunds_menu"}]
                ]}
                edit_message(cid, mid, txt, kb)
                return "ok", 200

            if data.startswith('crypamt_'):
                amt_str = data.split('_')[1]
                if amt_str == 'more':
                    txt = f"<b>🪙 Crypto Transfer (Custom Amount)</b>\n\n<blockquote><b>📂 How to Pay:</b>\n ├ 1️⃣ Open your Crypto Wallet.\n ├ 2️⃣ Send your desired amount (Min <b>${MIN_DEPOSIT:g}</b>) to:\n │   ├ 🔸 <b>BEP20:</b> <code>{CRYPTO_WALLETS['BEP20']}</code>\n │   └ 🔸 <b>TRC20:</b> <code>{CRYPTO_WALLETS['TRC20']}</code>\n └ 3️⃣ Copy the TXID (Transaction Hash).</blockquote>\n<i>⚠️ Make the payment, submit the TXID, and the administrator will review and credit the exact amount you sent.</i>"
                else:
                    txt = f"<b>🪙 Crypto Transfer (${amt_str})</b>\n\n<blockquote><b>📂 How to Pay:</b>\n ├ 1️⃣ Open your Crypto Wallet.\n ├ 2️⃣ Send EXACTLY <b>{amt_str} USDT</b> to:\n │   ├ 🔸 <b>BEP20:</b> <code>{CRYPTO_WALLETS['BEP20']}</code>\n │   └ 🔸 <b>TRC20:</b> <code>{CRYPTO_WALLETS['TRC20']}</code>\n └ 3️⃣ Copy the TXID (Transaction Hash).</blockquote>\n<i>⚠️ Click <b>I Have Paid</b> ONLY after successful transfer.</i>"
                
                kb = {"inline_keyboard": [
                    [{"text": "✅ I Have Paid (Submit TXID)", "callback_data": f"submittxid_crypto_{amt_str}"}],
                    [{"text": "❌ Cancel", "callback_data": "cancel_draft"}]
                ]}
                edit_message(cid, mid, txt, kb)
                return "ok", 200

            if data.startswith('submittxid_crypto_'):
                amt_str = data.split('_')[2]
                s = json.load(open(SESSION_FILE)) if os.path.exists(SESSION_FILE) else {}
                if uid not in s: s[uid] = {}
                s[uid]['st'] = 'AWAITING_CRYPTO_TXID'
                s[uid]['tmp_crypto_amt'] = amt_str
                json.dump(s, open(SESSION_FILE, 'w'))
                
                txt = "📝 <b>Submit Transaction Details</b>\n\nPlease <b>type or paste</b> your <b>TXID (Transaction Hash)</b> below:"
                delete_message(cid, mid)
                send(cid, txt, MAIN_KB)
                return "ok", 200

            if data == 'paym_binpay_auto':
                s = json.load(open(SESSION_FILE)) if os.path.exists(SESSION_FILE) else {}
                if uid not in s: s[uid] = {}
                s[uid]['st'] = 'AWAITING_BINANCE_AMOUNT'
                json.dump(s, open(SESSION_FILE, 'w'))
                txt = "<b>🟨 Binance Pay (Automatic)</b>\n\nHow much USDT do you want to deposit?\n<i>(Minimum: $1.00)</i>\n\nPlease <b>type the amount</b> below:"
                delete_message(cid, mid)
                send(cid, txt, MAIN_KB)
                return "ok", 200

            if data.startswith('checkbinpay_'):
                payload = data.replace('checkbinpay_', '')
                retry_count = int(payload.split('||')[1]) if '||' in payload else 0
                inv_id = payload.split('||')[0] if '||' in payload else payload
                
                c = get_conn()
                amount_str, username_str = "0", "Unknown"
                if c:
                    cur = c.cursor()
                    cur.execute("SELECT amount, txid, status FROM invoices WHERE invoice_id=%s", (inv_id,))
                    inv = cur.fetchone()
                    if inv:
                        if inv['status'] == 'PAID':
                            requests.post(f"{TG_URL}/answerCallbackQuery", json={"callback_query_id": cq_id, "text": "Already Paid!"})
                            c.close(); return "ok", 200
                        amount_str, username_str = str(inv['amount']), inv['txid']
                        cur.execute("UPDATE invoices SET status='VERIFYING' WHERE invoice_id=%s", (inv_id,))
                        c.commit()
                    c.close()

                scan_txt = f"<b>⏳ Scanning Binance Network...</b>\nyour invoice id: <code>{inv_id}</code>\nChecking for your payment of <b>${float(amount_str):g}</b> from <b>{username_str}</b>.\n<blockquote> ├  To This Binance User\n │   ├ 🆔 <b>Binance ID:</b> <code>{BINANCE_ID}</code>\n │   └ 👤 <b>Nickname: {BINANCE_NICK}</b>\n └ I am waiting...</blockquote><i>Attempt 1/6... Please wait up to 1 minute.</i>"
                kb = {"inline_keyboard": [[{"text": "❌ Cancel payment", "callback_data": "cancel_draft"}]]}
                
                requests.post(f"{TG_URL}/editMessageReplyMarkup", json={'chat_id': cid, 'message_id': mid, 'reply_markup': json.dumps({'inline_keyboard': []})}, verify=False)
                new_mid = send(cid, scan_txt, kb)
                if not new_mid: new_mid = mid
                
                try: subprocess.Popen([sys.executable, BINANCE_WORKER_SCRIPT, uid, str(cid), str(new_mid), inv_id, str(retry_count)], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, close_fds=True, start_new_session=True)
                except: pass
                return "ok", 200

            if data.startswith('selbrand_'):
                parts = data.split('_')
                brand_safe, imei_str = parts[1], parts[2]
                show_services_menu(cid, uid, brand_safe, imei_str, mid, u_info)
                return "ok", 200

            if data.startswith('draftsrv_'):
                parts = data.split('_')
                srv_id, imei_str = parts[1], parts[2]
                
                c = get_conn()
                srv_info = None
                if c:
                    cur = c.cursor()
                    cur.execute("SELECT * FROM services WHERE id=%s", (srv_id,))
                    srv_info = cur.fetchone()
                    c.close()
                    
                if not srv_info:
                    edit_message(cid, mid, "❌ Service not found.")
                    return "ok", 200
                    
                role = u_info.get('role', 'user') if u_info else 'user'
                discount = float(u_info.get('discount_percent', 0.0)) if u_info else 0.0
                base_price = float(srv_info['price_reseller']) if role in ['reseller', 'admin'] else float(srv_info['price'])
                cost = base_price * (1 - (discount / 100))
                bal = float(get_user_credits(uid)['credit'] if get_user_credits(uid) else 0.0)
                
                txt = f"✅ <b>Service Selected</b>\n\n📱 <b>Service:</b> {srv_info['service_name']}\n⚠️ This operation will deduct <b>${cost:.2f}</b> credits.\n💰 Current credit: <b>${bal:.2f}</b>\n\nDo you want to proceed?"

                kb = {"inline_keyboard": []}
                if bal >= cost: kb["inline_keyboard"].append([{"text": f"✅ Confirm (Cost: ${cost:g})", "callback_data": f"confirmsrv_{srv_id}_{imei_str}"}])
                else: kb["inline_keyboard"].append([{"text": f"💳 Add Funds (Payment)", "callback_data": f"addfunds_menu"}])
                kb["inline_keyboard"].append([{"text": "🔙 Back", "callback_data": f"selbrand_{srv_info['brand']}_{imei_str}"}])
                edit_message(cid, mid, txt, kb)
                return "ok", 200

            if data.startswith('confirmsrv_'):
                parts = data.split('_')
                srv_id, imei = parts[1], parts[2]
                
                c = get_conn()
                srv_info = None
                if c:
                    cur = c.cursor()
                    cur.execute("SELECT * FROM services WHERE id=%s", (srv_id,))
                    srv_info = cur.fetchone()
                
                if not srv_info:
                    if c: c.close()
                    return "ok", 200
                    
                role = u_info.get('role', 'user') if u_info else 'user'
                discount = float(u_info.get('discount_percent', 0.0)) if u_info else 0.0
                base_price = float(srv_info['price_reseller']) if role in ['reseller', 'admin'] else float(srv_info['price'])
                cost = base_price * (1 - (discount / 100))
                
                bal = float(get_user_credits(uid)['credit'] if get_user_credits(uid) else 0.0)
                if bal < cost:
                    edit_message(cid, mid, f"❌ <b>Insufficient Balance</b>\nYour balance is ${bal:.2f}, but this requires ${cost:.2f}.")
                    if c: c.close()
                    return "ok", 200
                    
                if cost > 0: cur.execute("UPDATE users SET credit = credit - %s WHERE user_id = %s", (cost, uid))
                
                track_id = gen_track_id("ORDER")
                brand_safe = srv_info['brand']
                cur.execute("INSERT INTO imei_logs (user_id, service_id, imei, status, brand, cost, source, created_at, track_id) VALUES (%s, %s, %s, 'PENDING', %s, %s, 'BOT', NOW(), %s)", (uid, srv_id, imei, brand_safe, cost, track_id))
                c.commit(); c.close()
                name_clean = srv_info['service_name'].replace(" - FREE", "")
                edit_message(cid, mid, f"📂 <b>Server Status</b>\n ├ 🆔 <b>Work ID:</b> {track_id}\n ├ ▶️ <b>Action:</b> {name_clean}\n └ ⏳ <b>Status:</b> Processing...\n\nYour request is queued Please wait.\nThis may take up to 60 seconds.")
                trigger_worker(); return "ok", 200

            if data == 'cancel_draft':
                delete_message(cid, mid)
                return "ok", 200

        tmsg = o.get('text','').strip()
        tmsg_lower = tmsg.lower()
        if tmsg_lower.startswith('/'):
            if os.path.exists(SESSION_FILE):
                try: s = json.load(open(SESSION_FILE)); s.get(uid, {})['st'] = 'IDLE'; json.dump(s, open(SESSION_FILE, 'w'))
                except: pass
            
            if tmsg_lower == '/start': send(cid, TEXTS['menu_tree'], MAIN_KB)
            elif tmsg_lower == '/help': send(cid, TEXTS['help'], MAIN_KB)
            elif tmsg_lower == '/api':
                ud = get_user_credits(uid)
                bal, tok = float(ud['credit']) if ud else 0.0, ud['api_token'] if ud else generate_api_token(uid)
                send(cid, f"👤 <b>Your API Info</b>\n\n💰 <b>Balance:</b> <code>${bal:.2f}</code>\n🔑 <b>API Token:</b>\n<code>{tok}</code>", {"inline_keyboard": [[{"text": "🔄 Gen New Token", "callback_data": "gen_token"}]]})
            elif tmsg_lower == '/payment':
                send(cid, "💳 <b>Select Payment Method</b>\n\nPlease select your preferred top-up method:", {"inline_keyboard": [[{"text": "💳 S-PayWay (Secure Gateway)", "callback_data": "paym_spayway"}], [{"text": "🪙 Crypto (USDT)", "callback_data": "paym_crypto_wallet"}], [{"text": "🟨 Binance Pay", "callback_data": "paym_binpay_auto"}], [{"text": "❌ Cancel", "callback_data": "cancel_draft"}]]})
            elif tmsg in ['/Paid', '/FREE', '/Total', '/Credit', '/USED', '/Refund', '/Remining', '/Xiaomi', '/Apple', '/Transsion', '/Reports']: handle_report_command(cid, uid, tmsg)
            else: send(cid, TEXTS['menu_tree'], MAIN_KB)
            return "ok", 200

        if tmsg == '📚 Help':
            send(cid, TEXTS['help'], MAIN_KB)
            return "ok", 200
        elif tmsg == '💳 Payment':
            send(cid, "💳 <b>Select Payment Method</b>\n\nPlease select your preferred top-up method:", {"inline_keyboard": [[{"text": "💳 S-PayWay (Secure Gateway)", "callback_data": "paym_spayway"}], [{"text": "🪙 Crypto (USDT)", "callback_data": "paym_crypto_wallet"}], [{"text": "🟨 Binance Pay", "callback_data": "paym_binpay_auto"}], [{"text": "❌ Cancel", "callback_data": "cancel_draft"}]]})
            return "ok", 200
        elif tmsg == '📊 Reports':
            handle_report_command(cid, uid, '/Reports')
            return "ok", 200

        tmsg_upper = tmsg.upper()
        if not (len(tmsg) == 15 and tmsg.isdigit()) and not (len(tmsg_upper) in (10, 12) and re.match(r'^[A-Z0-9]+$', tmsg_upper) and not tmsg.isdigit()):
            ticket_id, is_new = get_or_create_ticket(uid)
            log_message(uid, 'in', tmsg, mid, '', ticket_id)
            if is_new: send(cid, f"✅ Message sent to admin!\n🎫 Ticket ID: <code>{ticket_id}</code>\nStatus: ⏳ Pending", MAIN_KB)
            else: send(cid, f"✅ Message added to open ticket: <code>{ticket_id}</code>", MAIN_KB)
            return "ok",200

        inf = generic.call_ifree(tmsg_upper)
        brand_safe = generic.get_dynamic_brand(str(inf.get('product') or inf.get('model') or '').upper(), inf.get('brand') or ("Apple" if not tmsg.isdigit() else "Unknown"))
        
        if not brand_safe or brand_safe == 'Unknown':
            kb = {"inline_keyboard": [
                [{"text": "🍎 Apple", "callback_data": f"selbrand_APPLE_{tmsg_upper}"}, {"text": "🟠 Xiaomi", "callback_data": f"selbrand_XIAOMI_{tmsg_upper}"}], 
                [{"text": "📱 Transsion", "callback_data": f"selbrand_TRANSSION_{tmsg_upper}"}, {"text": "🔵 Samsung", "callback_data": f"selbrand_SAMSUNG_{tmsg_upper}"}], 
                [{"text": "❌ Cancel", "callback_data": "cancel_draft"}]]}
            send(cid, "⚠️ <b>Brand Not Detected</b>\nWe couldn't automatically detect the brand.\n\n👇 Please select manually:", kb)
            return "ok", 200

        show_services_menu(cid, uid, brand_safe, tmsg_upper, None, u_info)

    except Exception as e: pass
    return "ok",200

if __name__ == '__main__':
    application.run(port=5000)