import click
import requests


def make_invite(client_id: str | int) -> str:
    permissions = 2048 + 16 + 1024  # = 3088

    invite_url = f"https://discord.com/oauth2/authorize?client_id={str(client_id)}&scope=bot&permissions={permissions}"
    return invite_url


@click.command()
@click.option("--bot-token", type=str, required=True)
def generate_bot_invite_url(bot_token: str):
    """
    Generate the Discord bot invitation URL.

    Returns:
        URL that user can click to add bot to their server
    """
    # Get bot's client ID from the token (it's the first part before the first dot)
    # But safer to get it from the API
    try:
        headers = {"Authorization": f"Bot {bot_token}"}
        response = requests.get(
            "https://discord.com/api/v10/users/@me", headers=headers
        )
        response.raise_for_status()
        bot_info = response.json()
        client_id = bot_info["id"]
    except Exception as e:
        raise ValueError(f"Could not get bot info: {e}")

    invite_url = make_invite(client_id)
    click.echo(f"Bot invite URL: {invite_url}")


@click.command()
def create_channels():
    """Create Discord channels using the configured servers."""
    from memory.common.discord import load_servers

    click.echo("Loading Discord servers and creating channels...")
    load_servers()
    click.echo("Discord channels setup completed.")


@click.command()
@click.option("--bot-token", type=str, required=True, help="Discord bot token")
def add_bot_user(bot_token: str):
    """Add a Discord bot user to the system by fetching bot info from Discord API."""
    from memory.common.db.connection import make_session
    from memory.common.db.models import DiscordUser, DiscordServer, DiscordBotUser

    # Fetch bot information from Discord API
    try:
        headers = {"Authorization": f"Bot {bot_token}"}
        response = requests.get(
            "https://discord.com/api/v10/users/@me", headers=headers
        )
        response.raise_for_status()
        bot_info = response.json()

        discord_id = int(bot_info["id"])
        username = bot_info["username"]
        display_name = bot_info.get("global_name")
        discriminator = bot_info.get("discriminator", "0")

        # Use discriminator if it's not "0" (new username system uses "0")
        if discriminator != "0":
            username = f"{username}#{discriminator}"

    except Exception as e:
        click.echo(f"Error: Could not fetch bot info from Discord API: {e}")
        return

    # Create email and name from Discord info
    email = f"{username.replace('#', '_')}@discord.bot"
    name = display_name or username

    with make_session() as session:
        # Get or create DiscordUser
        discord_user = (
            session.query(DiscordUser).filter(DiscordUser.id == discord_id).first()
        )
        if discord_user:
            click.echo(f"Found existing Discord user: {discord_user.username}")
            # Update username and display_name in case they changed
            discord_user.username = username
            discord_user.display_name = display_name
        else:
            discord_user = DiscordUser(
                id=discord_id,
                username=username,
                display_name=display_name,
            )
            session.add(discord_user)
            click.echo(f"Created new Discord user: {username}")

        # Get or create DiscordBotUser (search by api_key)
        bot_user = (
            session.query(DiscordBotUser)
            .filter(DiscordBotUser.api_key == bot_token)
            .first()
        )
        if bot_user:
            click.echo(f"Found existing bot user: {bot_user.name}")
            # Update email and name in case they changed
            bot_user.email = email
            bot_user.name = name
            # Ensure they're connected
            if discord_user not in bot_user.discord_users:
                bot_user.discord_users.append(discord_user)
                click.echo("Linked Discord user to bot user")
        else:
            bot_user = DiscordBotUser.create_with_api_key(
                discord_users=[discord_user],
                name=name,
                email=email,
                api_key=bot_token,
            )
            session.add(bot_user)
            click.echo(f"Created new bot user: {name}")
            click.echo("Linked Discord user to bot user")

        session.commit()

        click.echo("\n✓ Successfully configured Discord bot user:")
        click.echo(f"  Bot Name: {bot_user.name}")
        click.echo(f"  Bot Email: {bot_user.email}")
        click.echo(f"  API Key: {bot_user.api_key}")
        click.echo(f"  Discord ID: {discord_user.id}")
        click.echo(f"  Discord Username: {discord_user.username}")
        if display_name:
            click.echo(f"  Discord Display Name: {display_name}")

    click.echo("\n\nTo add the bot to your server, click the link below:")
    click.echo(f"Bot invite URL: {make_invite(discord_id)}")


@click.group()
def cli():
    """Discord setup utilities."""
    pass


cli.add_command(generate_bot_invite_url, name="generate-invite")
cli.add_command(create_channels, name="create-channels")
cli.add_command(add_bot_user, name="add-bot-user")


if __name__ == "__main__":
    cli()
