import discord
from discord.ext import commands
from PIL import Image, ImageDraw, ImageFont, ImageOps
import io
import os
from dotenv import load_dotenv
import requests
from random import randint

# Bot setup
load_dotenv()

TOKEN = os.getenv("TOKEN")
intents = discord.Intents.all()

bot = commands.Bot(command_prefix="!?", intents=intents)

# Simple user data structure
user_data = {}


def get_user_data(user_id):
    """Get or initialize user data."""
    if user_id not in user_data:
        user_data[user_id] = {"xp": 0, "level": 53}
    return user_data[user_id]


import io
from PIL import Image, ImageDraw, ImageFont


async def create_profile_card(user, background_image_path):
    """
    Create a profile card image for a user with a custom background and text overlay.

    Args:
        user (discord.Member): The user whose profile card is being generated.
        background_image_path (str): Path to the background image.

    Returns:
        io.BytesIO: A BytesIO object containing the profile card image.
    """
    # Profile card dimensions
    card_width, card_height = 400, 200
    text_color = (255, 255, 255)
    progress_bar_color = (0, 255, 0)
    outline_color = (255, 255, 255)
    tint_color = (50, 50, 50)
    transparency = 25
    opacity = int(255 * transparency / 100)

    # Load and resize the background image
    background_image = Image.open(background_image_path).resize((card_width, card_height))

    # Create a new image with the background
    card_image = Image.new("RGBA", (card_width, card_height))
    card_image.paste(background_image, (0, 0))

    # Create a semi-transparent overlay
    overlay = Image.new("RGBA", card_image.size, tint_color + (opacity,))
    card_image = Image.alpha_composite(card_image, overlay)

    draw = ImageDraw.Draw(card_image)

    # Load fonts
    font_path = "arial.ttf"
    font = ImageFont.truetype(font_path, 20)

    # Draw user info
    draw.text((10, 10), f"User: {user.display_name}", fill=text_color, font=font)
    user_info = get_user_data(user.id)
    draw.text((10, 40), f"Level: {user_info['level']}", fill=text_color, font=font)
    draw.text((10, 70), f"XP: {user_info['xp']}/{user_info['level'] * 100}", fill=text_color, font=font)

    # Draw the progress bar
    max_xp = user_info['level'] * 100
    progress_ratio = user_info['xp'] / max_xp if max_xp > 0 else 0
    progress_width = int(progress_ratio * 200)

    draw.rectangle([(10, 100), (210, 120)], outline=outline_color, width=2)
    draw.rectangle([(10, 100), (10 + progress_width, 120)], fill=progress_bar_color)

    # Draw the user's profile picture
    try:
        profile_size = 96
        margin = 30
        profile_picture_data = await user.avatar.read()
        profile_image = Image.open(io.BytesIO(profile_picture_data)).resize((profile_size, profile_size))
        card_image.paste(profile_image, (card_width - profile_size - margin, margin), profile_image.convert("RGBA"))
    except Exception as error:
        print(f"Error fetching profile picture: {error}")

    # Save image to a BytesIO object
    image_bytes = io.BytesIO()
    card_image.save(image_bytes, format="PNG")
    image_bytes.seek(0)

    return image_bytes


async def create_balance_card(user, credits, tokens, bucks):
    # Card dimensions
    width, height = 450, 250
    card = Image.new("RGB", (width, height), (255, 255, 255))
    draw = ImageDraw.Draw(card)

    # Gradient Background
    gradient_color_1 = (38, 0, 77)  # Dark purple
    gradient_color_2 = (128, 0, 128)  # Purple
    for y in range(height):
        blend = y / height
        r = int(gradient_color_1[0] * (1 - blend) + gradient_color_2[0] * blend)
        g = int(gradient_color_1[1] * (1 - blend) + gradient_color_2[1] * blend)
        b = int(gradient_color_1[2] * (1 - blend) + gradient_color_2[2] * blend)
        draw.line([(0, y), (width, y)], fill=(r, g, b))

    # Avatar with circular border
    try:
        avatar_bytes = await user.avatar.read()
        avatar = Image.open(io.BytesIO(avatar_bytes)).resize((60, 60))
    except Exception:
        # Fallback: blank avatar
        avatar = Image.new("RGBA", (60, 60), (128, 128, 128, 255))
    mask = Image.new("L", avatar.size, 0)
    ImageDraw.Draw(mask).ellipse((0, 0, 60, 60), fill=255)
    avatar = ImageOps.fit(avatar, mask.size, centering=(0.5, 0.5))
    avatar.putalpha(mask)

    # Draw avatar circle background
    avatar_bg = Image.new("RGBA", (70, 70), (255, 255, 255, 0))
    draw_bg = ImageDraw.Draw(avatar_bg)
    draw_bg.ellipse((0, 0, 70, 70), fill=(255, 255, 255, 100))  # Border color

    card.paste(avatar_bg, (20, height - 110), avatar_bg)
    card.paste(avatar, (25, height - 105), avatar)

    # Fonts
    title_font = ImageFont.load_default()
    balance_font = ImageFont.load_default()

    # Header Text
    draw.text((110, 20), "tatsu.", font=title_font, fill="white")
    draw.text((width - 90, 25), "Member", font=title_font, fill="white")

    # Balance Background Box
    balance_box = (100, 70, width - 20, 200)
    draw.rounded_rectangle(balance_box, radius=15, fill=(255, 255, 255, 50))

    # Balance Items
    icon_x = 120
    text_x = icon_x + 35

    # Credits
    draw.ellipse((icon_x, 90, icon_x + 25, 115), fill=(255, 215, 0))  # Coin icon color
    draw.text((text_x, 90), f"{credits:,} Credits", font=balance_font, fill="black")

    # Tokens
    draw.ellipse(
        (icon_x, 125, icon_x + 25, 150), fill=(0, 255, 127)
    )  # Token icon color
    draw.text((text_x, 125), f"{tokens:,} Tokens", font=balance_font, fill="black")

    # Bucks
    draw.ellipse(
        (icon_x, 160, icon_x + 25, 185), fill=(50, 205, 50)
    )  # Bucks icon color
    draw.text((text_x, 160), f"{bucks:,} Guild Bucks", font=balance_font, fill="black")

    # User tag
    user_tag = f"{user.name}#{user.discriminator}"
    draw.text((110, height - 35), user_tag, font=title_font, fill="white")

    # Add Chip (Credit Card Style)
    chip_width, chip_height = 50, 35
    chip_x = width - 80
    chip_y = 100
    draw.rectangle(
        [chip_x, chip_y, chip_x + chip_width, chip_y + chip_height],
        fill=(192, 192, 192),  # Light gray color for the chip
        outline="white",
        width=2,
    )

    # Chip lines for texture
    line_spacing = 7
    for i in range(1, chip_height // line_spacing):
        y = chip_y + i * line_spacing
        draw.line(
            [(chip_x + 5, y), (chip_x + chip_width - 5, y)], fill="white", width=1
        )

    # Save to a BytesIO object to send on Discord
    with io.BytesIO() as image_binary:
        card.save(image_binary, "PNG")
        image_binary.seek(0)
        return discord.File(fp=image_binary, filename="balance_card.png")


@bot.event
async def on_ready():
    if bot.user is not None:
        print(f"Logged in as {bot.user.name}")
    else:
        print(f"Logged in")


@bot.command(name="profile")
async def profile(ctx):
    """Command to display user profile."""
    user = ctx.author
    user_info = get_user_data(user.id)

    # Create profile card image
    profile_image = create_profile_card(user, f"images/image_{randint(1,100)}.jpg")

    # Send the image in the channel
    await ctx.send(file=discord.File(await profile_image, "profile.png"))


@bot.command()
async def balance(ctx):
    user = ctx.author
    # Example balance data; replace with actual data retrieval

    credits = 9493006
    tokens = 58
    bucks = 234328

    file = await create_balance_card(user, credits, tokens, bucks)
    await ctx.send(file=file)


# Example command to add XP for testing
@bot.command(name="addxp")
async def add_xp(ctx, amount: int):
    """Command to add XP for testing."""
    user_info = get_user_data(ctx.author.id)
    user_info["xp"] += amount

    # Level up logic (example: every 100 XP earns a level)
    if user_info["xp"] >= user_info["level"] * 100:
        user_info["level"] += 1
        user_info["xp"] = 0  # Reset XP after leveling up

    await ctx.send(
        f"Added {amount} XP to {ctx.author.mention}. Total XP: {user_info['xp']} | Level: {user_info['level']}"
    )


if TOKEN is not None:
    bot.run(TOKEN)
else:
    print(f"{TOKEN=}")
