import { auth } from '$lib/auth';
import { uploadProfilePicture } from '$lib/server/s3';
import { error, json } from '@sveltejs/kit';
import { db } from '$lib/server/db';
import { user } from '$lib/server/db/schema';
import { eq } from 'drizzle-orm';
import { MAX_FILE_SIZE } from '$lib/data/constants';
import { isNameAppropriate } from '$lib/server/moderation';

async function validateInputs(name: string, bio: string, username: string, avatarFile: File | null) {
    if (!name || !name.trim()) {
        throw error(400, 'Display name is required');
    }

    const trimmedName = name.trim();
    if (trimmedName.length < 2) {
        throw error(400, 'Display name must be at least 2 characters');
    }

    if (trimmedName.length > 50) {
        throw error(400, 'Display name must be 50 characters or less');
    }

    if (!(await isNameAppropriate(trimmedName))) {
        throw error(400, 'Name contains inappropriate content');
    }

    if (bio && bio.length > 160) {
        throw error(400, 'Bio must be 160 characters or less');
    }

    if (username && (username.length < 3 || username.length > 30)) {
        throw error(400, 'Username must be between 3 and 30 characters');
    }

    if (username) {
        const alphanumericRegex = /^[a-z0-9_]+$/;
        if (!alphanumericRegex.test(username)) {
            throw error(400, 'Username must contain only lowercase letters, numbers, and underscores');
        }

        const purelyNumericRegex = /^\d+$/;
        if (purelyNumericRegex.test(username)) {
            throw error(400, 'Username cannot be purely numeric');
        }
    }

    if (username && !(await isNameAppropriate(username))) {
        throw error(400, 'Username contains inappropriate content');
    }

    if (bio && !(await isNameAppropriate(bio))) {
        throw error(400, 'Bio contains inappropriate content');
    }

    if (avatarFile && avatarFile.size > MAX_FILE_SIZE) {
        throw error(400, 'Avatar file must be smaller than 1MB');
    }
}

export async function POST({ request }) {
    const session = await auth.api.getSession({
        headers: request.headers
    });

    if (!session?.user) {
        throw error(401, 'Not authenticated');
    }

    const formData = await request.formData();

    let name = (formData.get('name') as string)?.trim();
    const bio = formData.get('bio') as string;
    const username = (formData.get('username') as string)?.toLowerCase().trim();
    const avatarFile = formData.get('avatar') as File | null;

    name = name?.trim().replace(/\s+/g, ' ');

    await validateInputs(name, bio, username, avatarFile);

    const updates: Record<string, any> = {
        name,
        bio,
        username,
        updatedAt: new Date()
    };

    if (avatarFile && avatarFile.size > 0) {
        try {
            const arrayBuffer = await avatarFile.arrayBuffer();
            const key = await uploadProfilePicture(
                session.user.id,
                new Uint8Array(arrayBuffer),
                avatarFile.type
            );
            updates.image = key;
        } catch (e) {
            console.error('Avatar upload failed, continuing without update:', e);
        }
    }

    await db.update(user)
        .set(updates)
        .where(eq(user.id, Number(session.user.id)));

    return json({ success: true });
}
