package components

import (
	"context"
	"strconv"
	"fmt"
	"github.com/starfleetcptn/gomft/internal/db"
)

// FileMetadataFilter represents filter parameters for file metadata queries
type FileMetadataFilter struct {
	Status    string
	JobID     string
	FileName  string
	Hash      string
	StartDate string
	EndDate   string
}

// FileMetadataListData contains data for the file metadata list template
type FileMetadataListData struct {
	Files      []db.FileMetadata
	TotalCount int64
	Page       int
	Limit      int
	TotalPages int
	Job        *db.Job // Optional: if viewing files for a specific job
	Filter     FileMetadataFilter
}

// FileMetadataDetailsData contains data for the file metadata details template
type FileMetadataDetailsData struct {
	File db.FileMetadata
}

// FileMetadataSearchData contains data for the file metadata search template
type FileMetadataSearchData struct {
	Files      []db.FileMetadata
	TotalCount int64
	Page       int
	Limit      int
	TotalPages int
	Filter     FileMetadataFilter
}

// getStatusBadgeClass returns the appropriate CSS class for a file status badge
func getStatusBadgeClass(status string) string {
	switch status {
	case "processed":
		return "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300"
	case "archived":
		return "bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300"
	case "deleted":
		return "bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300"
	case "archived_and_deleted":
		return "bg-orange-100 text-orange-800 dark:bg-orange-900 dark:text-orange-300"
	case "error":
		return "bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300"
	default:
		return "bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300"
	}
}

// formatFileSize formats a file size in bytes to a human-readable string
func formatFileSize(size int64) string {
	if size < 1024 {
		return fmt.Sprintf("%d B", size)
	} else if size < 1024*1024 {
		return fmt.Sprintf("%.2f KB", float64(size)/1024)
	} else if size < 1024*1024*1024 {
		return fmt.Sprintf("%.2f MB", float64(size)/(1024*1024))
	} else {
		return fmt.Sprintf("%.2f GB", float64(size)/(1024*1024*1024))
	}
}

// Updated Dialog component using Flowbite
templ FileMetadataDialog(id string, title string, message string, confirmClass string, confirmText string, action string, fileID uint, fileName string, section string) {
	<div id={ id } tabindex="-1" aria-hidden="true" class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full bg-gray-900/50 dark:bg-gray-900/80 backdrop-blur-sm">
		<div class="relative p-4 w-full max-w-md max-h-full mx-auto">
			<div class="relative bg-white rounded-lg shadow dark:bg-gray-700">
				<div class="p-6 text-center">
					if action == "delete" {
						<i class="fas fa-trash-alt text-red-400 text-3xl mb-4"></i>
					} else {
						<i class="fas fa-exclamation-triangle text-yellow-400 text-3xl mb-4"></i>
					}
					<h3 class="mb-5 text-lg font-normal text-gray-500 dark:text-gray-400">{ message }</h3>
					if section == "list" {
						<button 
							type="button" 
							class="text-white font-medium rounded-lg text-sm px-5 py-2.5 text-center me-2 bg-red-600 hover:bg-red-700 focus:ring-4 focus:outline-none focus:ring-red-300 dark:bg-red-500 dark:hover:bg-red-600 dark:focus:ring-red-800"
							hx-delete={ fmt.Sprintf("/files/%d", fileID) }
							hx-target={ fmt.Sprintf("#file-row-%d", fileID) }
							hx-swap="delete"
							data-file-name={ fileName }
							data-file-id={ fmt.Sprint(fileID) }
							id={ fmt.Sprintf("delete-file-btn-%d", fileID) }
							onclick={ triggerFileDelete(id, fileID, fileName) }>
							{ confirmText }
						</button>
					} else {
						<button 
							type="button" 
							class="text-white font-medium rounded-lg text-sm px-5 py-2.5 text-center me-2 bg-red-600 hover:bg-red-700 focus:ring-4 focus:outline-none focus:ring-red-300 dark:bg-red-500 dark:hover:bg-red-600 dark:focus:ring-red-800"
							hx-delete={ fmt.Sprintf("/files/%d", fileID) }
							hx-redirect="/files"
							data-file-name={ fileName }
							data-file-id={ fmt.Sprint(fileID) }
							id={ fmt.Sprintf("delete-file-btn-%d", fileID) }
							onclick={ triggerFileDelete(id, fileID, fileName) }>
							{ confirmText }
						</button>
					}
					<button type="button" data-modal-hide={ id } class="text-gray-500 bg-white hover:bg-gray-100 focus:ring-4 focus:outline-none focus:ring-gray-200 rounded-lg border border-gray-200 text-sm font-medium px-5 py-2.5 hover:text-gray-900 focus:z-10 dark:bg-gray-700 dark:text-gray-300 dark:border-gray-500 dark:hover:text-white dark:hover:bg-gray-600 dark:focus:ring-gray-600">
						Cancel
					</button>
				</div>
			</div>
		</div>
	</div>
}

script hideFileDialog(id string) {
	document.getElementById(id).classList.add("hidden");
	document.getElementById(id).classList.remove("flex");
}

script showFileDialog(id string) {
	document.getElementById(id).classList.remove("hidden");
	document.getElementById(id).classList.add("flex");
}

script triggerFileDelete(dialogId string, fileID uint, fileName string) {
	// Hide the dialog
	document.getElementById(dialogId).classList.add("hidden");
	document.getElementById(dialogId).classList.remove("flex");
		
	// Store data in a way that's accessible to event handlers
	window.lastDeletedFile = {
		id: fileID,
		name: fileName
	};

	// Add custom marker to track this deletion
	window.currentlyDeletingFile = true;
}

// Rename from FileMetadataListContent to FileMetadataListPartial to match what the handler expects
templ FileMetadataListPartial(data FileMetadataListData) {
	<!-- Store file IDs for dialogs -->
	<div id="dialog-container">
		<!-- Dialogs will be rendered at the bottom of the container -->
		for _, file := range data.Files {
			@FileMetadataDialog(
				fmt.Sprintf("delete-file-dialog-%d", file.ID),
				"Delete File Metadata",
				fmt.Sprintf("Are you sure you want to delete the metadata for '%s'? This cannot be undone.", file.FileName),
				"btn-danger",
				"Delete",
				"delete",
				file.ID,
				file.FileName,
				"list",
			)
		}
	</div>

	<div class="relative overflow-x-auto shadow-md sm:rounded-lg">
		<table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
			<thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
				<tr>
					<th scope="col" class="px-6 py-3">ID</th>
					<th scope="col" class="px-6 py-3">Filename</th>
					<th scope="col" class="px-6 py-3">Size</th>
					<th scope="col" class="px-6 py-3">Processed</th>
					<th scope="col" class="px-6 py-3">Status</th>
					if data.Job == nil {
						<th scope="col" class="px-6 py-3">Job</th>
					}
					<th scope="col" class="px-6 py-3">Actions</th>
				</tr>
			</thead>
			<tbody>
				for _, file := range data.Files {
					<tr id={ fmt.Sprintf("file-row-%d", file.ID) } class="bg-white border-b dark:bg-gray-800 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600">
						<td class="px-6 py-4">{ strconv.FormatUint(uint64(file.ID), 10) }</td>
						<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white">
							<a href={ templ.SafeURL(fmt.Sprintf("/files/%d", file.ID)) } class="hover:underline">
								{ file.FileName }
							</a>
						</td>
						<td class="px-6 py-4">{ formatFileSize(file.FileSize) }</td>
						<td class="px-6 py-4">{ file.ProcessedTime.Format("2006-01-02 15:04:05") }</td>
						<td class="px-6 py-4">
							<span class={ "text-xs font-medium me-2 px-2.5 py-0.5 rounded", getStatusBadgeClass(file.Status) }>
								{ file.Status }
							</span>
						</td>
						if data.Job == nil && file.Job.ID > 0 {
							<td class="px-6 py-4">
								<a href={ templ.SafeURL(fmt.Sprintf("/files/job/%d", file.Job.ID)) } class="font-medium text-blue-600 dark:text-blue-500 hover:underline">
									{ file.Job.Name }
								</a>
							</td>
						}
						<td class="px-6 py-4">
							<div class="flex space-x-3">
								<a href={ templ.SafeURL(fmt.Sprintf("/files/%d", file.ID)) } class="font-medium text-blue-600 dark:text-blue-500 hover:underline">
									<i class="fas fa-eye"></i>
								</a>
								<button 
									type="button"
									onclick={ showFileDialog(fmt.Sprintf("delete-file-dialog-%d", file.ID)) }
									class="font-medium text-red-600 dark:text-red-500 hover:underline">
									<i class="fas fa-trash"></i>
								</button>
							</div>
						</td>
					</tr>
				}
			</tbody>
		</table>
		
		<!-- Flowbite Pagination -->
		if data.TotalPages > 1 {
			<nav class="flex items-center flex-column flex-wrap md:flex-row justify-between p-4" aria-label="Table navigation">
				<span class="text-sm font-normal text-gray-500 dark:text-gray-400 mb-4 md:mb-0">
					Showing <span class="font-semibold text-gray-900 dark:text-white">{ strconv.Itoa((data.Page-1)*data.Limit+1) }-{ strconv.Itoa(func() int { 
						end := data.Page*data.Limit
						if int64(end) > data.TotalCount {
							return int(data.TotalCount)
						}
						return end
					}()) }</span> of <span class="font-semibold text-gray-900 dark:text-white">{ strconv.FormatInt(data.TotalCount, 10) }</span>
				</span>
				<ul class="inline-flex -space-x-px rtl:space-x-reverse text-sm h-8">
					<li>
						if data.Page == 1 {
							<span class="flex items-center justify-center px-3 h-8 ms-0 leading-tight text-gray-500 bg-white border border-gray-300 rounded-s-lg cursor-not-allowed dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400">
								Previous
							</span>
						} else {
							<a hx-get={ fmt.Sprintf("/files/partial?page=%d&limit=%d&status=%s&filename=%s&job_id=%s", data.Page - 1, data.Limit, data.Filter.Status, data.Filter.FileName, data.Filter.JobID) }
							   hx-target="#file-list-container"
							   hx-swap="innerHTML"
							   class="flex items-center justify-center px-3 h-8 ms-0 leading-tight text-gray-500 bg-white border border-gray-300 rounded-s-lg hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white">
								Previous
							</a>
						}
					</li>
					
					for i := 1; i <= data.TotalPages; i++ {
						// Always show first page, last page, and pages around current page
						if i == 1 || i == data.TotalPages || (i >= data.Page-2 && i <= data.Page+2) {
							<li>
								if i == data.Page {
									<span aria-current="page" class="flex items-center justify-center px-3 h-8 text-blue-600 border border-gray-300 bg-blue-50 hover:bg-blue-100 hover:text-blue-700 dark:border-gray-700 dark:bg-gray-700 dark:text-white">
										{ strconv.Itoa(i) }
									</span>
								} else {
									<a hx-get={ fmt.Sprintf("/files/partial?page=%d&limit=%d&status=%s&filename=%s&job_id=%s", i, data.Limit, data.Filter.Status, data.Filter.FileName, data.Filter.JobID) }
									   hx-target="#file-list-container"
									   hx-swap="innerHTML"
									   class="flex items-center justify-center px-3 h-8 leading-tight text-gray-500 bg-white border border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white">
										{ strconv.Itoa(i) }
									</a>
								}
							</li>
						} else if (i == 2 && data.Page > 4) || (i == data.TotalPages-1 && data.Page < data.TotalPages-3) {
							// Show ellipsis for gaps
							<li>
								<span class="flex items-center justify-center px-3 h-8 leading-tight text-gray-500 bg-white border border-gray-300 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400">
									...
								</span>
							</li>
						}
					}
					
					<li>
						if data.Page == data.TotalPages {
							<span class="flex items-center justify-center px-3 h-8 leading-tight text-gray-500 bg-white border border-gray-300 rounded-e-lg cursor-not-allowed dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400">
								Next
							</span>
						} else {
							<a hx-get={ fmt.Sprintf("/files/partial?page=%d&limit=%d&status=%s&filename=%s&job_id=%s", data.Page + 1, data.Limit, data.Filter.Status, data.Filter.FileName, data.Filter.JobID) }
							   hx-target="#file-list-container"
							   hx-swap="innerHTML"
							   class="flex items-center justify-center px-3 h-8 leading-tight text-gray-500 bg-white border border-gray-300 rounded-e-lg hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white">
								Next
							</a>
						}
					</li>
				</ul>
			</nav>
		}
	</div>
}

// Update the main FileMetadataList template to use the partial template
templ FileMetadataList(ctx context.Context, data FileMetadataListData) {
	@LayoutWithContext("File Metadata", ctx) {
		<!-- Status and Error Messages -->
		<div id="toast-container" class="fixed top-5 right-5 z-50 flex flex-col gap-2"></div>
		
		<script>
			// Debug notification system
			console.log("File Metadata template loaded, setting up notification system");
			
			// Function to create and show a toast
			function showToast(message, type) {
				const toastContainer = document.getElementById('toast-container');
				
				// Create toast element
				const toast = document.createElement('div');
				toast.id = 'toast-' + type + '-' + Date.now();
				toast.className = 'flex items-center w-full max-w-xs p-4 mb-4 rounded-lg shadow text-gray-500 bg-white dark:text-gray-400 dark:bg-gray-800 transform translate-y-16 opacity-0 transition-all duration-300 ease-out';
				toast.role = 'alert';
				
				// Set toast content based on type
				let iconClass, bgColorClass, textColorClass;
				
				if (type === 'success') {
					iconClass = 'text-green-500 bg-green-100 dark:bg-green-800 dark:text-green-200';
					bgColorClass = 'text-green-500 dark:text-green-200';
					textColorClass = 'text-green-500 dark:text-green-200';
				} else if (type === 'error') {
					iconClass = 'text-red-500 bg-red-100 dark:bg-red-800 dark:text-red-200';
					bgColorClass = 'text-red-500 dark:text-red-200';
					textColorClass = 'text-red-500 dark:text-red-200';
				} else {
					iconClass = 'text-blue-500 bg-blue-100 dark:bg-blue-800 dark:text-blue-200';
					bgColorClass = 'text-blue-500 dark:text-blue-200';
					textColorClass = 'text-blue-500 dark:text-blue-200';
				}
				
				// Set inner HTML with appropriate icon and message
				toast.innerHTML = `
					<div class="inline-flex items-center justify-center flex-shrink-0 w-8 h-8 rounded-lg ${iconClass}">
						${type === 'success' 
							? '<i class="fas fa-check"></i>' 
							: type === 'error' 
							? '<i class="fas fa-exclamation-circle"></i>'
							: '<i class="fas fa-info-circle"></i>'}
					</div>
					<div class="ml-3 text-sm font-normal">${message}</div>
					<button type="button" class="ml-auto -mx-1.5 -my-1.5 bg-white text-gray-400 hover:text-gray-900 rounded-lg focus:ring-2 focus:ring-gray-300 p-1.5 hover:bg-gray-100 inline-flex h-8 w-8 dark:text-gray-500 dark:hover:text-white dark:bg-gray-800 dark:hover:bg-gray-700" data-dismiss-target="#${toast.id}" aria-label="Close">
						<span class="sr-only">Close</span>
						<i class="fas fa-times"></i>
					</button>
				`;
				
				// Add toast to container
				toastContainer.appendChild(toast);
				
				// Trigger animation after a small delay to ensure the DOM has updated
				setTimeout(() => {
					toast.classList.remove('translate-y-16', 'opacity-0');
					toast.classList.add('translate-y-0', 'opacity-100');
				}, 10);
				
				// Add event listener to close button
				const closeButton = toast.querySelector('button[data-dismiss-target]');
				closeButton.addEventListener('click', function() {
					// Animate out before removing
					toast.classList.add('opacity-0', 'translate-y-4');
					setTimeout(() => {
						toast.remove();
					}, 300);
				});
				
				// Auto-remove toast after 5 seconds
				setTimeout(() => {
					toast.classList.add('opacity-0', 'translate-y-4');
					setTimeout(() => {
						toast.remove();
					}, 300);
				}, 5000);
			}
			
			// Handle modal hide buttons
			document.addEventListener('DOMContentLoaded', function() {
				const hideButtons = document.querySelectorAll('[data-modal-hide]');
				hideButtons.forEach(button => {
					button.addEventListener('click', function() {
						const modalId = this.getAttribute('data-modal-hide');
						const modal = document.getElementById(modalId);
						modal.classList.add('hidden');
						modal.classList.remove('flex');
					});
				});
			});
			
			// Track all HTMX events for debugging
			document.addEventListener('htmx:beforeRequest', function(event) {
				console.log("HTMX before request:", event.detail);
				
				// Check if this is a DELETE request by examining the URL and method
				const path = event.detail.path;
				const method = event.detail.verb;
				
				console.log(`Request path: ${path}, method: ${method}`);
				
				// Pattern match for file deletions (e.g., /files/123)
				if (path && method === 'DELETE' && path.match(/^\/files\/\d+$/)) {
					console.log("Detected file deletion request via URL pattern");
					
					// This is definitely a delete request - store this information
					window.isFileDeleteRequest = true;
				}
			});

			// Track HTMX after-request events for file deletion
			document.addEventListener('htmx:afterRequest', function(event) {
				console.log("HTMX after request:", event.detail);
				
				// Check for file deletion multiple ways
				const isDeleteRequest = 
					// Check global flag from the triggerFileDelete function
					window.currentlyDeletingFile ||
					// Check flag from beforeRequest handler
					window.isFileDeleteRequest ||
					// Check URL pattern directly from this event
					(event.detail.pathInfo && event.detail.pathInfo.requestPath && 
					 event.detail.pathInfo.requestPath.match(/^\/files\/\d+$/) && 
					 event.detail.verb === 'DELETE');
				
				console.log(`Is delete request: ${isDeleteRequest}`);
				
				// If this is a successful delete request, show notification
				if (isDeleteRequest && event.detail.successful) {
					console.log("Delete request was successful");
					
					let fileName = "Unknown";
					
					// Try multiple sources for file name
					if (event.detail.elt && event.detail.elt.getAttribute) {
						fileName = event.detail.elt.getAttribute('data-file-name') || fileName;
					}
					
					if (fileName === "Unknown" && window.lastDeletedFile) {
						// Fallback to our stored file info
						fileName = window.lastDeletedFile.name;
					}
					
					console.log(`Showing success notification for deleted file: ${fileName}`);
					showToast(`File "${fileName}" deleted successfully`, 'success');
					
					// Clear flags
					window.currentlyDeletingFile = false;
					window.isFileDeleteRequest = false;
					window.lastDeletedFile = null;
				}
			});
			
			// Track HTMX error events for file deletion
			document.addEventListener('htmx:responseError', function(event) {
				console.log("HTMX response error:", event.detail);
				
				// Similar logic as success but for errors
				const isDeleteRequest = 
					window.currentlyDeletingFile ||
					window.isFileDeleteRequest ||
					(event.detail.pathInfo && event.detail.pathInfo.requestPath && 
					 event.detail.pathInfo.requestPath.match(/^\/files\/\d+$/) && 
					 event.detail.verb === 'DELETE');
				
				if (isDeleteRequest) {
					console.log("Delete request failed");
					
					let fileName = "Unknown";
					
					// Try multiple sources for file name
					if (event.detail.elt && event.detail.elt.getAttribute) {
						fileName = event.detail.elt.getAttribute('data-file-name') || fileName;
					}
					
					if (fileName === "Unknown" && window.lastDeletedFile) {
						// Fallback to our stored file info
						fileName = window.lastDeletedFile.name;
					}
					
					let errorMsg = `Failed to delete file "${fileName}"`;
					
					if (event.detail.xhr && event.detail.xhr.responseText) {
						errorMsg = `Error: ${event.detail.xhr.responseText}`;
					}
					
					console.log(`Showing error notification: ${errorMsg}`);
					showToast(errorMsg, 'error');
					
					// Clear flags
					window.currentlyDeletingFile = false;
					window.isFileDeleteRequest = false;
					window.lastDeletedFile = null;
				}
			});
		</script>
		
		<div id="file-metadata-container" style="min-height: 100vh;" class="bg-gray-50 dark:bg-gray-900">
			<div class="pb-8 w-full">
				<div class="mb-6 flex flex-col md:flex-row md:items-center md:justify-between gap-4">
					<h1 class="text-2xl font-bold text-gray-900 dark:text-white flex items-center">
						<i class="fas fa-file-alt w-6 h-6 mr-2 text-blue-500"></i>
						if data.Job != nil {
							Files for Job: { data.Job.Name }
						} else {
							File Metadata
						}
					</h1>
					<a href="/files/search" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800">
						<i class="fas fa-search mr-2"></i>Advanced Search
					</a>
				</div>
				
				<!-- Filter Form -->
				<div class="p-4 mb-6 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700 w-full">
					<h5 class="mb-4 text-lg font-semibold text-gray-900 dark:text-white">Filter Files</h5>
					<form 
						hx-get="/files/partial" 
						hx-target="#file-list-container" 
						hx-swap="innerHTML"
						hx-indicator="#filter-loading"
						hx-headers='{"X-HX-Request": "true"}'
						class="grid grid-cols-1 md:grid-cols-3 gap-4">
						if data.Job == nil {
							<div>
								<label for="job_id" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Job</label>
								<input type="text" id="job_id" name="job_id" value={ data.Filter.JobID } placeholder="Job ID" 
									class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" />
							</div>
						}
						<div>
							<label for="status" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Status</label>
							<select id="status" name="status" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
								<option value="">All Statuses</option>
								<option value="processed" selected?={ data.Filter.Status == "processed" }>Processed</option>
								<option value="archived" selected?={ data.Filter.Status == "archived" }>Archived</option>
								<option value="deleted" selected?={ data.Filter.Status == "deleted" }>Deleted</option>
								<option value="archived_and_deleted" selected?={ data.Filter.Status == "archived_and_deleted" }>Archived & Deleted</option>
								<option value="error" selected?={ data.Filter.Status == "error" }>Error</option>
							</select>
						</div>
						<div>
							<label for="filename" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Filename</label>
							<input type="text" id="filename" name="filename" value={ data.Filter.FileName } placeholder="Filename or partial match" 
								class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" />
						</div>
						<div class="md:col-span-3 flex justify-end items-center">
							<button type="submit" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800">
								<i class="fas fa-filter mr-2"></i> Apply Filters
							</button>
							<div id="filter-loading" class="htmx-indicator ml-2 flex items-center">
								<i class="fas fa-circle-notch fa-spin text-blue-600"></i>
							</div>
						</div>
					</form>
				</div>
				
				<!-- Results -->
				<div class="bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700 w-full">
					<div class="flex items-center justify-between p-4 border-b border-gray-200 dark:border-gray-600">
						<h5 class="text-lg font-semibold text-gray-900 dark:text-white">Files ({ strconv.FormatInt(data.TotalCount, 10) })</h5>
						<span class="text-sm text-gray-500 dark:text-gray-400">
							Page { strconv.Itoa(data.Page) } of { strconv.Itoa(data.TotalPages) }
						</span>
					</div>
					<div id="file-list-container" class="w-full">
						if len(data.Files) > 0 {
							@FileMetadataListPartial(data)
						} else {
							<div class="p-6 text-center text-gray-500 dark:text-gray-400">
								<svg class="mx-auto mb-4 w-12 h-12 text-gray-400" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
									<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" />
								</svg>
								<p>No file metadata found matching your criteria.</p>
							</div>
						}
					</div>
				</div>
			</div>

			<script>
				// Set dark background color if in dark mode
				if (document.documentElement.classList.contains('dark')) {
					document.getElementById('file-metadata-container').style.backgroundColor = '#111827';
				}
				
				// Add event listener for theme changes
				document.addEventListener('DOMContentLoaded', function() {
					const themeToggle = document.getElementById('theme-toggle');
					if (themeToggle) {
						themeToggle.addEventListener('click', function() {
							setTimeout(function() {
								const isDark = document.documentElement.classList.contains('dark');
								document.getElementById('file-metadata-container').style.backgroundColor = isDark ? '#111827' : 'rgb(249, 250, 251)';
							}, 50);
						});
					}
				});
			</script>
		</div>
	}
}

// FileMetadataDetails renders detailed information about a file
templ FileMetadataDetails(ctx context.Context, data FileMetadataDetailsData) {
	@LayoutWithContext("File Details", ctx) {
		<!-- Status and Error Messages -->
		<div id="toast-container" class="fixed top-5 right-5 z-50 flex flex-col gap-2"></div>
		
		<script>
			// Debug notification system
			console.log("File Details template loaded, setting up notification system");
			
			// Function to create and show a toast
			function showToast(message, type) {
				const toastContainer = document.getElementById('toast-container');
				
				// Create toast element
				const toast = document.createElement('div');
				toast.id = 'toast-' + type + '-' + Date.now();
				toast.className = 'flex items-center w-full max-w-xs p-4 mb-4 rounded-lg shadow text-gray-500 bg-white dark:text-gray-400 dark:bg-gray-800 transform translate-y-16 opacity-0 transition-all duration-300 ease-out';
				toast.role = 'alert';
				
				// Set toast content based on type
				let iconClass, bgColorClass, textColorClass;
				
				if (type === 'success') {
					iconClass = 'text-green-500 bg-green-100 dark:bg-green-800 dark:text-green-200';
					bgColorClass = 'text-green-500 dark:text-green-200';
					textColorClass = 'text-green-500 dark:text-green-200';
				} else if (type === 'error') {
					iconClass = 'text-red-500 bg-red-100 dark:bg-red-800 dark:text-red-200';
					bgColorClass = 'text-red-500 dark:text-red-200';
					textColorClass = 'text-red-500 dark:text-red-200';
				} else {
					iconClass = 'text-blue-500 bg-blue-100 dark:bg-blue-800 dark:text-blue-200';
					bgColorClass = 'text-blue-500 dark:text-blue-200';
					textColorClass = 'text-blue-500 dark:text-blue-200';
				}
				
				// Set inner HTML with appropriate icon and message
				toast.innerHTML = `
					<div class="inline-flex items-center justify-center flex-shrink-0 w-8 h-8 rounded-lg ${iconClass}">
						${type === 'success' 
							? '<i class="fas fa-check"></i>' 
							: type === 'error' 
							? '<i class="fas fa-exclamation-circle"></i>'
							: '<i class="fas fa-info-circle"></i>'}
					</div>
					<div class="ml-3 text-sm font-normal">${message}</div>
					<button type="button" class="ml-auto -mx-1.5 -my-1.5 bg-white text-gray-400 hover:text-gray-900 rounded-lg focus:ring-2 focus:ring-gray-300 p-1.5 hover:bg-gray-100 inline-flex h-8 w-8 dark:text-gray-500 dark:hover:text-white dark:bg-gray-800 dark:hover:bg-gray-700" data-dismiss-target="#${toast.id}" aria-label="Close">
						<span class="sr-only">Close</span>
						<i class="fas fa-times"></i>
					</button>
				`;
				
				// Add toast to container
				toastContainer.appendChild(toast);
				
				// Trigger animation after a small delay to ensure the DOM has updated
				setTimeout(() => {
					toast.classList.remove('translate-y-16', 'opacity-0');
					toast.classList.add('translate-y-0', 'opacity-100');
				}, 10);
				
				// Add event listener to close button
				const closeButton = toast.querySelector('button[data-dismiss-target]');
				closeButton.addEventListener('click', function() {
					// Animate out before removing
					toast.classList.add('opacity-0', 'translate-y-4');
					setTimeout(() => {
						toast.remove();
					}, 300);
				});
				
				// Auto-remove toast after 5 seconds
				setTimeout(() => {
					toast.classList.add('opacity-0', 'translate-y-4');
					setTimeout(() => {
						toast.remove();
					}, 300);
				}, 5000);
			}
			
			// Handle modal hide buttons
			document.addEventListener('DOMContentLoaded', function() {
				const hideButtons = document.querySelectorAll('[data-modal-hide]');
				hideButtons.forEach(button => {
					button.addEventListener('click', function() {
						const modalId = this.getAttribute('data-modal-hide');
						const modal = document.getElementById(modalId);
						modal.classList.add('hidden');
						modal.classList.remove('flex');
					});
				});
			});
			
			// Track deletion events
			document.addEventListener('htmx:beforeRequest', function(event) {
				if (event.detail.path && event.detail.path.match(/^\/files\/\d+$/) && event.detail.verb === 'DELETE') {
					window.isFileDeleteRequest = true;
				}
			});
			
			document.addEventListener('htmx:afterRequest', function(event) {
				const isDeleteRequest = 
					window.currentlyDeletingFile ||
					window.isFileDeleteRequest ||
					(event.detail.pathInfo && event.detail.pathInfo.requestPath && 
					event.detail.pathInfo.requestPath.match(/^\/files\/\d+$/) && 
					event.detail.verb === 'DELETE');
				
				if (isDeleteRequest && event.detail.successful) {
					let fileName = "Unknown";
					
					if (event.detail.elt && event.detail.elt.getAttribute) {
						fileName = event.detail.elt.getAttribute('data-file-name') || fileName;
					}
					
					if (fileName === "Unknown" && window.lastDeletedFile) {
						fileName = window.lastDeletedFile.name;
					}
					
					showToast(`File "${fileName}" deleted successfully`, 'success');
					
					window.currentlyDeletingFile = false;
					window.isFileDeleteRequest = false;
					window.lastDeletedFile = null;
				}
			});
			
			document.addEventListener('htmx:responseError', function(event) {
				const isDeleteRequest = 
					window.currentlyDeletingFile ||
					window.isFileDeleteRequest ||
					(event.detail.pathInfo && event.detail.pathInfo.requestPath && 
					event.detail.pathInfo.requestPath.match(/^\/files\/\d+$/) && 
					event.detail.verb === 'DELETE');
				
				if (isDeleteRequest) {
					let fileName = "Unknown";
					
					if (event.detail.elt && event.detail.elt.getAttribute) {
						fileName = event.detail.elt.getAttribute('data-file-name') || fileName;
					}
					
					if (fileName === "Unknown" && window.lastDeletedFile) {
						fileName = window.lastDeletedFile.name;
					}
					
					let errorMsg = `Failed to delete file "${fileName}"`;
					
					if (event.detail.xhr && event.detail.xhr.responseText) {
						errorMsg = `Error: ${event.detail.xhr.responseText}`;
					}
					
					showToast(errorMsg, 'error');
					
					window.currentlyDeletingFile = false;
					window.isFileDeleteRequest = false;
					window.lastDeletedFile = null;
				}
			});
		</script>
		
		<div id="file-details-container" style="min-height: 100vh;" class="bg-gray-50 dark:bg-gray-900">
			<div class="pb-8 w-full">
				<div class="mb-6 flex flex-col md:flex-row md:items-center md:justify-between gap-4">
					<h1 class="text-2xl font-bold text-gray-900 dark:text-white flex items-center">
						<i class="fas fa-file-alt w-6 h-6 mr-2 text-blue-500"></i>
						File Details: { data.File.FileName }
					</h1>
					<a href="/files" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800">
						<i class="fas fa-arrow-left mr-2"></i> Back to Files
					</a>
				</div>
				
				<div class="bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700 w-full">
					<!-- Card header -->
					<div class="p-4 md:p-5 border-b border-gray-200 dark:border-gray-700">
						<h5 class="text-xl font-bold leading-none text-gray-900 dark:text-white">
							{ data.File.FileName }
						</h5>
						<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
							File ID: { strconv.FormatUint(uint64(data.File.ID), 10) }
						</p>
					</div>
					
					<!-- Card content -->
					<div class="p-4 md:p-5">
						<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
							<!-- File Information -->
							<div>
								<h6 class="text-lg font-semibold mb-4 text-gray-900 dark:text-white flex items-center">
									<i class="fas fa-file-alt mr-2 text-gray-500 dark:text-gray-400"></i> File Information
								</h6>
								<div class="overflow-x-auto relative shadow-md sm:rounded-lg">
									<table class="w-full text-sm text-left text-gray-500 dark:text-gray-400">
										<tbody>
											<tr class="border-b dark:border-gray-700">
												<th scope="row" class="py-3 px-4 font-medium text-gray-900 whitespace-nowrap dark:text-white bg-gray-50 dark:bg-gray-800">
													Filename
												</th>
												<td class="py-3 px-4 bg-white dark:bg-gray-800">
													{ data.File.FileName }
												</td>
											</tr>
											<tr class="border-b dark:border-gray-700">
												<th scope="row" class="py-3 px-4 font-medium text-gray-900 whitespace-nowrap dark:text-white bg-gray-50 dark:bg-gray-800">
													Size
												</th>
												<td class="py-3 px-4 bg-white dark:bg-gray-800">
													{ formatFileSize(data.File.FileSize) }
												</td>
											</tr>
											<tr class="border-b dark:border-gray-700">
												<th scope="row" class="py-3 px-4 font-medium text-gray-900 whitespace-nowrap dark:text-white bg-gray-50 dark:bg-gray-800">
													Hash
												</th>
												<td class="py-3 px-4 break-all bg-white dark:bg-gray-800">
													if data.File.FileHash != "" {
														<span class="font-mono">{ data.File.FileHash }</span>
													} else {
														<span class="text-gray-400 dark:text-gray-500 italic">Not available</span>
													}
												</td>
											</tr>
											<tr class="border-b dark:border-gray-700">
												<th scope="row" class="py-3 px-4 font-medium text-gray-900 whitespace-nowrap dark:text-white bg-gray-50 dark:bg-gray-800">
													Status
												</th>
												<td class="py-3 px-4 bg-white dark:bg-gray-800">
													<span class={ "text-xs font-medium px-2.5 py-0.5 rounded", getStatusBadgeClass(data.File.Status) }>
														{ data.File.Status }
													</span>
												</td>
											</tr>
											<tr class="border-b dark:border-gray-700">
												<th scope="row" class="py-3 px-4 font-medium text-gray-900 whitespace-nowrap dark:text-white bg-gray-50 dark:bg-gray-800">
													Original Path
												</th>
												<td class="py-3 px-4 break-all bg-white dark:bg-gray-800">
													<div class="flex items-center">
														<i class="fas fa-folder mr-2 text-yellow-500"></i>
														<span>{ data.File.OriginalPath }</span>
													</div>
												</td>
											</tr>
											<tr class="border-b dark:border-gray-700">
												<th scope="row" class="py-3 px-4 font-medium text-gray-900 whitespace-nowrap dark:text-white bg-gray-50 dark:bg-gray-800">
													Destination Path
												</th>
												<td class="py-3 px-4 break-all bg-white dark:bg-gray-800">
													<div class="flex items-center">
														<i class="fas fa-folder-open mr-2 text-blue-500"></i>
														<span>{ data.File.DestinationPath }</span>
													</div>
												</td>
											</tr>
										</tbody>
									</table>
								</div>
							</div>
							
							<!-- Processing Information -->
							<div>
								<h6 class="text-lg font-semibold mb-4 text-gray-900 dark:text-white flex items-center">
									<i class="fas fa-cogs mr-2 text-gray-500 dark:text-gray-400"></i> Processing Information
								</h6>
								<div class="overflow-x-auto relative shadow-md sm:rounded-lg">
									<table class="w-full text-sm text-left text-gray-500 dark:text-gray-400">
										<tbody>
											<tr class="border-b dark:border-gray-700">
												<th scope="row" class="py-3 px-4 font-medium text-gray-900 whitespace-nowrap dark:text-white bg-gray-50 dark:bg-gray-800">
													Job
												</th>
												<td class="py-3 px-4 bg-white dark:bg-gray-800">
													<a href={ templ.SafeURL(fmt.Sprintf("/files/job/%d", data.File.JobID)) } class="font-medium text-blue-600 dark:text-blue-500 hover:underline">
														{ data.File.Job.Name }
													</a>
												</td>
											</tr>
											<tr class="border-b dark:border-gray-700">
												<th scope="row" class="py-3 px-4 font-medium text-gray-900 whitespace-nowrap dark:text-white bg-gray-50 dark:bg-gray-800">
													Processed Time
												</th>
												<td class="py-3 px-4 bg-white dark:bg-gray-800">
													<div class="flex items-center">
														<i class="far fa-clock mr-2 text-gray-500"></i>
														<span>{ data.File.ProcessedTime.Format("2006-01-02 15:04:05") }</span>
													</div>
												</td>
											</tr>
											<tr class="border-b dark:border-gray-700">
												<th scope="row" class="py-3 px-4 font-medium text-gray-900 whitespace-nowrap dark:text-white bg-gray-50 dark:bg-gray-800">
													Creation Time
												</th>
												<td class="py-3 px-4 bg-white dark:bg-gray-800">
													<div class="flex items-center">
														<i class="fas fa-calendar-plus mr-2 text-green-500"></i>
														<span>{ data.File.CreationTime.Format("2006-01-02 15:04:05") }</span>
													</div>
												</td>
											</tr>
											<tr class="border-b dark:border-gray-700">
												<th scope="row" class="py-3 px-4 font-medium text-gray-900 whitespace-nowrap dark:text-white bg-gray-50 dark:bg-gray-800">
													Modification Time
												</th>
												<td class="py-3 px-4 bg-white dark:bg-gray-800">
													<div class="flex items-center">
														<i class="fas fa-calendar-alt mr-2 text-purple-500"></i>
														<span>{ data.File.ModTime.Format("2006-01-02 15:04:05") }</span>
													</div>
												</td>
											</tr>
											if data.File.Status == "error" && data.File.ErrorMessage != "" {
												<tr class="border-b dark:border-gray-700">
													<th scope="row" class="py-3 px-4 font-medium text-gray-900 whitespace-nowrap dark:text-white bg-gray-50 dark:bg-gray-800">
														Error
													</th>
													<td class="py-3 px-4 break-all bg-white dark:bg-gray-800">
														<div class="flex items-start">
															<i class="fas fa-exclamation-triangle mt-1 mr-2 text-red-500"></i>
															<span class="text-red-600 dark:text-red-400">{ data.File.ErrorMessage }</span>
														</div>
													</td>
												</tr>
											}
											<tr class="border-b dark:border-gray-700">
												<th scope="row" class="py-3 px-4 font-medium text-gray-900 whitespace-nowrap dark:text-white bg-gray-50 dark:bg-gray-800">
													Record Created
												</th>
												<td class="py-3 px-4 bg-white dark:bg-gray-800">
													{ data.File.CreatedAt.Format("2006-01-02 15:04:05") }
												</td>
											</tr>
											<tr class="border-b dark:border-gray-700">
												<th scope="row" class="py-3 px-4 font-medium text-gray-900 whitespace-nowrap dark:text-white bg-gray-50 dark:bg-gray-800">
													Record Updated
												</th>
												<td class="py-3 px-4 bg-white dark:bg-gray-800">
													{ data.File.UpdatedAt.Format("2006-01-02 15:04:05") }
												</td>
											</tr>
										</tbody>
									</table>
								</div>
							</div>
						</div>
						
						<!-- Delete dialog -->
						@FileMetadataDialog(
							fmt.Sprintf("delete-file-dialog-%d", data.File.ID),
							"Delete File Metadata",
							fmt.Sprintf("Are you sure you want to delete the metadata for '%s'? This cannot be undone.", data.File.FileName),
							"btn-danger",
							"Delete",
							"delete",
							data.File.ID,
							data.File.FileName,
							"details",
						)
						
						<!-- Action buttons -->
						<div class="mt-6 flex flex-wrap justify-end gap-3">
							<a href="/files" class="py-2.5 px-5 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700">
								<i class="fas fa-list mr-2"></i> Back to Files
							</a>
							<button 
								type="button"
								onclick={ showFileDialog(fmt.Sprintf("delete-file-dialog-%d", data.File.ID)) }
								class="text-white bg-red-700 hover:bg-red-800 focus:ring-4 focus:ring-red-300 font-medium rounded-lg text-sm px-5 py-2.5 dark:bg-red-600 dark:hover:bg-red-700 focus:outline-none dark:focus:ring-red-800">
								<i class="fas fa-trash mr-2"></i> Delete Record
							</button>
						</div>
					</div>
				</div>
			</div>

			<script>
				// Set dark background color if in dark mode
				if (document.documentElement.classList.contains('dark')) {
					document.getElementById('file-details-container').style.backgroundColor = '#111827';
				}
				
				// Add event listener for theme changes
				document.addEventListener('DOMContentLoaded', function() {
					const themeToggle = document.getElementById('theme-toggle');
					if (themeToggle) {
						themeToggle.addEventListener('click', function() {
							setTimeout(function() {
								const isDark = document.documentElement.classList.contains('dark');
								document.getElementById('file-details-container').style.backgroundColor = isDark ? '#111827' : 'rgb(249, 250, 251)';
							}, 50);
						});
					}
				});
			</script>
		</div>
	}
}

// FileMetadataSearch renders an advanced search form for file metadata
templ FileMetadataSearch(ctx context.Context, data FileMetadataSearchData) {
	@LayoutWithContext("Search Files", ctx) {
		<!-- Status and Error Messages -->
		<div id="toast-container" class="fixed top-5 right-5 z-50 flex flex-col gap-2"></div>
		
		<script>
			// Debug notification system
			console.log("File Search template loaded, setting up notification system");
			
			// Function to create and show a toast
			function showToast(message, type) {
				const toastContainer = document.getElementById('toast-container');
				
				// Create toast element
				const toast = document.createElement('div');
				toast.id = 'toast-' + type + '-' + Date.now();
				toast.className = 'flex items-center w-full max-w-xs p-4 mb-4 rounded-lg shadow text-gray-500 bg-white dark:text-gray-400 dark:bg-gray-800 transform translate-y-16 opacity-0 transition-all duration-300 ease-out';
				toast.role = 'alert';
				
				// Set toast content based on type
				let iconClass, bgColorClass, textColorClass;
				
				if (type === 'success') {
					iconClass = 'text-green-500 bg-green-100 dark:bg-green-800 dark:text-green-200';
					bgColorClass = 'text-green-500 dark:text-green-200';
					textColorClass = 'text-green-500 dark:text-green-200';
				} else if (type === 'error') {
					iconClass = 'text-red-500 bg-red-100 dark:bg-red-800 dark:text-red-200';
					bgColorClass = 'text-red-500 dark:text-red-200';
					textColorClass = 'text-red-500 dark:text-red-200';
				} else {
					iconClass = 'text-blue-500 bg-blue-100 dark:bg-blue-800 dark:text-blue-200';
					bgColorClass = 'text-blue-500 dark:text-blue-200';
					textColorClass = 'text-blue-500 dark:text-blue-200';
				}
				
				// Set inner HTML with appropriate icon and message
				toast.innerHTML = `
					<div class="inline-flex items-center justify-center flex-shrink-0 w-8 h-8 rounded-lg ${iconClass}">
						${type === 'success' 
							? '<i class="fas fa-check"></i>' 
							: type === 'error' 
							? '<i class="fas fa-exclamation-circle"></i>'
							: '<i class="fas fa-info-circle"></i>'}
					</div>
					<div class="ml-3 text-sm font-normal">${message}</div>
					<button type="button" class="ml-auto -mx-1.5 -my-1.5 bg-white text-gray-400 hover:text-gray-900 rounded-lg focus:ring-2 focus:ring-gray-300 p-1.5 hover:bg-gray-100 inline-flex h-8 w-8 dark:text-gray-500 dark:hover:text-white dark:bg-gray-800 dark:hover:bg-gray-700" data-dismiss-target="#${toast.id}" aria-label="Close">
						<span class="sr-only">Close</span>
						<i class="fas fa-times"></i>
					</button>
				`;
				
				// Add toast to container
				toastContainer.appendChild(toast);
				
				// Trigger animation after a small delay to ensure the DOM has updated
				setTimeout(() => {
					toast.classList.remove('translate-y-16', 'opacity-0');
					toast.classList.add('translate-y-0', 'opacity-100');
				}, 10);
				
				// Add event listener to close button
				const closeButton = toast.querySelector('button[data-dismiss-target]');
				closeButton.addEventListener('click', function() {
					// Animate out before removing
					toast.classList.add('opacity-0', 'translate-y-4');
					setTimeout(() => {
						toast.remove();
					}, 300);
				});
				
				// Auto-remove toast after 5 seconds
				setTimeout(() => {
					toast.classList.add('opacity-0', 'translate-y-4');
					setTimeout(() => {
						toast.remove();
					}, 300);
				}, 5000);
			}
			
			// Handle modal hide buttons
			document.addEventListener('DOMContentLoaded', function() {
				const hideButtons = document.querySelectorAll('[data-modal-hide]');
				hideButtons.forEach(button => {
					button.addEventListener('click', function() {
						const modalId = this.getAttribute('data-modal-hide');
						const modal = document.getElementById(modalId);
						modal.classList.add('hidden');
						modal.classList.remove('flex');
					});
				});
			});
			
			// Track deletion events
			document.addEventListener('htmx:beforeRequest', function(event) {
				if (event.detail.path && event.detail.path.match(/^\/files\/\d+$/) && event.detail.verb === 'DELETE') {
					window.isFileDeleteRequest = true;
				}
			});
			
			document.addEventListener('htmx:afterRequest', function(event) {
				const isDeleteRequest = 
					window.currentlyDeletingFile ||
					window.isFileDeleteRequest ||
					(event.detail.pathInfo && event.detail.pathInfo.requestPath && 
					event.detail.pathInfo.requestPath.match(/^\/files\/\d+$/) && 
					event.detail.verb === 'DELETE');
				
				if (isDeleteRequest && event.detail.successful) {
					let fileName = "Unknown";
					
					if (event.detail.elt && event.detail.elt.getAttribute) {
						fileName = event.detail.elt.getAttribute('data-file-name') || fileName;
					}
					
					if (fileName === "Unknown" && window.lastDeletedFile) {
						fileName = window.lastDeletedFile.name;
					}
					
					showToast(`File "${fileName}" deleted successfully`, 'success');
					
					window.currentlyDeletingFile = false;
					window.isFileDeleteRequest = false;
					window.lastDeletedFile = null;
				}
			});
			
			document.addEventListener('htmx:responseError', function(event) {
				const isDeleteRequest = 
					window.currentlyDeletingFile ||
					window.isFileDeleteRequest ||
					(event.detail.pathInfo && event.detail.pathInfo.requestPath && 
					event.detail.pathInfo.requestPath.match(/^\/files\/\d+$/) && 
					event.detail.verb === 'DELETE');
				
				if (isDeleteRequest) {
					let fileName = "Unknown";
					
					if (event.detail.elt && event.detail.elt.getAttribute) {
						fileName = event.detail.elt.getAttribute('data-file-name') || fileName;
					}
					
					if (fileName === "Unknown" && window.lastDeletedFile) {
						fileName = window.lastDeletedFile.name;
					}
					
					let errorMsg = `Failed to delete file "${fileName}"`;
					
					if (event.detail.xhr && event.detail.xhr.responseText) {
						errorMsg = `Error: ${event.detail.xhr.responseText}`;
					}
					
					showToast(errorMsg, 'error');
					
					window.currentlyDeletingFile = false;
					window.isFileDeleteRequest = false;
					window.lastDeletedFile = null;
				}
			});
		</script>
		
		<div id="file-search-container" style="min-height: 100vh;" class="bg-gray-50 dark:bg-gray-900">
			<div class="pb-8 w-full">
				<div class="mb-6 flex flex-col md:flex-row md:items-center md:justify-between gap-4">
					<h1 class="text-2xl font-bold text-gray-900 dark:text-white flex items-center">
						<i class="fas fa-search w-6 h-6 mr-2 text-blue-500"></i>
						File Metadata Search
					</h1>
					<a href="/files" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800">
						<i class="fas fa-arrow-left mr-2"></i> Back to Files
					</a>
				</div>
				
				<div class="p-4 mb-6 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700 w-full">
					<h5 class="mb-4 text-lg font-semibold text-gray-900 dark:text-white">Advanced File Search</h5>
					<form 
						hx-get="/files/search/partial"
						hx-target="#search-results-container" 
						hx-swap="innerHTML"
						hx-indicator="#search-form-loading"
						hx-headers='{"X-HX-Request": "true"}'
						hx-boost="false"
						class="grid grid-cols-1 md:grid-cols-2 gap-4">
						<div>
							<label for="job_id" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Job ID</label>
							<input type="text" id="job_id" name="job_id" value={ data.Filter.JobID } placeholder="Job ID" 
								class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" />
						</div>
						<div>
							<label for="status" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Status</label>
							<select id="status" name="status" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
								<option value="">All Statuses</option>
								<option value="processed" selected?={ data.Filter.Status == "processed" }>Processed</option>
								<option value="archived" selected?={ data.Filter.Status == "archived" }>Archived</option>
								<option value="deleted" selected?={ data.Filter.Status == "deleted" }>Deleted</option>
								<option value="archived_and_deleted" selected?={ data.Filter.Status == "archived_and_deleted" }>Archived & Deleted</option>
								<option value="error" selected?={ data.Filter.Status == "error" }>Error</option>
							</select>
						</div>
						<div>
							<label for="filename" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Filename</label>
							<input type="text" id="filename" name="filename" value={ data.Filter.FileName } placeholder="Filename or partial match" 
								class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" />
						</div>
						<div>
							<label for="hash" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">File Hash</label>
							<input type="text" id="hash" name="hash" value={ data.Filter.Hash } placeholder="MD5 hash" 
								class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" />
						</div>
						<div>
							<label for="start_date" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Processed After</label>
							<input type="date" id="start_date" name="start_date" value={ data.Filter.StartDate } 
								class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" />
						</div>
						<div>
							<label for="end_date" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Processed Before</label>
							<input type="date" id="end_date" name="end_date" value={ data.Filter.EndDate } 
								class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" />
						</div>
						<div class="md:col-span-2 flex justify-end">
							<button type="submit" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800">
								<i class="fas fa-search mr-2"></i> Search Files
							</button>
							<div id="search-form-loading" class="htmx-indicator ml-2 flex items-center">
								<i class="fas fa-circle-notch fa-spin text-blue-600"></i>
							</div>
						</div>
					</form>
				</div>
				
				<!-- Results -->
				<div class="bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700 w-full">
					<div class="flex items-center justify-between p-4 border-b border-gray-200 dark:border-gray-600">
						<h5 class="text-lg font-semibold text-gray-900 dark:text-white">Search Results ({ strconv.FormatInt(data.TotalCount, 10) })</h5>
						<span class="text-sm text-gray-500 dark:text-gray-400">
							Page { strconv.Itoa(data.Page) } of { strconv.Itoa(data.TotalPages) }
						</span>
					</div>
					<div id="search-results-container" class="w-full">
						@FileMetadataSearchContent(data)
					</div>
				</div>
			</div>

			<script>
				// Set dark background color if in dark mode
				if (document.documentElement.classList.contains('dark')) {
					document.getElementById('file-search-container').style.backgroundColor = '#111827';
				}
				
				// Add event listener for theme changes
				document.addEventListener('DOMContentLoaded', function() {
					const themeToggle = document.getElementById('theme-toggle');
					if (themeToggle) {
						themeToggle.addEventListener('click', function() {
							setTimeout(function() {
								const isDark = document.documentElement.classList.contains('dark');
								document.getElementById('file-search-container').style.backgroundColor = isDark ? '#111827' : 'rgb(249, 250, 251)';
							}, 50);
						});
					}
				});
			</script>
		</div>
	}
}

// Similarly, create a separate template for the search results
templ FileMetadataSearchContent(data FileMetadataSearchData) {
	<!-- Store file IDs for dialogs -->
	<div id="search-dialog-container">
		<!-- Dialogs will be rendered at the bottom of the container, outside the table -->
		for _, file := range data.Files {
			@FileMetadataDialog(
				fmt.Sprintf("delete-file-dialog-%d", file.ID),
				"Delete File Metadata",
				fmt.Sprintf("Are you sure you want to delete the metadata for '%s'? This cannot be undone.", file.FileName),
				"btn-danger",
				"Delete",
				"delete",
				file.ID,
				file.FileName,
				"list",
			)
		}
	</div>
	
	<div class="relative overflow-x-auto">
		<table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
			<thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
				<tr>
					<th scope="col" class="px-6 py-3">ID</th>
					<th scope="col" class="px-6 py-3">Filename</th>
					<th scope="col" class="px-6 py-3">Size</th>
					<th scope="col" class="px-6 py-3">Processed</th>
					<th scope="col" class="px-6 py-3">Status</th>
					<th scope="col" class="px-6 py-3">Job</th>
					<th scope="col" class="px-6 py-3">Actions</th>
				</tr>
			</thead>
			<tbody>
				if len(data.Files) > 0 {
					for _, file := range data.Files {
						<tr id={ fmt.Sprintf("file-row-%d", file.ID) } class="bg-white border-b dark:bg-gray-800 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600">
							<td class="px-6 py-4">{ strconv.FormatUint(uint64(file.ID), 10) }</td>
							<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white">
								<a href={ templ.SafeURL(fmt.Sprintf("/files/%d", file.ID)) } class="hover:underline">
									{ file.FileName }
								</a>
							</td>
							<td class="px-6 py-4">{ formatFileSize(file.FileSize) }</td>
							<td class="px-6 py-4">{ file.ProcessedTime.Format("2006-01-02 15:04:05") }</td>
							<td class="px-6 py-4">
								<span class={ "text-xs font-medium px-2.5 py-0.5 rounded", getStatusBadgeClass(file.Status) }>
									{ file.Status }
								</span>
							</td>
							<td class="px-6 py-4">
								if file.Job.ID > 0 {
									<a href={ templ.SafeURL(fmt.Sprintf("/files/job/%d", file.Job.ID)) } class="font-medium text-blue-600 dark:text-blue-500 hover:underline">
										{ file.Job.Name }
									</a>
								} else {
									<span class="text-gray-400 dark:text-gray-500 italic">N/A</span>
								}
							</td>
							<td class="px-6 py-4">
								<div class="flex space-x-3">
									<a href={ templ.SafeURL(fmt.Sprintf("/files/%d", file.ID)) } class="font-medium text-blue-600 dark:text-blue-500 hover:underline">
										<i class="fas fa-eye"></i>
									</a>
									<button 
										type="button"
										onclick={ showFileDialog(fmt.Sprintf("delete-file-dialog-%d", file.ID)) }
										class="font-medium text-red-600 dark:text-red-500 hover:underline">
										<i class="fas fa-trash"></i>
									</button>
								</div>
							</td>
						</tr>
					}
				} else {
					<tr>
						<td colspan="7" class="px-6 py-10 text-center text-gray-500 dark:text-gray-400">
							<svg class="mx-auto mb-4 w-12 h-12 text-gray-400" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
								<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" />
							</svg>
							<p>No files found matching your search criteria.</p>
						</td>
					</tr>
				}
			</tbody>
		</table>
	</div>
	
	<!-- Pagination for search results -->
	if data.TotalPages > 1 {
		<nav class="flex items-center flex-column flex-wrap md:flex-row justify-between p-4" aria-label="Table navigation">
			<span class="text-sm font-normal text-gray-500 dark:text-gray-400 mb-4 md:mb-0">
				Showing <span class="font-semibold text-gray-900 dark:text-white">{ strconv.Itoa((data.Page-1)*data.Limit+1) }-{ strconv.Itoa(func() int { 
					end := data.Page*data.Limit
					if int64(end) > data.TotalCount {
						return int(data.TotalCount)
					}
					return end
				}()) }</span> of <span class="font-semibold text-gray-900 dark:text-white">{ strconv.FormatInt(data.TotalCount, 10) }</span>
			</span>
			<ul class="inline-flex -space-x-px rtl:space-x-reverse text-sm h-8">
				<li>
					if data.Page == 1 {
						<span class="flex items-center justify-center px-3 h-8 ms-0 leading-tight text-gray-500 bg-white border border-gray-300 rounded-s-lg cursor-not-allowed dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400">
							Previous
						</span>
					} else {
						<a hx-get={ fmt.Sprintf("/files/search/partial?page=%d&limit=%d&status=%s&filename=%s&job_id=%s&hash=%s&start_date=%s&end_date=%s", data.Page - 1, data.Limit, data.Filter.Status, data.Filter.FileName, data.Filter.JobID, data.Filter.Hash, data.Filter.StartDate, data.Filter.EndDate) }
						   hx-target="#search-results-container"
						   hx-swap="innerHTML"
						   hx-headers='{"X-HX-Request": "true"}'
						   class="flex items-center justify-center px-3 h-8 ms-0 leading-tight text-gray-500 bg-white border border-gray-300 rounded-s-lg hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white">
							Previous
						</a>
					}
				</li>
				
				for i := 1; i <= data.TotalPages; i++ {
					// Always show first page, last page, and pages around current page
					if i == 1 || i == data.TotalPages || (i >= data.Page-2 && i <= data.Page+2) {
						<li>
							if i == data.Page {
								<span aria-current="page" class="flex items-center justify-center px-3 h-8 text-blue-600 border border-gray-300 bg-blue-50 hover:bg-blue-100 hover:text-blue-700 dark:border-gray-700 dark:bg-gray-700 dark:text-white">
									{ strconv.Itoa(i) }
								</span>
							} else {
								<a hx-get={ fmt.Sprintf("/files/search/partial?page=%d&limit=%d&status=%s&filename=%s&job_id=%s&hash=%s&start_date=%s&end_date=%s", i, data.Limit, data.Filter.Status, data.Filter.FileName, data.Filter.JobID, data.Filter.Hash, data.Filter.StartDate, data.Filter.EndDate) }
								   hx-target="#search-results-container"
								   hx-swap="innerHTML"
								   hx-headers='{"X-HX-Request": "true"}'
								   class="flex items-center justify-center px-3 h-8 leading-tight text-gray-500 bg-white border border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white">
									{ strconv.Itoa(i) }
								</a>
							}
						</li>
					} else if (i == 2 && data.Page > 4) || (i == data.TotalPages-1 && data.Page < data.TotalPages-3) {
						// Show ellipsis for gaps
						<li>
							<span class="flex items-center justify-center px-3 h-8 leading-tight text-gray-500 bg-white border border-gray-300 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400">
								...
							</span>
						</li>
					}
				}
				
				<li>
					if data.Page == data.TotalPages {
						<span class="flex items-center justify-center px-3 h-8 leading-tight text-gray-500 bg-white border border-gray-300 rounded-e-lg cursor-not-allowed dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400">
							Next
						</span>
					} else {
						<a hx-get={ fmt.Sprintf("/files/search/partial?page=%d&limit=%d&status=%s&filename=%s&job_id=%s&hash=%s&start_date=%s&end_date=%s", data.Page + 1, data.Limit, data.Filter.Status, data.Filter.FileName, data.Filter.JobID, data.Filter.Hash, data.Filter.StartDate, data.Filter.EndDate) }
						   hx-target="#search-results-container"
						   hx-swap="innerHTML"
						   hx-headers='{"X-HX-Request": "true"}'
						   class="flex items-center justify-center px-3 h-8 leading-tight text-gray-500 bg-white border border-gray-300 rounded-e-lg hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white">
							Next
						</a>
					}
				</li>
			</ul>
		</nav>
	}
}

