import aiohttp
import asyncio
import time
import random
import math
import json
from datetime import datetime
from colorama import Fore, Style, init

# Inicializar colorama
init(autoreset=True)

class Bot:
    def __init__(self, token, prefix):
        self.token = token
        self.prefix = prefix
        self.commands = {}
        self.event_handlers = {}
        self.session = None
        self.ws = None
        self.variables = {}
        self.db = {}  # Base de datos simple en memoria
        self.eco = {}  # Economía de usuarios
        self.levels = {}  # Sistema de niveles

    def command(self, name, code):
        """Registra un comando."""
        self.commands[name] = code

    def on_event(self, event_name, code):
        """Registra un manejador de eventos."""
        self.event_handlers[event_name] = code

    async def connect(self):
        """Conecta el bot a Discord."""
        self.session = aiohttp.ClientSession()
        self.ws = await self.session.ws_connect('wss://gateway.discord.gg/?v=9&encoding=json')
        await self.identify()

    async def identify(self):
        """Envía el payload de identificación a Discord."""
        payload = {
            'op': 2,
            'd': {
                'token': self.token,
                'properties': {
                    '$os': 'linux',
                    '$browser': 'renacord',
                    '$device': 'renacord'
                }
            }
        }
        await self.ws.send_json(payload)

    async def event_loop(self):
        """Maneja los eventos de Discord."""
        async for msg in self.ws:
            if msg.type == aiohttp.WSMsgType.TEXT:
                data = msg.json()
                if data['op'] == 0:  # Dispatch event
                    event_type = data['t']
                    event_data = data['d']
                    if event_type in self.event_handlers:
                        await self.execute_code(self.event_handlers[event_type], event_data)
                    if event_type == 'MESSAGE_CREATE':
                        await self.handle_message(event_data)
                    elif event_type == 'GUILD_MEMBER_ADD':
                        await self.handle_member_join(event_data)
                    elif event_type == 'MESSAGE_DELETE':
                        await self.handle_message_delete(event_data)

    async def handle_message(self, message):
        """Procesa los mensajes y ejecuta comandos."""
        content = message['content']
        if content.startswith(self.prefix):
            command_name = content[len(self.prefix):].split()[0]
            if command_name in self.commands:
                code = self.commands[command_name]
                code = self.replace_variables(code, message)
                await self.execute_code(code, message)

    def replace_variables(self, code, message):
        """Reemplaza variables en el código."""
        if "$pingms" in code:
            latency = int(self.ws.latency * 1000)  # Latencia en ms
            code = code.replace("$pingms", str(latency))
        if "$author" in code:
            code = code.replace("$author", message['author']['username'])
        if "$channel" in code:
            code = code.replace("$channel", message['channel_id'])
        if "$guild" in code:
            code = code.replace("$guild", message['guild_id'])
        return code

    async def execute_code(self, code, message):
        """Ejecuta el código del comando o evento."""
        lines = code.split('\n')
        for line in lines:
            if line.startswith("$send"):
                await self.send_message(message['channel_id'], line[6:])
            elif line.startswith("$embed"):
                await self.send_embed(message['channel_id'], line[7:])
            elif line.startswith("$math"):
                result = self.execute_math(line[6:])
                await self.send_message(message['channel_id'], str(result))
            elif line.startswith("$if"):
                await self.execute_conditional(line[4:], message)
            elif line.startswith("$add_role"):
                await self.add_role(message['author']['id'], line[10:])
            elif line.startswith("$remove_role"):
                await self.remove_role(message['author']['id'], line[13:])
            elif line.startswith("$create_channel"):
                await self.create_channel(line[16:])
            elif line.startswith("$delete_channel"):
                await self.delete_channel(line[16:])
            elif line.startswith("$react"):
                await self.add_reaction(message['id'], line[7:])
            elif line.startswith("$wait"):
                await asyncio.sleep(int(line[6:]))
            elif line.startswith("$random"):
                await self.send_message(message['channel_id'], str(random.randint(0, 100)))
            elif line.startswith("$ban"):
                await self.ban_user(message['author']['id'], line[5:])
            elif line.startswith("$kick"):
                await self.kick_user(message['author']['id'], line[6:])
            elif line.startswith("$mute"):
                await self.mute_user(message['author']['id'], line[6:])
            elif line.startswith("$unmute"):
                await self.unmute_user(message['author']['id'], line[8:])
            elif line.startswith("$give_money"):
                await self.give_money(message['author']['id'], int(line[12:]))
            elif line.startswith("$take_money"):
                await self.take_money(message['author']['id'], int(line[12:]))
            elif line.startswith("$balance"):
                await self.check_balance(message['author']['id'])
            elif line.startswith("$add_xp"):
                await self.add_xp(message['author']['id'], int(line[8:]))
            elif line.startswith("$level"):
                await self.check_level(message['author']['id'])
            elif line.startswith("$create_ticket"):
                await self.create_ticket(message['author']['id'])
            elif line.startswith("$close_ticket"):
                await self.close_ticket(message['channel_id'])
            elif line.startswith("$log"):
                await self.log_action(line[5:])

    async def send_message(self, channel_id, content):
        """Envía un mensaje a un canal."""
        url = f'https://discord.com/api/v9/channels/{channel_id}/messages'
        headers = {
            'Authorization': f'Bot {self.token}',
            'Content-Type': 'application/json'
        }
        payload = {
            'content': content
        }
        async with self.session.post(url, json=payload, headers=headers) as resp:
            if resp.status != 200:
                print(f"Error al enviar mensaje: {resp.status}")

    async def send_embed(self, channel_id, embed_data):
        """Envía un embed a un canal."""
        url = f'https://discord.com/api/v9/channels/{channel_id}/messages'
        headers = {
            'Authorization': f'Bot {self.token}',
            'Content-Type': 'application/json'
        }
        embed = {
            "title": embed_data.get("title", "Embed Title"),
            "description": embed_data.get("description", "Embed Description"),
            "color": embed_data.get("color", 0x00ff00),
            "fields": embed_data.get("fields", []),
            "footer": embed_data.get("footer", {})
        }
        payload = {
            "embeds": [embed]
        }
        async with self.session.post(url, json=payload, headers=headers) as resp:
            if resp.status != 200:
                print(f"Error al enviar embed: {resp.status}")

    def execute_math(self, expression):
        """Ejecuta una expresión matemática."""
        try:
            return eval(expression)
        except Exception as e:
            return f"Error: {e}"

    async def execute_conditional(self, condition, message):
        """Ejecuta un condicional."""
        if "==" in condition:
            left, right = condition.split("==")
            if left.strip() == right.strip():
                await self.execute_code(condition.split("then")[1], message)

    async def add_role(self, user_id, role_id):
        """Añade un rol a un usuario."""
        url = f'https://discord.com/api/v9/guilds/{message["guild_id"]}/members/{user_id}/roles/{role_id}'
        headers = {
            'Authorization': f'Bot {self.token}'
        }
        async with self.session.put(url, headers=headers) as resp:
            if resp.status != 204:
                print(f"Error al añadir rol: {resp.status}")

    async def remove_role(self, user_id, role_id):
        """Remueve un rol de un usuario."""
        url = f'https://discord.com/api/v9/guilds/{message["guild_id"]}/members/{user_id}/roles/{role_id}'
        headers = {
            'Authorization': f'Bot {self.token}'
        }
        async with self.session.delete(url, headers=headers) as resp:
            if resp.status != 204:
                print(f"Error al remover rol: {resp.status}")

    async def create_channel(self, name):
        """Crea un canal."""
        url = f'https://discord.com/api/v9/guilds/{message["guild_id"]}/channels'
        headers = {
            'Authorization': f'Bot {self.token}',
            'Content-Type': 'application/json'
        }
        payload = {
            "name": name,
            "type": 0  # Tipo de canal (0 = texto)
        }
        async with self.session.post(url, json=payload, headers=headers) as resp:
            if resp.status != 201:
                print(f"Error al crear canal: {resp.status}")

    async def delete_channel(self, channel_id):
        """Elimina un canal."""
        url = f'https://discord.com/api/v9/channels/{channel_id}'
        headers = {
            'Authorization': f'Bot {self.token}'
        }
        async with self.session.delete(url, headers=headers) as resp:
            if resp.status != 200:
                print(f"Error al eliminar canal: {resp.status}")

    async def add_reaction(self, message_id, emoji):
        """Añade una reacción a un mensaje."""
        url = f'https://discord.com/api/v9/channels/{message["channel_id"]}/messages/{message_id}/reactions/{emoji}/@me'
        headers = {
            'Authorization': f'Bot {self.token}'
        }
        async with self.session.put(url, headers=headers) as resp:
            if resp.status != 204:
                print(f"Error al añadir reacción: {resp.status}")

    async def ban_user(self, user_id, reason):
        """Banea a un usuario."""
        url = f'https://discord.com/api/v9/guilds/{message["guild_id"]}/bans/{user_id}'
        headers = {
            'Authorization': f'Bot {self.token}',
            'Content-Type': 'application/json'
        }
        payload = {
            "reason": reason
        }
        async with self.session.put(url, json=payload, headers=headers) as resp:
            if resp.status != 204:
                print(f"Error al banear usuario: {resp.status}")

    async def kick_user(self, user_id, reason):
        """Expulsa a un usuario."""
        url = f'https://discord.com/api/v9/guilds/{message["guild_id"]}/members/{user_id}'
        headers = {
            'Authorization': f'Bot {self.token}',
            'Content-Type': 'application/json'
        }
        payload = {
            "reason": reason
        }
        async with self.session.delete(url, json=payload, headers=headers) as resp:
            if resp.status != 204:
                print(f"Error al expulsar usuario: {resp.status}")

    async def mute_user(self, user_id, reason):
        """Silencia a un usuario."""
        url = f'https://discord.com/api/v9/guilds/{message["guild_id"]}/members/{user_id}'
        headers = {
            'Authorization': f'Bot {self.token}',
            'Content-Type': 'application/json'
        }
        payload = {
            "reason": reason
        }
        async with self.session.patch(url, json=payload, headers=headers) as resp:
            if resp.status != 204:
                print(f"Error al silenciar usuario: {resp.status}")

    async def unmute_user(self, user_id, reason):
        """Desilencia a un usuario."""
        url = f'https://discord.com/api/v9/guilds/{message["guild_id"]}/members/{user_id}'
        headers = {
            'Authorization': f'Bot {self.token}',
            'Content-Type': 'application/json'
        }
        payload = {
            "reason": reason
        }
        async with self.session.patch(url, json=payload, headers=headers) as resp:
            if resp.status != 204:
                print(f"Error al desilenciar usuario: {resp.status}")

    async def give_money(self, user_id, amount):
        """Da dinero a un usuario."""
        if user_id not in self.eco:
            self.eco[user_id] = 0
        self.eco[user_id] += amount
        await self.send_message(message['channel_id'], f"Se dieron {amount} monedas a {message['author']['username']}.")

    async def take_money(self, user_id, amount):
        """Quita dinero a un usuario."""
        if user_id not in self.eco:
            self.eco[user_id] = 0
        self.eco[user_id] -= amount
        await self.send_message(message['channel_id'], f"Se quitaron {amount} monedas a {message['author']['username']}.")

    async def check_balance(self, user_id):
        """Muestra el balance de un usuario."""
        if user_id not in self.eco:
            self.eco[user_id] = 0
        await self.send_message(message['channel_id'], f"El balance de {message['author']['username']} es {self.eco[user_id]} monedas.")

    async def add_xp(self, user_id, amount):
        """Añade XP a un usuario."""
        if user_id not in self.levels:
            self.levels[user_id] = {"xp": 0, "level": 1}
        self.levels[user_id]["xp"] += amount
        if self.levels[user_id]["xp"] >= self.levels[user_id]["level"] * 100:
            self.levels[user_id]["level"] += 1
            self.levels[user_id]["xp"] = 0
            await self.send_message(message['channel_id'], f"¡{message['author']['username']} ha subido al nivel {self.levels[user_id]['level']}!")

    async def check_level(self, user_id):
        """Muestra el nivel de un usuario."""
        if user_id not in self.levels:
            self.levels[user_id] = {"xp": 0, "level": 1}
        await self.send_message(message['channel_id'], f"{message['author']['username']} está en el nivel {self.levels[user_id]['level']} con {self.levels[user_id]['xp']} XP.")

    async def create_ticket(self, user_id):
        """Crea un ticket."""
        ticket_channel = await self.create_channel(f"ticket-{message['author']['username']}")
        await self.send_message(ticket_channel, f"Ticket creado por {message['author']['username']}.")

    async def close_ticket(self, channel_id):
        """Cierra un ticket."""
        await self.delete_channel(channel_id)

    async def log_action(self, action):
        """Registra una acción en los logs."""
        print(f"[LOG] {action}")

    async def run(self):
        """Inicia el bot."""
        # Mostrar el nombre Renacord en degradado
        print(Fore.CYAN + Style.BRIGHT + """
      ██████╗ ███████╗███╗   ██╗ █████╗  ██████╗ ██████╗ ██████╗ ██████╗ 
      ██╔══██╗██╔════╝████╗  ██║██╔══██╗██╔════╝██╔═══██╗██╔══██╗██╔══██╗
      ██████╔╝█████╗  ██╔██╗ ██║███████║██║     ██║   ██║██████╔╝██║  ██║
      ██╔══██╗██╔══╝  ██║╚██╗██║██╔══██║██║     ██║   ██║██╔══██╗██║  ██║
      ██║  ██║███████╗██║ ╚████║██║  ██║╚██████╗╚██████╔╝██║  ██║██████╔╝
      ╚═╝  ╚═╝╚══════╝╚═╝  ╚═══╝╚═╝  ╚═╝ ╚═════╝ ╚═════╝ ╚═╝  ╚═╝╚═════╝ 
        """ + Style.RESET_ALL)

        # Mostrar el ID de la sesión
        session_id = random.randint(100000, 999999)
        print(Fore.WHITE + f"ID de sesión: {session_id}")

        # Conectar el bot
        try:
            await self.connect()
            print(Fore.GREEN + "✅ Sesión iniciada correctamente." + Style.RESET_ALL)
            await self.event_loop()
        except Exception as e:
            print(Fore.RED + f"❌ Error al iniciar sesión: {e}" + Style.RESET_ALL)

# Ejemplo de uso
bot = Bot(token="TU_TOKEN_AQUÍ", prefix="$")
asyncio.run(bot.run())