<script lang="ts">
	import { toast } from 'svelte-sonner';
	import { getContext, onDestroy, onMount, tick } from 'svelte';
	const i18n = getContext('i18n');

	import Modal from '$lib/components/common/Modal.svelte';
	import SearchInput from './Sidebar/SearchInput.svelte';
	import {
		getChatById,
		getChatList,
		getChatListBySearchText,
		searchMessages,
		reindexUserChats,
		type MessageSearchResult
	} from '$lib/apis/chats';
	import Spinner from '../common/Spinner.svelte';

	import dayjs from '$lib/dayjs';
	import calendar from 'dayjs/plugin/calendar';
	import Loader from '../common/Loader.svelte';
	import { createMessagesList } from '$lib/utils';
	import { config, user } from '$lib/stores';
	import Messages from '../chat/Messages.svelte';
	import { goto } from '$app/navigation';
	import PencilSquare from '../icons/PencilSquare.svelte';
	import PageEdit from '../icons/PageEdit.svelte';
	dayjs.extend(calendar);

	export let show = false;
	export let onClose = () => {};

	let actions = [
		{
			label: $i18n.t('Start a new conversation'),
			onClick: async () => {
				await goto(`/${query ? `?q=${query}` : ''}`);
				show = false;
				onClose();
			},
			icon: PencilSquare
		}
	];

	let query = '';
	let page = 1;

	let searchType = 'message'; // 'message' or 'chat' - default to message

	let chatList = null;
	let messageSearchResponse: SearchResponse | null = null;

	let chatListLoading = false;
	let allChatsLoaded = false;

	let searchDebounceTimeout;

	let selectedIdx = null;
	let selectedChat = null;

	let selectedModels = [''];
	let history = null;
	let messages = null;

	// Search controls
	let searchMode = 'smart'; // 'smart', 'exact', 'advanced'
	let sortBy = 'relevance'; // 'relevance', 'date'
	let groupByConversation = false;
	let showFilters = false;
	let showPreview = false; // Preview toggle - default off
	
	// Filters
	let dateFilter = 'all'; // 'all', 'today', 'week', 'month', 'custom'
	let roleFilter = 'all'; // 'all', 'user', 'assistant'
	let selectedTags = [];
	let selectedFolder = null;

	// Reindex state
	let isReindexing = false;
	let reindexProgress = { indexed: 0, total: 0 };

	// Pagination for message results
	let messageResultsPage = 1;
	const RESULTS_PER_PAGE = 10;
	$: displayedMessageResults = messageSearchResponse?.hits.slice(0, messageResultsPage * RESULTS_PER_PAGE) || [];
	$: hasMoreResults = messageSearchResponse && displayedMessageResults.length < messageSearchResponse.hits.length;

	$: if (!chatListLoading && chatList) {
		loadChatPreview(selectedIdx);
	}

	const loadChatPreview = async (selectedIdx) => {
		if (!chatList || chatList.length === 0 || selectedIdx === null) {
			selectedChat = null;
			messages = null;
			history = null;
			selectedModels = [''];
			return;
		}

		const selectedChatIdx = selectedIdx - actions.length;
		if (selectedChatIdx < 0 || selectedChatIdx >= chatList.length) {
			selectedChat = null;
			messages = null;
			history = null;
			selectedModels = [''];
			return;
		}

		const chatId = chatList[selectedChatIdx].id;

		const chat = await getChatById(localStorage.token, chatId).catch(async (error) => {
			return null;
		});

		if (chat) {
			if (chat?.chat?.history) {
				selectedModels =
					(chat?.chat?.models ?? undefined) !== undefined
						? chat?.chat?.models
						: [chat?.chat?.models ?? ''];

				history = chat?.chat?.history;
				messages = createMessagesList(chat?.chat?.history, chat?.chat?.history?.currentId);

				// scroll to the bottom of the messages container
				await tick();
				const messagesContainerElement = document.getElementById('chat-preview');
				if (messagesContainerElement) {
					messagesContainerElement.scrollTop = messagesContainerElement.scrollHeight;
				}
			} else {
				messages = [];
			}
		} else {
			toast.error($i18n.t('Failed to load chat preview'));
			selectedChat = null;
			messages = null;
			history = null;
			selectedModels = [''];
			return;
		}
	};

	const loadMessageChatPreview = async (chatId, messageId) => {
		const chat = await getChatById(localStorage.token, chatId).catch(async (error) => {
			return null;
		});

		if (chat) {
			if (chat?.chat?.history) {
				selectedModels =
					(chat?.chat?.models ?? undefined) !== undefined
						? chat?.chat?.models
						: [chat?.chat?.models ?? ''];

				selectedChat = chat;
				
				// Find the leaf of the branch containing the message
				let leafId = messageId;
				const messagesDict = chat.chat.history.messages;
				while (messagesDict[leafId]?.childrenIds?.length > 0) {
					leafId = messagesDict[leafId].childrenIds.at(-1);
				}

				history = {
					...chat.chat.history,
					currentId: leafId
				};
				messages = createMessagesList(history, leafId);

				// Scroll to the target message
				await tick();
				const messagesContainerElement = document.getElementById('chat-preview');
				if (messagesContainerElement) {
					// Try to find and scroll to the specific message
					setTimeout(() => {
						const messageElement = messagesContainerElement.querySelector(`#message-${messageId}`);
						if (messageElement) {
							messageElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
						} else {
							messagesContainerElement.scrollTop = messagesContainerElement.scrollHeight;
						}
					}, 100);
				}
			} else {
				messages = [];
			}
		}
	};

	const searchHandler = async () => {
		if (!show) {
			return;
		}

		if (searchDebounceTimeout) {
			clearTimeout(searchDebounceTimeout);
		}

		page = 1;
		chatList = null;
		messageSearchResponse = null;
		chatListLoading = true;

		if (query === '') {
			if (searchType === 'chat') {
				chatList = await getChatList(localStorage.token, page);
			} else {
				// For message search with empty query, just show empty state
				messageSearchResponse = { hits: [], totalHits: 0, processingTimeMs: 0, page: 1, limit: 60, query: '' };
			}
			chatListLoading = false;
		} else {
			if (searchDebounceTimeout) {
				clearTimeout(searchDebounceTimeout);
			}

			searchDebounceTimeout = setTimeout(async () => {
				if (searchType === 'chat') {
					chatList = await getChatListBySearchText(localStorage.token, query, page);
				} else {
					// Reset pagination
					messageResultsPage = 1;

					// Build filter parameters
					let filters = {};
					if (roleFilter !== 'all') {
						filters.role = roleFilter;
					}
					if (dateFilter !== 'all') {
						const now = Math.floor(Date.now() / 1000);
						const dayInSeconds = 86400;
						let timestampFilter;
						if (dateFilter === 'today') {
							timestampFilter = now - dayInSeconds;
						} else if (dateFilter === 'week') {
							timestampFilter = now - (7 * dayInSeconds);
						} else if (dateFilter === 'month') {
							timestampFilter = now - (30 * dayInSeconds);
						}
						if (timestampFilter) {
							filters.timestamp = Math.floor(timestampFilter);
						}
					}
					if (selectedTags.length > 0) {
						filters.tags = selectedTags;
					}
					if (selectedFolder) {
						filters.folderId = selectedFolder;
					}

					// Modify query for exact match mode
					let searchQuery = query;
					if (searchMode === 'exact') {
						searchQuery = `"${query}"`;
					}

					// Fetch ALL results from backend
					messageSearchResponse = await searchMessages(
						localStorage.token,
						searchQuery,
						page,
						sortBy,
						filters
					).catch((e) => {
						console.error('Message search failed:', e);
						return null;
					});
				}

				if ((chatList ?? []).length === 0) {
					allChatsLoaded = true;
				} else {
					allChatsLoaded = false;
				}
				chatListLoading = false;
			}, 300);
		}

		selectedChat = null;
		messages = null;
		history = null;
		selectedModels = [''];

		if ((chatList ?? []).length === 0) {
			allChatsLoaded = true;
		} else {
			allChatsLoaded = false;
		}
	};

	const loadMoreChats = async () => {
		chatListLoading = true;
		page += 1;

		let newChatList = [];

		if (query) {
			newChatList = await getChatListBySearchText(localStorage.token, query, page);
		} else {
			newChatList = await getChatList(localStorage.token, page);
		}

		// once the bottom of the list has been reached (no results) there is no need to continue querying
		allChatsLoaded = newChatList.length === 0;

		if (newChatList.length > 0) {
			chatList = [...chatList, ...newChatList];
		}

		chatListLoading = false;
	};

	$: if (show) {
		searchHandler();
	}

	const onKeyDown = (e) => {
		const searchOptions = document.getElementById('search-options-container');
		if (searchOptions || !show) {
			return;
		}

		if (e.code === 'Escape') {
			show = false;
			onClose();
		} else if (e.code === 'Enter') {
			const item = document.querySelector(`[data-arrow-selected="true"]`);
			if (item) {
				item?.click();
				show = false;
			}

			return;
		} else if (e.code === 'ArrowDown') {
			const searchInput = document.getElementById('search-input');

			if (searchInput) {
				// check if focused on the search input
				if (document.activeElement === searchInput) {
					searchInput.blur();
					selectedIdx = 0;
					return;
				}
			}

			selectedIdx = Math.min(selectedIdx + 1, (chatList ?? []).length - 1 + actions.length);
		} else if (e.code === 'ArrowUp') {
			if (selectedIdx === 0) {
				const searchInput = document.getElementById('search-input');

				if (searchInput) {
					// check if focused on the search input
					if (document.activeElement !== searchInput) {
						searchInput.focus();
						selectedIdx = 0;
						return;
					}
				}
			}

			selectedIdx = Math.max(selectedIdx - 1, 0);
		}

		const item = document.querySelector(`[data-arrow-selected="true"]`);
		item?.scrollIntoView({ block: 'center', inline: 'nearest', behavior: 'instant' });
	};

	onMount(() => {
		actions = [
			...actions,
			...(($config?.features?.enable_notes ?? false) &&
			($user?.role === 'admin' || ($user?.permissions?.features?.notes ?? true))
				? [
						{
							label: $i18n.t('Create a new note'),
							onClick: async () => {
								await goto(`/notes?content=${query}`);
								show = false;
								onClose();
							},
							icon: PageEdit
						}
					]
				: [])
		];

		document.addEventListener('keydown', onKeyDown);
	});

	onDestroy(() => {
		if (searchDebounceTimeout) {
			clearTimeout(searchDebounceTimeout);
		}
		document.removeEventListener('keydown', onKeyDown);
	});

	const handleReindex = async () => {
		isReindexing = true;
		reindexProgress = { indexed: 0, total: 0 };

		try {
			const result = await reindexUserChats(localStorage.token);
			reindexProgress = result;
			toast.success($i18n.t(`Re-indexed ${result.indexed} out of ${result.total} chats successfully`));
			
			// Refresh search results
			await searchHandler();
		} catch (e) {
			toast.error($i18n.t('Failed to re-index chats: {{error}}', { error: e.message || e }));
		} finally {
			isReindexing = false;
		}
	};
</script>

<Modal size="xl" bind:show>
	<div class="py-3 dark:text-gray-300 text-gray-700">
		<div class="px-4 pb-1.5">
			<div class="flex items-center justify-center mb-2 text-sm">
				<button
					class="px-3 py-1 rounded-l-lg {searchType === 'message'
						? 'bg-gray-200 dark:bg-gray-700'
						: 'bg-gray-100 dark:bg-gray-800'}"
					on:click={() => {
						searchType = 'message';
						searchHandler();
					}}
				>
					{$i18n.t('Messages')}
				</button>
				<button
					class="px-3 py-1 rounded-r-lg {searchType === 'chat'
						? 'bg-gray-200 dark:bg-gray-700'
						: 'bg-gray-100 dark:bg-gray-800'}"
					on:click={() => {
						searchType = 'chat';
						searchHandler();
					}}
				>
					{$i18n.t('Chats')}
				</button>
			</div>

			{#if searchType === 'message'}
				<!-- Compact filter controls -->
				<div class="flex items-center gap-2 mb-2 text-xs flex-wrap">
					<!-- Search Mode Toggle -->
					<div class="flex rounded-md overflow-hidden border border-gray-200 dark:border-gray-700">
						<button
							class="px-2 py-1 {searchMode === 'smart'
								? 'bg-blue-500 text-white'
								: 'bg-gray-50 dark:bg-gray-800'}"
							on:click={() => {
								searchMode = 'smart';
								searchHandler();
							}}
						>
							Smart
						</button>
						<button
							class="px-2 py-1 {searchMode === 'exact'
								? 'bg-blue-500 text-white'
								: 'bg-gray-50 dark:bg-gray-800'}"
							on:click={() => {
								searchMode = 'exact';
								searchHandler();
							}}
						>
							Exact
						</button>
					</div>

					<!-- Sort Toggle -->
					<div class="flex rounded-md overflow-hidden border border-gray-200 dark:border-gray-700">
						<button
							class="px-2 py-1 {sortBy === 'relevance'
								? 'bg-blue-500 text-white'
								: 'bg-gray-50 dark:bg-gray-800'}"
							on:click={() => {
								sortBy = 'relevance';
								searchHandler();
							}}
						>
							Relevance
						</button>
						<button
							class="px-2 py-1 {sortBy === 'date'
								? 'bg-blue-500 text-white'
								: 'bg-gray-50 dark:bg-gray-800'}"
							on:click={() => {
								sortBy = 'date';
								searchHandler();
							}}
						>
							Date
						</button>
					</div>

					<!-- Group Toggle -->
					<button
						class="px-2 py-1 rounded-md border border-gray-200 dark:border-gray-700 {groupByConversation
							? 'bg-blue-500 text-white'
							: 'bg-gray-50 dark:bg-gray-800'}"
						on:click={() => {
							groupByConversation = !groupByConversation;
						}}
					>
						Group
					</button>

					<!-- Filters Toggle -->
					<button
						class="px-2 py-1 rounded-md border border-gray-200 dark:border-gray-700 {showFilters
							? 'bg-blue-500 text-white'
							: 'bg-gray-50 dark:bg-gray-800'}"
						on:click={() => {
							showFilters = !showFilters;
						}}
					>
						Filters {showFilters ? '▼' : '▶'}
					</button>

					<!-- Preview Toggle -->
					<button
						class="px-2 py-1 rounded-md border border-gray-200 dark:border-gray-700 {showPreview
							? 'bg-blue-500 text-white'
							: 'bg-gray-50 dark:bg-gray-800'}"
						on:click={() => {
							showPreview = !showPreview;
						}}
					>
						Preview
					</button>

					<!-- Reindex Button -->
					<button
						class="px-2 py-1 rounded-md border border-gray-200 dark:border-gray-700 bg-orange-500 text-white hover:bg-orange-600 disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-1"
						on:click={handleReindex}
						disabled={isReindexing}
						title="Re-index all your chats to update search"
					>
						{#if isReindexing}
							<Spinner className="size-3" />
							{reindexProgress.indexed}/{reindexProgress.total}
						{:else}
							⟳ Re-index
						{/if}
					</button>
				</div>

				{#if showFilters}
					<div class="p-2 bg-gray-50 dark:bg-gray-850 rounded-md mb-2 text-xs space-y-2">
						<!-- Date Filter -->
						<div class="flex items-center gap-2">
							<label class="text-gray-600 dark:text-gray-400 min-w-[60px]">Date:</label>
							<select
								bind:value={dateFilter}
								on:change={searchHandler}
								class="flex-1 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded px-2 py-1"
							>
								<option value="all">All Time</option>
								<option value="today">Today</option>
								<option value="week">Last 7 Days</option>
								<option value="month">Last 30 Days</option>
							</select>
						</div>

						<!-- Role Filter -->
						<div class="flex items-center gap-2">
							<label class="text-gray-600 dark:text-gray-400 min-w-[60px]">Role:</label>
							<select
								bind:value={roleFilter}
								on:change={searchHandler}
								class="flex-1 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded px-2 py-1"
							>
								<option value="all">All Messages</option>
								<option value="user">User Only</option>
								<option value="assistant">AI Only</option>
							</select>
						</div>
					</div>
				{/if}
			{/if}

			<SearchInput
				bind:value={query}
				on:input={searchHandler}
				placeholder={$i18n.t('Search')}
				showClearButton={true}
				onFocus={() => {
					selectedIdx = null;
					messages = null;
				}}
				onKeydown={(e) => {
					console.log('e', e);

					if (e.code === 'Enter' && (chatList ?? []).length > 0) {
						const item = document.querySelector(`[data-arrow-selected="true"]`);
						if (item) {
							item?.click();
						}

						show = false;
						return;
					} else if (e.code === 'ArrowDown') {
						selectedIdx = Math.min(selectedIdx + 1, (chatList ?? []).length - 1 + actions.length);
					} else if (e.code === 'ArrowUp') {
						selectedIdx = Math.max(selectedIdx - 1, 0);
					} else {
						selectedIdx = 0;
					}

					const item = document.querySelector(`[data-arrow-selected="true"]`);
					item?.scrollIntoView({ block: 'center', inline: 'nearest', behavior: 'instant' });
				}}
			/>
		</div>

		<!-- <hr class="border-gray-50 dark:border-gray-850 my-1" /> -->

		<div class="flex px-4 pb-1">
			<div
				class="flex flex-col overflow-y-auto h-96 md:h-[40rem] max-h-full scrollbar-hidden w-full flex-1 pr-2"
			>
				<div class="w-full text-xs text-gray-500 dark:text-gray-500 font-medium pb-2 px-2">
					{$i18n.t('Actions')}
				</div>

				{#each actions as action, idx (action.label)}
					<button
						class=" w-full flex items-center rounded-xl text-sm py-2 px-3 hover:bg-gray-50 dark:hover:bg-gray-850 {selectedIdx ===
						idx
							? 'bg-gray-50 dark:bg-gray-850'
							: ''}"
						data-arrow-selected={selectedIdx === idx ? 'true' : undefined}
						dragabble="false"
						on:mouseenter={() => {
							selectedIdx = idx;
						}}
						on:click={async () => {
							await action.onClick();
						}}
					>
						<div class="pr-2">
							<svelte:component this={action.icon} />
						</div>
						<div class=" flex-1 text-left">
							<div class="text-ellipsis line-clamp-1 w-full">
								{$i18n.t(action.label)}
							</div>
						</div>
					</button>
				{/each}

				{#if searchType === 'chat'}
					{#if chatList}
						<hr class="border-gray-50 dark:border-gray-850 my-3" />

						{#if chatList.length === 0}
							<div class="text-xs text-gray-500 dark:text-gray-400 text-center px-5 py-4">
								{$i18n.t('No results found')}
							</div>
						{/if}

						{#each chatList as chat, idx (chat.id)}
						{#if idx === 0 || (idx > 0 && chat.time_range !== chatList[idx - 1].time_range)}
							<div
								class="w-full text-xs text-gray-500 dark:text-gray-500 font-medium {idx === 0
									? ''
									: 'pt-5'} pb-2 px-2"
							>
								{$i18n.t(chat.time_range)}
								<!-- localisation keys for time_range to be recognized from the i18next parser (so they don't get automatically removed):
							{$i18n.t('Today')}
							{$i18n.t('Yesterday')}
							{$i18n.t('Previous 7 days')}
							{$i18n.t('Previous 30 days')}
							{$i18n.t('January')}
							{$i18n.t('February')}
							{$i18n.t('March')}
							{$i18n.t('April')}
							{$i18n.t('May')}
							{$i18n.t('June')}
							{$i18n.t('July')}
							{$i18n.t('August')}
							{$i18n.t('September')}
							{$i18n.t('October')}
							{$i18n.t('November')}
							{$i18n.t('December')}
							-->
							</div>
						{/if}

							<a
								class=" w-full flex justify-between items-center rounded-xl text-sm py-2 px-3 hover:bg-gray-50 dark:hover:bg-gray-850 {selectedIdx ===
								idx + actions.length
									? 'bg-gray-50 dark:bg-gray-850'
									: ''}"
								href="/c/{chat.id}"
								draggable="false"
								data-arrow-selected={selectedIdx === idx + actions.length ? 'true' : undefined}
								on:mouseenter={() => {
									selectedIdx = idx + actions.length;
								}}
								on:click={async () => {
									await goto(`/c/${chat.id}`);
									show = false;
									onClose();
								}}
							>
								<div class=" flex-1">
									<div class="text-ellipsis line-clamp-1 w-full">
										{chat?.title}
									</div>
								</div>

								<div class=" pl-3 shrink-0 text-gray-500 dark:text-gray-400 text-xs">
									{dayjs(chat?.updated_at * 1000).calendar()}
								</div>
							</a>
						{/each}

						{#if !allChatsLoaded}
							<Loader
								on:visible={(e) => {
									if (!chatListLoading) {
										loadMoreChats();
									}
								}}
							>
								<div
									class="w-full flex justify-center py-4 text-xs animate-pulse items-center gap-2"
								>
									<Spinner className=" size-4" />
									<div class=" ">{$i18n.t('Loading...')}</div>
								</div>
							</Loader>
						{/if}
					{:else}
						<div class="w-full h-full flex justify-center items-center">
							<Spinner className="size-5" />
						</div>
					{/if}
				{:else if searchType === 'message'}
					{#if messageSearchResponse}
						<hr class="border-gray-50 dark:border-gray-850 my-3" />
						
						{#if messageSearchResponse.hits.length === 0}
							<div class="text-xs text-gray-500 dark:text-gray-400 text-center px-5 py-4">
								{$i18n.t('No results found')}
							</div>
						{:else}
							<div
								class="w-full text-xs text-gray-500 dark:text-gray-500 font-medium pb-2 px-2 flex justify-between items-center"
							>
								<span class="font-semibold">Message Results</span>
								<span class="text-gray-600 dark:text-gray-400">
									<span class="font-semibold text-gray-700 dark:text-gray-300">{messageSearchResponse.estimatedTotalHits || messageSearchResponse.totalHits}</span>
									{messageSearchResponse.estimatedTotalHits ? ' ~' : ''} hits in
									<span class="font-semibold text-gray-700 dark:text-gray-300">{messageSearchResponse.processingTimeMs}</span>ms
								</span>
							</div>

							{#if groupByConversation}
								{@const groupedResults = displayedMessageResults.reduce((groups, item) => {
									const key = item.chatId;
									if (!groups[key]) {
										groups[key] = {
											chatId: key,
											chatTitle: item.chatTitle || 'Untitled Chat',
											messages: []
										};
									}
									groups[key].messages.push(item);
									return groups;
								}, {})}
								
								{@const groupsSortedByFirstMessage = Object.values(groupedResults).sort((a, b) => {
									// When sorting by date, use the timestamp; otherwise use score
									// Groups are ordered by their first message (backend already sorted)
									const firstA = a.messages[0];
									const firstB = b.messages[0];
									
									if (sortBy === 'date') {
										return firstB.timestamp - firstA.timestamp; // Newest first
									}
									return firstB._rankingScore - firstA._rankingScore; // Best match first
								})}
	
								{#each groupsSortedByFirstMessage as group (group.chatId)}
									<!-- Don't re-sort messages - trust backend order -->
									{@const sortedMessages = group.messages}
									
									<div class="mb-3">
										<div class="text-xs font-semibold text-gray-700 dark:text-gray-300 px-2 py-1 bg-gray-100 dark:bg-gray-800 rounded-t-lg">
											{group.chatTitle} <span class="text-gray-500">({group.messages.length})</span>
										</div>
										{#each sortedMessages as item (item.id)}
											<a
												class="w-full block text-sm py-2 px-3 border-l-2 border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-850 hover:border-blue-500"
												href="/c/{item.chatId}?mid={item.messageId}"
												on:mouseenter={() => {
													selectedIdx = item.id;
													if (showPreview) {
														loadMessageChatPreview(item.chatId, item.messageId);
													}
												}}
												on:click={() => {
													show = false;
													onClose();
												}}
												data-arrow-selected={selectedIdx === item.id ? 'true' : undefined}
											>
												<div class="text-ellipsis line-clamp-2 w-full font-medium text-gray-700 dark:text-gray-300 message-highlight"
												     style="white-space: pre-wrap; word-break: break-word;">
													{@html item._formatted?.content || ''}
												</div>
												<div class="text-xs text-gray-500 mt-0.5 flex justify-between items-center">
													<span>{item.role === 'user' ? 'You' : 'AI'} • {new Date(item.timestamp * 1000).toLocaleDateString()}</span>
													<span>Score: {item._rankingScore.toFixed(2)}</span>
												</div>
											</a>
										{/each}
									</div>
								{/each}
							{:else}
								{#each displayedMessageResults as item, idx (item.id)}
									<a
										class="w-full block rounded-xl text-sm py-2 px-3 my-1 border border-gray-200 dark:border-gray-800 hover:bg-gray-50 dark:hover:bg-gray-850 hover:border-blue-500"
										href="/c/{item.chatId}?mid={item.messageId}"
										on:mouseenter={() => {
											selectedIdx = actions.length + idx;
											if (showPreview) {
												loadMessageChatPreview(item.chatId, item.messageId);
											}
										}}
										on:click={() => {
											show = false;
											onClose();
										}}
										data-arrow-selected={selectedIdx === actions.length + idx ? 'true' : undefined}
									>
										<div class="text-xs text-gray-500 mb-1">{item.chatTitle || 'Untitled Chat'}</div>
										<div class="text-ellipsis line-clamp-2 w-full font-medium text-gray-700 dark:text-gray-300 message-highlight"
										     style="white-space: pre-wrap; word-break: break-word;">
											{@html item._formatted?.content || ''}
										</div>
										<div class="text-xs text-gray-500 mt-1 flex justify-between items-center">
											<span>{item.role === 'user' ? 'You' : 'AI'} • {new Date(item.timestamp * 1000).toLocaleDateString()}</span>
											<span>Score: {item._rankingScore.toFixed(2)}</span>
										</div>
									</a>
								{/each}
	
								{#if hasMoreResults}
									<button
										class="w-full text-center py-3 text-sm text-blue-500 hover:bg-gray-50 dark:hover:bg-gray-850 rounded-lg"
										on:click={() => {
											messageResultsPage += 1;
										}}
									>
										Load More ({messageSearchResponse.hits.length - displayedMessageResults.length} remaining)
									</button>
								{/if}
							{/if}
						{/if}
					{:else}
						<div class="w-full h-full flex justify-center items-center">
							<Spinner className="size-5" />
						</div>
					{/if}
				{/if}
			</div>
			<div
				id="chat-preview"
				class="{showPreview ? 'md:flex' : 'hidden'} md:flex-1 w-full overflow-y-auto h-96 md:h-[40rem] scrollbar-hidden"
			>
				{#if messages === null}
					<div
						class="w-full h-full flex justify-center items-center text-gray-500 dark:text-gray-400 text-sm"
					>
						{$i18n.t('Select a conversation to preview')}
					</div>
				{:else}
					<div class="w-full h-full flex flex-col">
						<Messages
							className="h-full flex pt-4 pb-8 w-full"
							chatId={`chat-preview-${selectedChat?.id ?? ''}`}
							user={$user}
							readOnly={true}
							{selectedModels}
							bind:history
							bind:messages
							autoScroll={true}
							sendMessage={() => {}}
							continueResponse={() => {}}
							regenerateResponse={() => {}}
						/>
					</div>
				{/if}
			</div>
		</div>
	</div>
</Modal>

<style>
	:global(.message-highlight mark) {
		background: rgba(59, 130, 246, 0.2) !important;
		color: inherit;
		padding: 2px 4px;
		border-radius: 2px;
		font-weight: 600;
	}
</style>
