import { fail } from '@sveltejs/kit';
import type { Actions, PageServerLoad } from './$types';
import { uploadDocument, deleteDocument, getSignedUrl, isS3Enabled, getActiveDocumentUrl } from '$lib/server/storage';
import { supabaseAdmin } from '$lib/server/supabase';
import { logDocumentAction } from '$lib/server/audit';

export const load: PageServerLoad = async ({ locals, url }) => {
	const folderId = url.searchParams.get('folder');

	// Load folders in current directory
	let foldersQuery = locals.supabase
		.from('document_folders')
		.select(`
			*,
			creator:members!document_folders_created_by_fkey(first_name, last_name)
		`)
		.order('name', { ascending: true });

	if (folderId) {
		foldersQuery = foldersQuery.eq('parent_id', folderId);
	} else {
		foldersQuery = foldersQuery.is('parent_id', null);
	}

	const { data: folders } = await foldersQuery;

	// Load documents in current folder
	let documentsQuery = locals.supabase
		.from('documents')
		.select(`
			*,
			category:document_categories(id, name, display_name, icon),
			uploader:members!documents_uploaded_by_fkey(first_name, last_name)
		`)
		.order('created_at', { ascending: false });

	if (folderId) {
		documentsQuery = documentsQuery.eq('folder_id', folderId);
	} else {
		documentsQuery = documentsQuery.is('folder_id', null);
	}

	const { data: documents } = await documentsQuery;

	// Load current folder details for breadcrumbs
	let currentFolder = null;
	let breadcrumbs: { id: string | null; name: string }[] = [{ id: null, name: 'Documents' }];

	if (folderId) {
		const { data: folder } = await locals.supabase
			.from('document_folders')
			.select('*')
			.eq('id', folderId)
			.single();

		currentFolder = folder;

		// Build breadcrumb path
		if (folder?.path) {
			const pathParts = folder.path.split('/');
			let currentPath = '';

			// Get all ancestor folders
			for (let i = 0; i < pathParts.length - 1; i++) {
				currentPath = currentPath ? `${currentPath}/${pathParts[i]}` : pathParts[i];
				const { data: ancestorFolder } = await locals.supabase
					.from('document_folders')
					.select('id, name')
					.eq('path', currentPath)
					.single();

				if (ancestorFolder) {
					breadcrumbs.push({ id: ancestorFolder.id, name: ancestorFolder.name });
				}
			}
			breadcrumbs.push({ id: folder.id, name: folder.name });
		}
	}

	// Load categories
	const { data: categories } = await locals.supabase
		.from('document_categories')
		.select('*')
		.eq('is_active', true)
		.order('sort_order', { ascending: true });

	// Resolve active URL for each document based on current storage settings
	const s3Enabled = await isS3Enabled();
	const documentsWithActiveUrl = (documents || []).map((doc: any) => ({
		...doc,
		// Compute active URL based on storage setting
		active_url: s3Enabled
			? (doc.file_url_s3 || doc.file_path)
			: (doc.file_url_local || doc.file_path)
	}));

	return {
		documents: documentsWithActiveUrl,
		folders: folders || [],
		categories: categories || [],
		currentFolder,
		currentFolderId: folderId,
		breadcrumbs
	};
};

export const actions: Actions = {
	createFolder: async ({ request, locals }) => {
		const { member } = await locals.safeGetSession();

		if (!member || (member.role !== 'board' && member.role !== 'admin')) {
			return fail(403, { error: 'You do not have permission to create folders' });
		}

		const formData = await request.formData();
		const name = (formData.get('name') as string)?.trim();
		const parentId = formData.get('parent_id') as string | null;
		const visibility = (formData.get('visibility') as string) || 'members';

		if (!name) {
			return fail(400, { error: 'Folder name is required' });
		}

		// Validate folder name
		if (name.includes('/') || name.includes('\\')) {
			return fail(400, { error: 'Folder name cannot contain slashes' });
		}

		const { error } = await locals.supabase.from('document_folders').insert({
			name,
			parent_id: parentId || null,
			visibility,
			created_by: member.id
		});

		if (error) {
			console.error('Create folder error:', error);
			if (error.code === '23505') {
				return fail(400, { error: 'A folder with this name already exists here' });
			}
			return fail(500, { error: 'Failed to create folder' });
		}

		return { success: 'Folder created!' };
	},

	renameFolder: async ({ request, locals }) => {
		const { member } = await locals.safeGetSession();

		if (!member || (member.role !== 'board' && member.role !== 'admin')) {
			return fail(403, { error: 'You do not have permission to rename folders' });
		}

		const formData = await request.formData();
		const folderId = formData.get('folder_id') as string;
		const name = (formData.get('name') as string)?.trim();

		if (!folderId || !name) {
			return fail(400, { error: 'Folder ID and name are required' });
		}

		if (name.includes('/') || name.includes('\\')) {
			return fail(400, { error: 'Folder name cannot contain slashes' });
		}

		const { error } = await locals.supabase
			.from('document_folders')
			.update({ name })
			.eq('id', folderId);

		if (error) {
			console.error('Rename folder error:', error);
			if (error.code === '23505') {
				return fail(400, { error: 'A folder with this name already exists here' });
			}
			return fail(500, { error: 'Failed to rename folder' });
		}

		return { success: 'Folder renamed!' };
	},

	deleteFolder: async ({ request, locals }) => {
		const { member } = await locals.safeGetSession();

		if (!member || member.role !== 'admin') {
			return fail(403, { error: 'Only admins can delete folders' });
		}

		const formData = await request.formData();
		const folderId = formData.get('folder_id') as string;

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

		// Check if folder has documents
		const { data: docs } = await locals.supabase
			.from('documents')
			.select('id')
			.eq('folder_id', folderId)
			.limit(1);

		if (docs && docs.length > 0) {
			return fail(400, { error: 'Cannot delete folder with documents. Move or delete documents first.' });
		}

		// Check if folder has subfolders
		const { data: subfolders } = await locals.supabase
			.from('document_folders')
			.select('id')
			.eq('parent_id', folderId)
			.limit(1);

		if (subfolders && subfolders.length > 0) {
			return fail(400, { error: 'Cannot delete folder with subfolders. Delete subfolders first.' });
		}

		const { error } = await locals.supabase
			.from('document_folders')
			.delete()
			.eq('id', folderId);

		if (error) {
			console.error('Delete folder error:', error);
			return fail(500, { error: 'Failed to delete folder' });
		}

		return { success: 'Folder deleted!' };
	},

	moveDocument: async ({ request, locals }) => {
		const { member } = await locals.safeGetSession();

		if (!member || (member.role !== 'board' && member.role !== 'admin')) {
			return fail(403, { error: 'You do not have permission to move documents' });
		}

		const formData = await request.formData();
		const documentId = formData.get('document_id') as string;
		const folderId = formData.get('folder_id') as string | null;

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

		const { error } = await locals.supabase
			.from('documents')
			.update({
				folder_id: folderId || null,
				updated_at: new Date().toISOString()
			})
			.eq('id', documentId);

		if (error) {
			console.error('Move document error:', error);
			return fail(500, { error: 'Failed to move document' });
		}

		return { success: 'Document moved!' };
	},

	upload: async ({ request, locals }) => {
		const { member } = await locals.safeGetSession();

		if (!member || (member.role !== 'board' && member.role !== 'admin')) {
			return fail(403, { error: 'You do not have permission to upload documents' });
		}

		const formData = await request.formData();
		const file = formData.get('file') as File;
		const title = formData.get('title') as string;
		const description = formData.get('description') as string;
		const categoryId = formData.get('category_id') as string;
		const visibility = formData.get('visibility') as string;
		const folderId = formData.get('folder_id') as string | null;

		// Validation
		if (!file || !file.size) {
			return fail(400, { error: 'Please select a file to upload' });
		}

		if (!title) {
			return fail(400, { error: 'Title is required' });
		}

		if (title.length > 200) {
			return fail(400, { error: 'Title must be 200 characters or less' });
		}

		// Upload using dual-storage document service (uploads to both S3 and Supabase Storage)
		const uploadResult = await uploadDocument(file);

		if (!uploadResult.success) {
			console.error('Upload error:', uploadResult.error);
			return fail(500, { error: uploadResult.error || 'Failed to upload file. Please try again.' });
		}

		// Create document record with both URLs for storage flexibility
		const { error: insertError } = await locals.supabase.from('documents').insert({
			title,
			description: description || null,
			category_id: categoryId || null,
			folder_id: folderId || null,
			// Primary URL (computed based on active storage setting)
			file_path: uploadResult.publicUrl || uploadResult.path,
			// Dual storage URLs
			file_url_local: uploadResult.localUrl || null,
			file_url_s3: uploadResult.s3Url || null,
			storage_path: uploadResult.path,
			// File metadata
			file_name: file.name,
			file_size: file.size,
			mime_type: file.type,
			visibility: visibility || 'members',
			uploaded_by: member.id
		});

		if (insertError) {
			// Try to clean up uploaded files from both backends
			if (uploadResult.path) {
				await deleteDocument(uploadResult.path);
			}
			console.error('Insert error:', insertError);
			return fail(500, { error: 'Failed to save document. Please try again.' });
		}

		return { success: 'Document uploaded successfully!' };
	},

	delete: async ({ request, locals }) => {
		const { member } = await locals.safeGetSession();

		if (!member || member.role !== 'admin') {
			return fail(403, { error: 'Only admins can delete documents' });
		}

		const formData = await request.formData();
		const documentId = formData.get('document_id') as string;

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

		// Get document to find storage path
		const { data: doc } = await locals.supabase
			.from('documents')
			.select('storage_path, file_path')
			.eq('id', documentId)
			.single();

		// Delete from database
		const { error: deleteError } = await locals.supabase
			.from('documents')
			.delete()
			.eq('id', documentId);

		if (deleteError) {
			console.error('Delete error:', deleteError);
			return fail(500, { error: 'Failed to delete document' });
		}

		logDocumentAction('delete',
			{ id: member.id, email: member.email! },
			{ id: documentId, title: doc?.storage_path || documentId },
			{ storage_path: doc?.storage_path }
		);

		// Delete from ALL storage backends (both S3 and Supabase Storage)
		if (doc?.storage_path) {
			// Use the storage_path directly
			await deleteDocument(doc.storage_path);
		} else if (doc?.file_path) {
			// Fallback for older documents without storage_path
			try {
				let storagePath = doc.file_path;

				// If it's a URL, extract the path
				if (doc.file_path.startsWith('http')) {
					const url = new URL(doc.file_path);
					// Handle Supabase storage URL format
					const supabaseMatch = url.pathname.match(/\/storage\/v1\/object\/public\/documents\/(.+)/);
					if (supabaseMatch) {
						storagePath = supabaseMatch[1];
					} else {
						// Handle S3 URL format
						const s3Match = url.pathname.match(/\/documents\/(.+)/);
						if (s3Match) {
							storagePath = s3Match[1];
						}
					}
				}

				await deleteDocument(storagePath);
			} catch (e) {
				console.error('Failed to delete file from storage:', e);
			}
		}

		return { success: 'Document deleted successfully!' };
	},

	updateVisibility: async ({ request, locals }) => {
		const { member } = await locals.safeGetSession();

		if (!member || (member.role !== 'board' && member.role !== 'admin')) {
			return fail(403, { error: 'You do not have permission to update documents' });
		}

		const formData = await request.formData();
		const documentId = formData.get('document_id') as string;
		const visibility = formData.get('visibility') as string;

		if (!documentId || !visibility) {
			return fail(400, { error: 'Document ID and visibility are required' });
		}

		const { error: updateError } = await locals.supabase
			.from('documents')
			.update({
				visibility,
				updated_at: new Date().toISOString()
			})
			.eq('id', documentId);

		if (updateError) {
			console.error('Update error:', updateError);
			return fail(500, { error: 'Failed to update document' });
		}

		logDocumentAction('visibility_change',
			{ id: member.id, email: member.email! },
			{ id: documentId },
			{ new_visibility: visibility }
		);

		return { success: 'Visibility updated!' };
	},

	getPreviewUrl: async ({ request, locals }) => {
		const { member } = await locals.safeGetSession();

		if (!member) {
			return fail(401, { error: 'Not authenticated' });
		}

		const formData = await request.formData();
		const documentId = formData.get('document_id') as string;

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

		// Get document with all URL columns
		const { data: doc } = await locals.supabase
			.from('documents')
			.select('*')
			.eq('id', documentId)
			.single();

		if (!doc) {
			return fail(404, { error: 'Document not found' });
		}

		// Check visibility permissions
		const canAccess =
			doc.visibility === 'public' ||
			(doc.visibility === 'members') ||
			(doc.visibility === 'board' && ['board', 'admin'].includes(member.role)) ||
			(doc.visibility === 'admin' && member.role === 'admin');

		if (!canAccess) {
			return fail(403, { error: 'You do not have permission to view this document' });
		}

		// Get the active URL based on current storage settings
		const activeUrl = await getActiveDocumentUrl({
			file_url_s3: doc.file_url_s3,
			file_url_local: doc.file_url_local,
			file_path: doc.file_path
		});

		// If we have a public URL, return it
		if (activeUrl && activeUrl.startsWith('http')) {
			return { previewUrl: activeUrl };
		}

		// Generate signed URL for private storage using storage_path or file_path
		const storagePath = doc.storage_path || doc.file_path;
		const { url, error } = await getSignedUrl('documents', storagePath, 3600);

		if (error || !url) {
			return fail(500, { error: 'Failed to generate preview URL' });
		}

		return { previewUrl: url };
	}
};
