import type { PageServerLoad, Actions } from './$types';
import { fail } from '@sveltejs/kit';
import { entryRepository, imageRepository, tagRepository } from '$lib/server/db/repository';
import {
	saveOriginal,
	saveThumbnail,
	ensureDirectories,
	deleteImage as deleteImageFile
} from '$lib/server/images/storage';
import { generateThumbnail } from '$lib/server/images/thumbnails';

export const load: PageServerLoad = async ({ url }) => {
	const showCompleted = url.searchParams.get('showCompleted') === 'true';
	const entries = entryRepository.getOrdered({ showCompleted });

	// Attach images AND tags to each entry
	const entriesWithData = entries.map((entry) => ({
		...entry,
		images: imageRepository.getByEntryId(entry.id),
		tags: tagRepository.getByEntryId(entry.id)
	}));

	// Get all tags for autocomplete
	const allTags = tagRepository.getAll();

	return {
		entries: entriesWithData,
		allTags,
		showCompleted
	};
};

export const actions: Actions = {
	create: async ({ request }) => {
		const formData = await request.formData();
		const title = formData.get('title')?.toString().trim() || undefined;
		const content = formData.get('content')?.toString().trim() || '';
		const type = formData.get('type')?.toString() as 'task' | 'thought' | undefined;

		// Validate content is not empty
		if (!content) {
			return fail(400, {
				error: 'Content is required',
				title: title || '',
				content: '',
				type: type || 'thought'
			});
		}

		const entry = entryRepository.create({
			title,
			content,
			type: type || 'thought'
		});

		return { success: true, entryId: entry.id };
	},

	update: async ({ request }) => {
		const formData = await request.formData();
		const id = formData.get('id')?.toString();

		if (!id) {
			return fail(400, { error: 'Entry ID is required' });
		}

		const existing = entryRepository.getById(id);
		if (!existing) {
			return fail(404, { error: 'Entry not found' });
		}

		// Collect fields to update
		const updates: Record<string, string | boolean | null> = {};

		const title = formData.get('title');
		if (title !== null) {
			updates.title = title.toString().trim() || null;
		}

		const content = formData.get('content');
		if (content !== null) {
			const contentStr = content.toString().trim();
			if (contentStr === '') {
				return fail(400, { error: 'Content cannot be empty' });
			}
			updates.content = contentStr;
		}

		const type = formData.get('type');
		if (type !== null) {
			const typeStr = type.toString();
			if (typeStr !== 'task' && typeStr !== 'thought') {
				return fail(400, { error: 'Invalid type' });
			}
			updates.type = typeStr;
		}

		const status = formData.get('status');
		if (status !== null) {
			const statusStr = status.toString();
			if (statusStr !== 'open' && statusStr !== 'done' && statusStr !== 'archived') {
				return fail(400, { error: 'Invalid status' });
			}
			updates.status = statusStr;
		}

		entryRepository.update(id, updates);

		return { success: true };
	},

	delete: async ({ request }) => {
		const formData = await request.formData();
		const id = formData.get('id')?.toString();

		if (!id) {
			return fail(400, { error: 'Entry ID is required' });
		}

		const existing = entryRepository.getById(id);
		if (!existing) {
			return fail(404, { error: 'Entry not found' });
		}

		entryRepository.delete(id);

		return { success: true };
	},

	toggleComplete: async ({ request }) => {
		const formData = await request.formData();
		const id = formData.get('id')?.toString();

		if (!id) {
			return fail(400, { error: 'Entry ID is required' });
		}

		const existing = entryRepository.getById(id);
		if (!existing) {
			return fail(404, { error: 'Entry not found' });
		}

		// Toggle status between 'open' and 'done'
		const newStatus = existing.status === 'done' ? 'open' : 'done';
		entryRepository.update(id, { status: newStatus });

		return { success: true };
	},

	uploadImage: async ({ request }) => {
		const formData = await request.formData();
		const file = formData.get('image') as File;
		const entryId = formData.get('entryId') as string;

		if (!file || file.size === 0) {
			return fail(400, { error: 'No file uploaded' });
		}

		if (!entryId) {
			return fail(400, { error: 'Entry ID required' });
		}

		// Verify entry exists
		const entry = entryRepository.getById(entryId);
		if (!entry) {
			return fail(404, { error: 'Entry not found' });
		}

		// Validate image type
		if (!file.type.startsWith('image/')) {
			return fail(400, { error: 'File must be an image' });
		}

		const ext = file.name.split('.').pop()?.toLowerCase() || 'jpg';
		const buffer = Buffer.from(await file.arrayBuffer());

		try {
			await ensureDirectories();

			// Generate and save thumbnail
			const thumbnailBuffer = await generateThumbnail(buffer);

			// Save to database to get ID
			const image = imageRepository.create({
				entryId,
				filename: file.name,
				ext
			});

			// Save original
			await saveOriginal(image.id, ext, buffer);

			// Save thumbnail
			await saveThumbnail(image.id, thumbnailBuffer);

			return { success: true, imageId: image.id };
		} catch (err) {
			console.error('Upload error:', err);
			return fail(500, { error: 'Failed to save image' });
		}
	},

	deleteImage: async ({ request }) => {
		const formData = await request.formData();
		const imageId = formData.get('imageId')?.toString();

		if (!imageId) {
			return fail(400, { error: 'Image ID required' });
		}

		// Get image to find extension for file deletion
		const image = imageRepository.getById(imageId);
		if (!image) {
			return fail(404, { error: 'Image not found' });
		}

		// Delete files from filesystem
		try {
			await deleteImageFile(imageId, image.ext);
		} catch (err) {
			console.error('Failed to delete image files:', err);
			// Continue to delete from database even if files missing
		}

		// Delete from database
		imageRepository.delete(imageId);

		return { success: true };
	},

	togglePin: async ({ request }) => {
		const formData = await request.formData();
		const id = formData.get('id')?.toString();

		if (!id) {
			return fail(400, { error: 'Entry ID is required' });
		}

		const existing = entryRepository.getById(id);
		if (!existing) {
			return fail(404, { error: 'Entry not found' });
		}

		// Toggle pinned state
		entryRepository.update(id, { pinned: !existing.pinned });

		return { success: true };
	},

	updateDueDate: async ({ request }) => {
		const formData = await request.formData();
		const id = formData.get('id')?.toString();
		const dueDate = formData.get('dueDate')?.toString() || null;

		if (!id) {
			return fail(400, { error: 'Entry ID is required' });
		}

		const existing = entryRepository.getById(id);
		if (!existing) {
			return fail(404, { error: 'Entry not found' });
		}

		// Update due date (empty string becomes null)
		entryRepository.update(id, { dueDate: dueDate || null });

		return { success: true };
	},

	updateTags: async ({ request }) => {
		const formData = await request.formData();
		const id = formData.get('id')?.toString();
		const tagsJson = formData.get('tags')?.toString() || '[]';

		if (!id) {
			return fail(400, { error: 'Entry ID is required' });
		}

		const existing = entryRepository.getById(id);
		if (!existing) {
			return fail(404, { error: 'Entry not found' });
		}

		try {
			const tagNames = JSON.parse(tagsJson) as string[];
			tagRepository.updateEntryTags(id, tagNames);
			return { success: true };
		} catch {
			return fail(400, { error: 'Invalid tags format' });
		}
	}
};
