<script lang="ts">
	import Icon from "$lib/components/atoms/icon.svelte";
	import { Button, buttonVariants } from "$lib/components/ui/button";
	import * as Card from "$lib/components/ui/card";
	import { Checkbox } from "$lib/components/ui/checkbox";
	import * as DropdownMenu from "$lib/components/ui/dropdown-menu";
	import { Input } from "$lib/components/ui/input";
	import * as Table from "$lib/components/ui/table";
	import { cn } from "$lib/utils";
	import {
		AlertCircle,
		Archive,
		Bell,
		Check,
		CheckCircle,
		ChevronLeft,
		ChevronRight,
		Clock,
		Info,
		ListFilter,
		Loader2,
		MoreHorizontal,
		Search,
		Trash2,
	} from "@lucide/svelte";
	import { onMount } from "svelte";
	import { notificationViewModel } from "./notification.vm.svelte";

	onMount(() => {
		setTimeout(() => {
			notificationViewModel.fetchNotifications();
			notificationViewModel.fetchUnreadCount();
		}, 500);
	});

	function getPriorityColor(priority: string) {
		switch (priority.toLowerCase()) {
			case "high":
				return "text-red-600 bg-red-50";
			case "medium":
				return "text-yellow-600 bg-yellow-50";
			case "low":
				return "text-emerald-600 dark:text-emerald-400 bg-green-50";
			default:
				return "text-gray-600 bg-gray-50";
		}
	}

	function getTypeIcon(type: string) {
		switch (type.toLowerCase()) {
			case "info":
				return Info;
			case "warning":
				return AlertCircle;
			case "success":
				return CheckCircle;
			case "error":
				return AlertCircle;
			default:
				return Bell;
		}
	}

	function formatRelativeTime(date: Date): string {
		const now = new Date();
		const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);

		if (diffInSeconds < 60) {
			return "just now";
		} else if (diffInSeconds < 3600) {
			const minutes = Math.floor(diffInSeconds / 60);
			return `${minutes} minute${minutes > 1 ? "s" : ""} ago`;
		} else if (diffInSeconds < 86400) {
			const hours = Math.floor(diffInSeconds / 3600);
			return `${hours} hour${hours > 1 ? "s" : ""} ago`;
		} else {
			const days = Math.floor(diffInSeconds / 86400);
			return `${days} day${days > 1 ? "s" : ""} ago`;
		}
	}

	function handleSelectAll(checked: boolean) {
		if (checked) {
			notificationViewModel.selectAll();
		} else {
			notificationViewModel.clearSelection();
		}
	}

	function handleRowSelect(notificationId: number, checked: boolean) {
		notificationViewModel.toggleSelection(notificationId);
	}

	async function handleBulkMarkAsRead() {
		if (notificationViewModel.selectedIds.size > 0) {
			await notificationViewModel.markAsRead(
				Array.from(notificationViewModel.selectedIds),
			);
			notificationViewModel.clearSelection();
		}
	}

	async function handleBulkMarkAsUnread() {
		if (notificationViewModel.selectedIds.size > 0) {
			await notificationViewModel.markAsUnread(
				Array.from(notificationViewModel.selectedIds),
			);
			notificationViewModel.clearSelection();
		}
	}

	async function handleBulkArchive() {
		if (notificationViewModel.selectedIds.size > 0) {
			await notificationViewModel.archive(
				Array.from(notificationViewModel.selectedIds),
			);
			notificationViewModel.clearSelection();
		}
	}

	async function handleBulkDelete() {
		if (notificationViewModel.selectedIds.size > 0) {
			await notificationViewModel.deleteNotifications(
				Array.from(notificationViewModel.selectedIds),
			);
			notificationViewModel.clearSelection();
		}
	}

	async function handleSingleAction(notificationId: number, action: string) {
		switch (action) {
			case "mark-read":
				await notificationViewModel.markAsRead([notificationId]);
				break;
			case "mark-unread":
				await notificationViewModel.markAsUnread([notificationId]);
				break;
			case "archive":
				await notificationViewModel.archive([notificationId]);
				break;
			case "delete":
				await notificationViewModel.deleteNotifications([notificationId]);
				break;
		}
	}

	function handleSearch(event: Event) {
		const target = event.target as HTMLInputElement;
		const searchTerm = target.value;

		notificationViewModel.setFilters({ search: searchTerm || undefined });
	}

	function handleFilterChange(key: string, value: any) {
		notificationViewModel.setFilters({ [key]: value });
	}

	// Reactive computed values
	let isAllSelected = $derived(
		notificationViewModel.notifications.length > 0 &&
			notificationViewModel.notifications.every((n) =>
				notificationViewModel.selectedIds.has(n.id),
			),
	);

	let isIndeterminate = $derived(
		notificationViewModel.selectedIds.size > 0 && !isAllSelected,
	);

	let hasSelection = $derived(notificationViewModel.selectedIds.size > 0);
</script>

<Card.Root>
	<Card.Header>
		<div class="flex items-center justify-between">
			<div class="flex items-center gap-2">
				<Icon icon={Bell} cls="h-5 w-5 text-primary" />
				<Card.Title>Notifications</Card.Title>
				{#if notificationViewModel.unreadCount > 0}
					<span
						class="bg-primary text-primary-foreground rounded-full px-2 py-0.5 text-xs font-medium"
					>
						{notificationViewModel.unreadCount} unread
					</span>
				{/if}
			</div>

			{#if hasSelection}
				<div class="flex items-center gap-2">
					<span class="text-muted-foreground text-sm">
						{notificationViewModel.selectedIds.size} selected
					</span>
					<Button
						variant="outline"
						size="sm"
						onclick={handleBulkMarkAsRead}
					>
						<Icon icon={Check} cls="h-4 w-4 mr-2" />
						Mark as Read
					</Button>
					<Button
						variant="outline"
						size="sm"
						onclick={handleBulkArchive}
					>
						<Icon icon={Archive} cls="h-4 w-4 mr-2" />
						Archive
					</Button>
					<Button
						variant="outline"
						size="sm"
						onclick={handleBulkDelete}
					>
						<Icon icon={Trash2} cls="h-4 w-4 mr-2" />
						Delete
					</Button>
				</div>
			{:else}
				<Button
					variant="outline"
					size="sm"
					onclick={() => notificationViewModel.markAllAsRead()}
					disabled={notificationViewModel.unreadCount === 0}
				>
					Mark All as Read
				</Button>
			{/if}
		</div>

		<div
			class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between"
		>
			<!-- Search -->
			<div class="relative max-w-sm flex-1">
				<Icon
					icon={Search}
					cls="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground"
				/>
				<Input
					placeholder="Search notifications..."
					class="pl-10"
					value={notificationViewModel.filters.search || ""}
					oninput={handleSearch}
				/>
			</div>

			<!-- Filters -->
			<div class="flex items-center gap-2">
				<DropdownMenu.Root>
					<DropdownMenu.Trigger
						class={buttonVariants({ variant: "outline", size: "sm" })}
					>
						<Icon icon={ListFilter} cls="h-4 w-4 mr-2" />
						Filters
					</DropdownMenu.Trigger>
					<DropdownMenu.Content>
						<DropdownMenu.Item
							onclick={() =>
								handleFilterChange("isRead", undefined)}
						>
							All
						</DropdownMenu.Item>
						<DropdownMenu.Item
							onclick={() => handleFilterChange("isRead", false)}
						>
							Unread Only
						</DropdownMenu.Item>
						<DropdownMenu.Item
							onclick={() => handleFilterChange("isRead", true)}
						>
							Read Only
						</DropdownMenu.Item>
						<DropdownMenu.Separator />
						<DropdownMenu.Item
							onclick={() =>
								handleFilterChange("isArchived", false)}
						>
							Active
						</DropdownMenu.Item>
						<DropdownMenu.Item
							onclick={() => handleFilterChange("isArchived", true)}
						>
							Archived
						</DropdownMenu.Item>
					</DropdownMenu.Content>
				</DropdownMenu.Root>
			</div>
		</div>
	</Card.Header>

	<Card.Content>
		{#if notificationViewModel.loading && notificationViewModel.notifications.length === 0}
			<div class="flex justify-center py-8">
				<Icon
					icon={Loader2}
					cls="h-8 w-8 animate-spin text-muted-foreground"
				/>
			</div>
		{:else if notificationViewModel.notifications.length === 0}
			<div class="py-8 text-center">
				<Icon
					icon={Bell}
					cls="h-12 w-12 text-muted-foreground mx-auto mb-4"
				/>
				<h3 class="mb-2 text-lg font-medium">No notifications</h3>
				<p class="text-muted-foreground">
					{notificationViewModel.filters.search
						? "No notifications match your search."
						: "You're all caught up!"}
				</p>
			</div>
		{:else}
			<div class="space-y-4">
				<!-- Table -->
				<Table.Root>
					<Table.Header>
						<Table.Row>
							<Table.Head class="w-12">
								<Checkbox
									checked={isAllSelected}
									indeterminate={isIndeterminate}
									onCheckedChange={handleSelectAll}
								/>
							</Table.Head>
							<Table.Head class="w-12"></Table.Head>
							<Table.Head>Notification</Table.Head>
							<Table.Head class="w-24">Priority</Table.Head>
							<Table.Head class="w-32">Time</Table.Head>
							<Table.Head class="w-12"></Table.Head>
						</Table.Row>
					</Table.Header>
					<Table.Body>
						{#each notificationViewModel.notifications as notification (notification.id)}
							<Table.Row
								class={cn(
									"hover:bg-muted/50 cursor-pointer",
									!notification.isRead &&
										"bg-primary/5 border-l-primary border-l-4",
								)}
							>
								<Table.Cell>
									<Checkbox
										checked={notificationViewModel.selectedIds.has(
											notification.id,
										)}
										onCheckedChange={(checked: boolean) =>
											handleRowSelect(
												notification.id,
												checked,
											)}
									/>
								</Table.Cell>
								<Table.Cell>
									<div
										class={cn(
											"rounded-full p-2",
											notification.isRead
												? "bg-muted"
												: "bg-primary/10",
										)}
									>
										<Icon
											icon={getTypeIcon(notification.type)}
											cls={cn(
												"h-4 w-4",
												notification.isRead
													? "text-muted-foreground"
													: "text-primary",
											)}
										/>
									</div>
								</Table.Cell>
								<Table.Cell>
									<div class="space-y-1">
										<p
											class={cn(
												"font-medium",
												notification.isRead
													? "text-muted-foreground"
													: "text-foreground",
											)}
										>
											{notification.title}
										</p>
										<p
											class="text-muted-foreground line-clamp-2 text-sm"
										>
											{notification.body}
										</p>
										{#if notification.category}
											<span
												class="bg-secondary text-secondary-foreground inline-flex items-center rounded-full px-2 py-1 text-xs font-medium"
											>
												{notification.category}
											</span>
										{/if}
									</div>
								</Table.Cell>
								<Table.Cell>
									<span
										class={cn(
											"inline-flex items-center rounded-full px-2 py-1 text-xs font-medium",
											getPriorityColor(
												notification.priority,
											),
										)}
									>
										{notification.priority}
									</span>
								</Table.Cell>
								<Table.Cell>
									<div
										class="text-muted-foreground flex items-center gap-1 text-sm"
									>
										<Icon icon={Clock} cls="h-3 w-3" />
										<span
											>{formatRelativeTime(
												notification.sentAt,
											)}</span
										>
									</div>
								</Table.Cell>
								<Table.Cell>
									<DropdownMenu.Root>
										<DropdownMenu.Trigger
											class={buttonVariants({
												variant: "ghost",
												size: "sm",
											})}
										>
											<Icon
												icon={MoreHorizontal}
												cls="h-4 w-4"
											/>
										</DropdownMenu.Trigger>
										<DropdownMenu.Content>
											{#if notification.isRead}
												<DropdownMenu.Item
													onclick={() =>
														handleSingleAction(
															notification.id,
															"mark-unread",
														)}
												>
													Mark as Unread
												</DropdownMenu.Item>
											{:else}
												<DropdownMenu.Item
													onclick={() =>
														handleSingleAction(
															notification.id,
															"mark-read",
														)}
												>
													Mark as Read
												</DropdownMenu.Item>
											{/if}
											<DropdownMenu.Item
												onclick={() =>
													handleSingleAction(
														notification.id,
														"archive",
													)}
											>
												Archive
											</DropdownMenu.Item>
											<DropdownMenu.Separator />
											<DropdownMenu.Item
												onclick={() =>
													handleSingleAction(
														notification.id,
														"delete",
													)}
												class="text-destructive"
											>
												Delete
											</DropdownMenu.Item>
										</DropdownMenu.Content>
									</DropdownMenu.Root>
								</Table.Cell>
							</Table.Row>
						{/each}
					</Table.Body>
				</Table.Root>

				<!-- Pagination -->
				{#if notificationViewModel.pagination.totalPages > 1}
					<div class="flex items-center justify-between">
						<div class="text-muted-foreground text-sm">
							Showing {(notificationViewModel.pagination.page - 1) *
								notificationViewModel.pagination.pageSize +
								1} to {Math.min(
								notificationViewModel.pagination.page *
									notificationViewModel.pagination.pageSize,
								notificationViewModel.pagination.total,
							)} of {notificationViewModel.pagination.total} notifications
						</div>

						<div class="flex items-center space-x-2">
							<Button
								variant="outline"
								size="sm"
								onclick={() =>
									notificationViewModel.goToPage(
										notificationViewModel.pagination.page - 1,
									)}
								disabled={notificationViewModel.pagination
									.page === 1}
							>
								<Icon icon={ChevronLeft} cls="h-4 w-4" />
								Previous
							</Button>

							<div class="flex items-center space-x-1">
								{#each Array.from( { length: Math.min(5, notificationViewModel.pagination.totalPages) }, (_, i) => {
										const startPage = Math.max(1, notificationViewModel.pagination.page - 2);
										return startPage + i;
									}, ) as page}
									{#if page <= notificationViewModel.pagination.totalPages}
										<Button
											variant={page ===
											notificationViewModel.pagination.page
												? "default"
												: "outline"}
											size="sm"
											onclick={() =>
												notificationViewModel.goToPage(
													page,
												)}
										>
											{page}
										</Button>
									{/if}
								{/each}
							</div>

							<Button
								variant="outline"
								size="sm"
								onclick={() =>
									notificationViewModel.goToPage(
										notificationViewModel.pagination.page + 1,
									)}
								disabled={notificationViewModel.pagination
									.page ===
									notificationViewModel.pagination.totalPages}
							>
								Next
								<Icon icon={ChevronRight} cls="h-4 w-4" />
							</Button>
						</div>
					</div>
				{/if}
			</div>
		{/if}
	</Card.Content>
</Card.Root>

<style>
	.line-clamp-2 {
		display: -webkit-box;
		-webkit-line-clamp: 2;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}
</style>
