import discord
from discord import app_commands
from discord.ext import commands
import pymongo
from bson.objectid import ObjectId
import logging
from config import DISCORD_CLIENT_ID, DISCORD_CLIENT_SECRET, DISCORD_REDIRECT_URI, DISCORD_BOT_TOKEN, DISCORD_GUILD_ID, ACCOUNT_LINKED_ROLE_ID, DISCORD_WEBHOOK_URL

# Set up logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s:%(levelname)s:%(name)s: %(message)s')
logger = logging.getLogger('resonance_rumble_bot')


# MongoDB setup
client = pymongo.MongoClient('mongodb://localhost:27017/')
db = client['resonance_rumble']
classes_collection = db['classes']
weapons_collection = db['weapons']
skins_collection = db['skins']
users_collection = db['users']
achievements_collection = db['achievements']


intents = discord.Intents.all()
intents.message_content = True #v2
intents.members = True
bot = commands.Bot(command_prefix='!', intents=intents)

LINKED_ROLE_NAME = "Account-linked"


@bot.event
async def on_ready():
    print(f'{bot.user} has connected to Discord!')
    try:
        synced = await bot.tree.sync()
        print(f"Synced {len(synced)} command(s)")
    except Exception as e:
        print(f"Error syncing commands: {e}")

@bot.event
async def on_member_join(member):
    logger.info(f"New member joined: {member.name} (ID: {member.id})")
    role = discord.utils.get(member.guild.roles, name="Member")
    if role:
        try:
            await member.add_roles(role)
            logger.info(f"Successfully added Member role to {member.name}")
        except discord.Forbidden:
            logger.error(f"Failed to add Member role to {member.name}: Bot doesn't have permission")
        except discord.HTTPException as e:
            logger.error(f"Failed to add Member role to {member.name}: {str(e)}")
    else:
        logger.error(f"'Member' role not found in the server")

async def class_autocomplete(interaction: discord.Interaction, current: str) -> list[app_commands.Choice[str]]:
    classes = classes_collection.find({}, {"name": 1})
    return [
        app_commands.Choice(name=class_doc["name"], value=class_doc["name"])
        for class_doc in classes if current.lower() in class_doc["name"].lower()
    ][:25]  # Discord limits to 25 choices

@bot.tree.command(name="class_info", description="Get information about a game class")
@app_commands.autocomplete(class_name=class_autocomplete)
async def class_info(interaction: discord.Interaction, class_name: str):
    class_data = classes_collection.find_one({"name": class_name})
    if class_data:
        embed = discord.Embed(title=f"{class_name} Class Info", color=0x00ff00)
        embed.add_field(name="Health", value=class_data['base_attributes']['health'], inline=True)
        embed.add_field(name="Speed", value=class_data['base_attributes']['speed'], inline=True)
        embed.add_field(name="Damage Multiplier", value=class_data['base_attributes']['damage_multiplier'], inline=True)
        embed.add_field(name="Weapon Limit", value=class_data['weapon_limit'], inline=True)
        await interaction.response.send_message(embed=embed)
    else:
        await interaction.response.send_message(f"Class '{class_name}' not found.", ephemeral=True)

async def weapon_autocomplete(interaction: discord.Interaction, current: str) -> list[app_commands.Choice[str]]:
    weapons = weapons_collection.find({}, {"name": 1})
    return [
        app_commands.Choice(name=weapon["name"], value=weapon["name"])
        for weapon in weapons if current.lower() in weapon["name"].lower()
    ][:25]

@bot.tree.command(name="weapon_info", description="Get information about a weapon")
@app_commands.autocomplete(weapon_name=weapon_autocomplete)
async def weapon_info(interaction: discord.Interaction, weapon_name: str):
    weapon_data = weapons_collection.find_one({"name": weapon_name})
    if weapon_data:
        embed = discord.Embed(title=f"{weapon_name} Weapon Info", color=0x0000ff)
        embed.add_field(name="Type", value=weapon_data['weapon_type'], inline=True)
        embed.add_field(name="Damage", value=weapon_data['base_attributes']['damage'], inline=True)
        embed.add_field(name="Fire Rate", value=weapon_data['base_attributes']['fire_rate'], inline=True)
        embed.add_field(name="Bullet Speed", value=weapon_data['base_attributes']['bullet_speed'], inline=True)
        await interaction.response.send_message(embed=embed)
    else:
        await interaction.response.send_message(f"Weapon '{weapon_name}' not found.", ephemeral=True)

async def skin_autocomplete(interaction: discord.Interaction, current: str) -> list[app_commands.Choice[str]]:
    skins = skins_collection.find({}, {"name": 1})
    return [
        app_commands.Choice(name=skin["name"], value=skin["name"])
        for skin in skins if current.lower() in skin["name"].lower()
    ][:25]

@bot.tree.command(name="skin_info", description="Get information about a skin")
@app_commands.autocomplete(skin_name=skin_autocomplete)
async def skin_info(interaction: discord.Interaction, skin_name: str):
    skin_data = skins_collection.find_one({"name": skin_name})
    if skin_data:
        embed = discord.Embed(title=f"{skin_name} Skin Info", color=0xff00ff)
        embed.add_field(name="Type", value=skin_data['type'], inline=True)
        embed.add_field(name="Rarity", value=skin_data['rarity'], inline=True)
        embed.add_field(name="Effect", value=skin_data['effect'], inline=True)
        await interaction.response.send_message(embed=embed)
    else:
        await interaction.response.send_message(f"Skin '{skin_name}' not found.", ephemeral=True)

@bot.tree.command(name="leaderboard", description="Show the top players")
@app_commands.describe(category="The category for the leaderboard")
@app_commands.choices(category=[
    app_commands.Choice(name="Level", value="level"),
    app_commands.Choice(name="Synth Coins", value="synth_coins"),
    app_commands.Choice(name="Experience", value="experience")
])
async def leaderboard(interaction: discord.Interaction, category: app_commands.Choice[str]):
    top_players = list(db.users.find().sort(category.value, -1).limit(10))
    
    embed = discord.Embed(title=f"Top 10 Players - {category.name}", color=0xffa500)
    for i, player in enumerate(top_players, 1):
        embed.add_field(name=f"{i}. {player['username']}", value=f"{category.name}: {player.get(category.value, 0)}", inline=False)
    
    await interaction.response.send_message(embed=embed)


@bot.tree.command(name="check_permissions", description="Check bot's permissions")
@commands.has_permissions(administrator=True)
async def check_permissions(interaction: discord.Interaction):
    bot_member = interaction.guild.get_member(bot.user.id)
    permissions = bot_member.guild_permissions

    embed = discord.Embed(title="Bot Permissions", color=0x00ff00)
    crucial_perms = ["manage_roles", "view_channel", "send_messages", "embed_links"]
    
    for perm, value in permissions:
        if perm in crucial_perms:
            embed.add_field(name=perm.replace('_', ' ').title(), value=str(value), inline=False)

    await interaction.response.send_message(embed=embed)

@bot.tree.command(name="link_status", description="Check your Resonance Rumble account link status")
async def link_status(interaction: discord.Interaction):
    user = users_collection.find_one({'discord_id': str(interaction.user.id)})
    if user:
        await add_linked_role(interaction.user)
        await interaction.response.send_message(f"Your Discord account is linked to the Resonance Rumble account: {user['username']}")
    else:
        await interaction.response.send_message("Your Discord account is not linked to any Resonance Rumble account. Use the in-game menu to link your account.")

async def add_linked_role(member):
    guild = member.guild
    role = discord.utils.get(guild.roles, name=LINKED_ROLE_NAME)
    if role is None:
        # Create the role if it doesn't exist
        role = await guild.create_role(name=LINKED_ROLE_NAME, color=discord.Color.blue())
    
    if role not in member.roles:
        try:
            await member.add_roles(role)
            print(f"Added {LINKED_ROLE_NAME} role to {member.name}")
        except discord.Forbidden:
            print(f"Bot doesn't have permission to add roles to {member.name}")
        except discord.HTTPException as e:
            print(f"Failed to add role to {member.name}: {str(e)}")

# You might want to add a command to manually sync roles
@bot.tree.command(name="sync_linked_role", description="Sync the Account-linked role for all linked users")
@commands.has_permissions(administrator=True)
async def sync_linked_role(interaction: discord.Interaction):
    await interaction.response.defer()
    guild = interaction.guild
    linked_users = users_collection.find({'discord_id': {'$exists': True}})
    count = 0
    for user in linked_users:
        member = guild.get_member(int(user['discord_id']))
        if member:
            await add_linked_role(member)
            count += 1
    await interaction.followup.send(f"Synced roles for {count} linked users.")



bot.run(DISCORD_BOT_TOKEN)