import { GlobalFonts, createCanvas, loadImage } from '@napi-rs/canvas';
import { levelingService } from '@shared/modules/leveling/leveling.service';
import path from 'path';

// Register Fonts
const fontDir = path.join(process.cwd(), 'bot', 'assets', 'fonts');
GlobalFonts.registerFromPath(path.join(fontDir, 'IBMPlexSansCondensed-SemiBold.ttf'), 'IBMPlexSansCondensed-SemiBold');
GlobalFonts.registerFromPath(path.join(fontDir, 'IBMPlexMono-Bold.ttf'), 'IBMPlexMono-Bold');

interface StudentCardData {
    username: string;
    avatarUrl: string;
    id: string;
    level: number;
    au: bigint; // Astral Units
    xp: bigint;
    className?: string | null;
}

export async function generateStudentIdCard(data: StudentCardData): Promise<Buffer> {
    const templatePath = path.join(process.cwd(), 'bot', 'assets', 'graphics', 'studentID', 'template.png');
    const classTemplatePath = path.join(process.cwd(), 'bot', 'assets', 'graphics', 'studentID', `Constellation-${data.className}.png`);

    const template = await loadImage(templatePath);
    const classTemplate = await loadImage(classTemplatePath);

    const canvas = createCanvas(template.width, template.height);
    const ctx = canvas.getContext('2d');

    // Draw Background Gradient with random hue
    const gradient = ctx.createLinearGradient(0, 0, canvas.width, canvas.height);
    const saturation = 40 + Math.random() * 20; // 40-60%
    const lightness = 20 + Math.random() * 20; // 20-40%
    const color2 = `hsl(${Math.random() * 360}, ${saturation}%, ${lightness}%)`;
    const color = `hsl(${Math.random() * 360}, ${saturation}%, ${lightness - 20}%)`;

    gradient.addColorStop(0, color);
    gradient.addColorStop(1, color2);

    ctx.fillStyle = gradient;
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    // Draw Template
    ctx.drawImage(template, 0, 0);

    // Draw Class Template
    ctx.drawImage(classTemplate, 0, 0);

    // Draw Avatar
    const avatarSize = 140;
    const avatarX = 19;
    const avatarY = 76;

    try {
        const avatar = await loadImage(data.avatarUrl);
        ctx.save();
        ctx.beginPath();
        // Square avatar
        ctx.rect(avatarX, avatarY, avatarSize, avatarSize);
        ctx.clip();
        ctx.drawImage(avatar, avatarX, avatarY, avatarSize, avatarSize);
        ctx.restore();
    } catch (e) {
        console.error("Failed to load avatar", e);
    }

    // Draw ID
    ctx.save();
    ctx.font = '12px IBMPlexMono-Bold';
    ctx.fillStyle = '#DAC7A1';
    ctx.textAlign = 'left';
    ctx.fillText(`ID: ${data.id}`, 314, 30);
    ctx.restore();

    // Draw Username
    ctx.save();
    ctx.font = '24px IBMPlexSansCondensed-SemiBold';
    ctx.fillStyle = '#FFFFFF';
    ctx.textAlign = 'left';
    ctx.fillText(data.username, 181, 122);
    ctx.restore();

    // Draw AU
    ctx.save();
    ctx.font = '24px IBMPlexMono-Bold';
    ctx.fillStyle = '#FFFFFF';
    ctx.textAlign = 'right';
    ctx.fillText(`${data.au}`, 270, 183);
    ctx.restore();

    // Draw Level
    ctx.save();
    ctx.font = '24px IBMPlexMono-Bold';
    ctx.fillStyle = '#FFFFFF';
    ctx.textAlign = 'center';
    ctx.fillText(`${data.level}`, 445, 255);
    ctx.restore();

    // Draw XP Bar
    const xpForThisLevel = levelingService.getXpForNextLevel(data.level); // The total size of the current level bucket
    const xpAtStartOfLevel = levelingService.getXpToReachLevel(data.level); // The accumulated XP when this level started
    const currentLevelProgress = Number(data.xp) - xpAtStartOfLevel; // How much XP into this level

    const xpBarMaxWidth = 382;
    const xpBarWidth = Math.max(0, Math.min(xpBarMaxWidth, xpBarMaxWidth * currentLevelProgress / xpForThisLevel));
    const xpBarHeight = 3;
    ctx.save();
    ctx.fillStyle = '#B3AD93';
    ctx.fillRect(32, 244, xpBarWidth, xpBarHeight);
    ctx.restore();

    return canvas.toBuffer('image/png');
}
