import datetime
import random

import requests
from telethon import TelegramClient, events, Button
import sqlite3
from datetime import date
import asyncio

# ========== 配置区 ==========
API_ID = 2040
API_HASH = "b18441a1ff607e10a989891a5462e627"
BOT_TOKEN = "8451724418:AAGTGqCmc1JiUr88IABhMiQTHeVLcAcnT5Y"
DB_PATH = "sign.db"
SIGN_POINTS = 10

ALLOWED_GROUPS = [-1003238845008]

PROXY = {
    'proxy_type': "socks5",
    'addr': "202.155.144.102",
    'port': 31102,
    'username': "SyNuejCtrQ",
    'password': "MH8ioL7EXf"
}

INVITE_LINK = "https://www.websea.my/en/signup?key=77346588"
# ============================

# 命令字典
COMMANDS = {
    '/sign': '签到，每天签到一次，获取积分',
    '签到': '签到，每天签到一次，获取积分',
    '/daily_rank': '查看今日发言排行',
    '/my_invites': '查看你邀请的人数',
    # '/btc': '获取 BTC/USDT 最新价格',
    '/help': '显示所有可用命令及说明'
}

# 命令分组
data = {
    "签到": ['/sign', '签到',"/tanda"],
    "发言": ["/daily_rank","发言","/kedudukan_harian"],
    "邀请": ['/my_invites',"邀请","/daily_position"],
    "币价": ['/btc', 'btc']
}

# 支持币种
crypto_currencies = {
    "BTC": {"type": "BTC-USDT", "url": "https://www.websea.com/zh-CN/trade/BTC-USDT"},
    "ETH": {"type": "ETH-USDT", "url": "https://www.websea.com/zh-CN/trade/ETH-USDT"},
    "SOL": {"type": "SOL-USDT", "url": "https://www.websea.com/zh-CN/trade/SOL-USDT"},
    "BNB": {"type": "BNB-USDT", "url": "https://www.websea.com/zh-CN/trade/BNB-USDT"},
    "WBS": {"type": "WBS-USDT", "url": "https://www.websea.com/zh-CN/trade/WBS-USDT"}
}

# 主菜单按钮
main_buttons = [
    [Button.inline("签到", b"/sign"), Button.inline("今日发言排行", b"/daily_rank")],
    [Button.inline("我的邀请", b"/my_invites"), Button.inline("币价", b"/btc")],
    [Button.inline("帮助", b"/help")]
]


def get_command_list_text():
    msg = "🤖 机器人命令列表：\n"
    for cmd, desc in COMMANDS.items():
        msg += f"{cmd} → {desc}\n"
    return msg


# ---------- 数据库 ----------
def init_db():
    conn = sqlite3.connect(DB_PATH)
    cursor = conn.cursor()
    cursor.execute('''
                   CREATE TABLE IF NOT EXISTS users
                   (
                       user_id
                       INTEGER
                       PRIMARY
                       KEY,
                       username
                       TEXT,
                       points
                       INTEGER
                       DEFAULT
                       0,
                       last_sign_date
                       TEXT
                   )
                   ''')
    cursor.execute('''
                   CREATE TABLE IF NOT EXISTS daily_messages
                   (
                       user_id
                       INTEGER,
                       date
                       TEXT,
                       count
                       INTEGER
                       DEFAULT
                       0,
                       PRIMARY
                       KEY
                   (
                       user_id,
                       date
                   )
                       )
                   ''')
    cursor.execute('''
                   CREATE TABLE IF NOT EXISTS invites
                   (
                       inviter_id
                       INTEGER,
                       invitee_id
                       INTEGER,
                       PRIMARY
                       KEY
                   (
                       inviter_id,
                       invitee_id
                   )
                       )
                   ''')
    conn.commit()
    conn.close()


def add_or_update_user(user_id, username):
    conn = sqlite3.connect(DB_PATH)
    cursor = conn.cursor()
    cursor.execute("INSERT OR IGNORE INTO users (user_id, username) VALUES (?, ?)", (user_id, username))
    cursor.execute("UPDATE users SET username=? WHERE user_id=?", (username, user_id))
    conn.commit()
    conn.close()


def can_sign(user_id):
    conn = sqlite3.connect(DB_PATH)
    cursor = conn.cursor()
    cursor.execute("SELECT last_sign_date FROM users WHERE user_id=?", (user_id,))
    row = cursor.fetchone()
    today = date.today().isoformat()
    conn.close()
    return False if row and row[0] == today else True


def add_points(user_id, points):
    today = date.today().isoformat()
    conn = sqlite3.connect(DB_PATH)
    cursor = conn.cursor()
    cursor.execute(
        "UPDATE users SET points = points + ?, last_sign_date = ? WHERE user_id = ?",
        (points, today, user_id)
    )
    conn.commit()
    conn.close()


def get_points(user_id):
    conn = sqlite3.connect(DB_PATH)
    cursor = conn.cursor()
    cursor.execute("SELECT points FROM users WHERE user_id=?", (user_id,))
    row = cursor.fetchone()
    conn.close()
    return row[0] if row else 0


# ---------- 发言统计 ----------
def add_message(user_id):
    today = date.today().isoformat()
    conn = sqlite3.connect(DB_PATH)
    cursor = conn.cursor()
    cursor.execute('''
                   INSERT INTO daily_messages (user_id, date, count)
                   VALUES (?, ?, 1) ON CONFLICT(user_id, date) DO
                   UPDATE SET count = count + 1
                   ''', (user_id, today))
    conn.commit()
    conn.close()


def get_daily_message_ranking():
    today = date.today().isoformat()
    conn = sqlite3.connect(DB_PATH)
    cursor = conn.cursor()
    cursor.execute('''
                   SELECT u.username, d.count
                   FROM daily_messages d
                            JOIN users u ON d.user_id = u.user_id
                   WHERE d.date = ?
                   ORDER BY d.count DESC
                   ''', (today,))
    rows = cursor.fetchall()
    conn.close()
    return rows


# ---------- 币价 ----------
def get_price(symbol: str):
    headers = {'user-agent': 'Mozilla/5.0'}
    tz = datetime.timezone(datetime.timedelta(hours=8))
    today = datetime.datetime.now(tz).date()
    start_of_day = datetime.datetime.combine(today, datetime.time.min, tzinfo=tz)
    end_of_day = datetime.datetime.combine(today, datetime.time.max, tzinfo=tz)

    params = {
        'symbol': symbol,
        'period': '30min',
        'start': int(start_of_day.timestamp()),
        'end': int(end_of_day.timestamp()),
    }

    try:
        response = requests.get('https://eapi.websea.com/webApi/market/getKline', params=params, headers=headers,
                                timeout=10)
        data = response.json()["result"]["data"]
        if not data:
            return 0, 0, 0, 0
        current_price = float(data[0]['close'])
        today_high = max(float(i['high']) for i in data)
        today_low = min(float(i['low']) for i in data)
        price_24h_ago = float(data[-1]['open'])
        change_24h = (current_price - price_24h_ago) / price_24h_ago * 100
        return current_price, change_24h, today_high, today_low
    except Exception as e:
        print("获取币价失败:", e)
        return 0, 0, 0, 0


def get_price_msg(symbol: str):
    current_price, change_24h, today_high, today_low = get_price(symbol)
    name = symbol.split('-')[0]
    url = crypto_currencies.get(name, {}).get("url", "#")
    msg = (
        f"📊 {name}/USDT 实时行情\n\n"
        f"💰 当前价格：{current_price:.4f} USDT\n"
        f"📈 24小时涨跌幅：{change_24h:.2f}%\n"
        f"⬆️ 最高价：{today_high:.4f} USDT\n"
        f"⬇️ 最低价：{today_low:.4f} USDT\n\n"
        f"🔗 交易链接：[点击前往]({url})\n"
        f"🎁 注册邀请：[立即加入]({INVITE_LINK})"
    )
    return msg


def get_crypto_buttons():
    """生成币种选择按钮"""
    buttons = []
    row = []
    for name in crypto_currencies.keys():
        row.append(Button.inline(name, f"price_{name}".encode()))
        if len(row) == 3:
            buttons.append(row)
            row = []
    if row:
        buttons.append(row)
    buttons.append([Button.inline("返回菜单", b"/help")])
    return buttons


# ---------- 命令处理 ----------
async def handle_command(event, cmd):
    user = await event.get_sender()
    user_id = user.id
    username = user.username or user.first_name or "未知用户"

    add_or_update_user(user_id, username)
    reply = ""

    if cmd in data["签到"]:
        if not can_sign(user_id):
            reply = f"🌞 @{username}，你今天已经签到过啦！"
        else:
            add_points(user_id, SIGN_POINTS)
            total = get_points(user_id)
            reply = f"✅ @{username} 签到成功！获得 {SIGN_POINTS} 积分\n当前总积分：{total}"
    elif cmd in data["发言"]:
        ranking = get_daily_message_ranking()
        if not ranking:
            reply = "📊 今日还没有人发言哦～"
        else:
            reply = "📊 今日发言排行：\n" + "\n".join(f"{i + 1}. {u}: {c}条" for i, (u, c) in enumerate(ranking))
    elif cmd in data["邀请"]:
        conn = sqlite3.connect(DB_PATH)
        cursor = conn.cursor()
        cursor.execute("SELECT COUNT(*) FROM invites WHERE inviter_id=?", (user_id,))
        count = cursor.fetchone()[0]
        conn.close()
        reply = f"👥 @{username}，你邀请了 {count} 人。"
    elif cmd in data["币价"]:
        await event.respond("请选择要查看的币种：", buttons=get_crypto_buttons())
        return
    else:
        await event.reply(get_command_list_text(), buttons=main_buttons)
        return

    await event.reply(reply)


# ---------- 价格按钮处理 ----------
async def handle_price_command(event, symbol_name: str):
    symbol = crypto_currencies[symbol_name]["type"]
    msg = get_price_msg(symbol)
    await event.edit(msg, buttons=get_crypto_buttons(), link_preview=False)


# ---------- 主逻辑 ----------
async def main():
    init_db()
    bot = TelegramClient('bot_session', API_ID, API_HASH, proxy=PROXY)
    await bot.start(bot_token=BOT_TOKEN)

    # 定时发送 SOL 币价
    for group_id in ALLOWED_GROUPS:
        asyncio.create_task(send_price_periodically(bot, group_id))

    # 欢迎新成员
    @bot.on(events.ChatAction)
    async def welcome(event):
        if event.user_added or event.user_joined:
            for user in event.users:
                name = user.username or user.first_name or "新成员"
                await event.reply(f"欢迎 @{name} 加入群聊！\n{get_command_list_text()}")

    # 普通消息
    @bot.on(events.NewMessage)
    async def on_message(event):
        if event.chat_id not in ALLOWED_GROUPS:
            return

        text = event.raw_text.strip().lower()

        # ✅ 去掉命令中的 @botname（如 /sign@dockersebot → /sign）
        if "@" in text:
            text = text.split("@")[0]

        for group in data:
            if text in [cmd.lower() for cmd in data[group]]:
                await handle_command(event, text)
                return

        add_message((await event.get_sender()).id)

    # # help
    # @bot.on(events.NewMessage(pattern='/help'))
    # async def send_help(event):

    # 按钮点击
    @bot.on(events.CallbackQuery)
    async def callback(event):
        await event.answer("正在处理...", alert=False)
        cmd = event.data.decode()

        # ✅ 同样去掉命令中的 @botname
        if "@" in cmd:
            cmd = cmd.split("@")[0]

        if cmd.startswith("price_"):
            symbol = cmd.split("_")[1]
            await handle_price_command(event, symbol)
        else:
            await handle_command(event, cmd)

    print("🤖 机器人已启动，等待群聊消息...")
    await bot.run_until_disconnected()


# ---------- 定时币价 ----------
async def send_price_periodically(bot, chat_id):
    while True:
        try:
            random_key = random.choice(list(crypto_currencies.keys()))
            msg = get_price_msg(crypto_currencies[random_key]["type"])
            await bot.send_message(chat_id, msg, buttons=get_crypto_buttons(), link_preview=False)
        except Exception as e:
            print(f"发送价格失败: {e}")
        await asyncio.sleep(3600)  # 每小时更新


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