import { json } from '@sveltejs/kit';
import { putContainerArchive } from '$lib/server/docker';
import { authorize } from '$lib/server/authorize';
import type { RequestHandler } from './$types';

/**
 * Create a simple tar archive from a single file
 * TAR format: 512-byte header followed by file content padded to 512 bytes
 */
function createTarArchive(filename: string, content: Uint8Array): Uint8Array {
	// TAR header is 512 bytes
	const header = new Uint8Array(512);
	const encoder = new TextEncoder();

	// File name (100 bytes)
	const nameBytes = encoder.encode(filename.slice(0, 99));
	header.set(nameBytes, 0);

	// File mode (8 bytes) - 0644
	header.set(encoder.encode('0000644\0'), 100);

	// Owner UID (8 bytes)
	header.set(encoder.encode('0000000\0'), 108);

	// Owner GID (8 bytes)
	header.set(encoder.encode('0000000\0'), 116);

	// File size in octal (12 bytes)
	const sizeOctal = content.length.toString(8).padStart(11, '0');
	header.set(encoder.encode(sizeOctal + '\0'), 124);

	// Modification time (12 bytes) - current time in octal
	const mtime = Math.floor(Date.now() / 1000).toString(8).padStart(11, '0');
	header.set(encoder.encode(mtime + '\0'), 136);

	// Checksum placeholder (8 spaces initially)
	header.set(encoder.encode('        '), 148);

	// Type flag - '0' for regular file
	header[156] = 48; // '0'

	// Link name (100 bytes) - empty
	// Magic (6 bytes) - 'ustar\0'
	header.set(encoder.encode('ustar\0'), 257);

	// Version (2 bytes) - '00'
	header.set(encoder.encode('00'), 263);

	// Owner name (32 bytes)
	header.set(encoder.encode('root'), 265);

	// Group name (32 bytes)
	header.set(encoder.encode('root'), 297);

	// Calculate checksum
	let checksum = 0;
	for (let i = 0; i < 512; i++) {
		checksum += header[i];
	}
	const checksumOctal = checksum.toString(8).padStart(6, '0') + '\0 ';
	header.set(encoder.encode(checksumOctal), 148);

	// Calculate padding to 512-byte boundary
	const paddingSize = (512 - (content.length % 512)) % 512;
	const padding = new Uint8Array(paddingSize);

	// End of archive marker (two 512-byte zero blocks)
	const endMarker = new Uint8Array(1024);

	// Combine all parts
	const totalSize = header.length + content.length + paddingSize + endMarker.length;
	const tar = new Uint8Array(totalSize);

	let offset = 0;
	tar.set(header, offset);
	offset += header.length;
	tar.set(content, offset);
	offset += content.length;
	tar.set(padding, offset);
	offset += paddingSize;
	tar.set(endMarker, offset);

	return tar;
}

export const POST: RequestHandler = async ({ params, url, request, cookies }) => {
	const auth = await authorize(cookies);

	const path = url.searchParams.get('path');
	const envId = url.searchParams.get('env');
	const envIdNum = envId ? parseInt(envId) : undefined;

	// Permission check with environment context
	if (auth.authEnabled && !await auth.can('containers', 'exec', envIdNum)) {
		return json({ error: 'Permission denied' }, { status: 403 });
	}

	if (!path) {
		return json({ error: 'Target path is required' }, { status: 400 });
	}

	try {
		const formData = await request.formData();
		const files = formData.getAll('files') as File[];

		if (files.length === 0) {
			return json({ error: 'No files provided' }, { status: 400 });
		}

		// For simplicity, we'll upload files one at a time
		// A more sophisticated implementation could pack multiple files into one tar
		const uploaded: string[] = [];
		const errors: string[] = [];

		for (const file of files) {
			try {
				const content = new Uint8Array(await file.arrayBuffer());
				const tar = createTarArchive(file.name, content);

				await putContainerArchive(
					params.id,
					path,
					tar,
					envId ? parseInt(envId) : undefined
				);

				uploaded.push(file.name);
			} catch (err: any) {
				errors.push(`${file.name}: ${err.message}`);
			}
		}

		if (errors.length > 0 && uploaded.length === 0) {
			return json({ error: 'Failed to upload files', details: errors }, { status: 500 });
		}

		return json({
			success: true,
			uploaded,
			errors: errors.length > 0 ? errors : undefined
		});
	} catch (error: any) {
		console.error('Error uploading to container:', error);

		if (error.message?.includes('Permission denied')) {
			return json({ error: 'Permission denied to write to this path' }, { status: 403 });
		}
		if (error.message?.includes('No such file or directory')) {
			return json({ error: 'Target directory not found' }, { status: 404 });
		}

		return json({ error: 'Failed to upload files' }, { status: 500 });
	}
};
