<script lang="ts">
	import type { PageData } from './$types';
	import type { LayoutData } from '../../$types';
	import { goto, invalidateAll } from '$app/navigation';
	import { format, isSameDay, isToday, isYesterday } from 'date-fns';
	import {
		sendMessage,
		deleteMessage,
		markAsRead,
		archiveConversation,
		muteConversation,
		deleteConversation,
		getSenderName,
		getSenderId,
		getConversationTypeLabel,
		getEntityDisplay
	} from '$lib/utils/messages';
	import { unreadCounts } from '$lib/stores/unreadCounts.svelte';

	interface Props {
		data: PageData & {
			user?: LayoutData['user'];
			accountLookup?: LayoutData['accountLookup'];
			customerLookup?: LayoutData['customerLookup'];
		};
	}

	let { data }: Props = $props();

	let conversation = $derived(data.conversation.data?.conversation);
	let messages = $derived(conversation?.messages ?? []);
	let currentUserId = $derived(data.user?.data?.me?.id ?? '');

	// Determine user type for entity links
	let userType = $derived<'team' | 'customer'>(
		data.user?.data?.me?.__typename === 'CustomerProfileType' ? 'customer' : 'team'
	);

	// Lookups from parent layout
	let accountLookup = $derived(data.accountLookup);
	let customerLookup = $derived(data.customerLookup);

	let messageInput = $state('');
	let isSending = $state(false);
	let actionsOpen = $state(false);
	let messagesContainer = $state<HTMLDivElement | null>(null);

	// Mark as read on mount
	$effect(() => {
		if (conversation && conversation.unreadCount > 0) {
			markAsRead(conversation.id)
				.then(() => {
					unreadCounts.decrementMessages(conversation!.unreadCount);
				})
				.catch(console.error);
		}
	});

	// Scroll to bottom on new messages
	$effect(() => {
		if (messages.length > 0 && messagesContainer) {
			setTimeout(() => {
				messagesContainer?.scrollTo({ top: messagesContainer.scrollHeight, behavior: 'smooth' });
			}, 100);
		}
	});

	async function handleSend() {
		if (!conversation || !messageInput.trim() || isSending) return;

		isSending = true;
		try {
			await sendMessage({
				conversationId: conversation.id,
				body: messageInput.trim()
			});
			messageInput = '';
			await invalidateAll();
		} catch (error) {
			console.error('Failed to send message:', error);
		} finally {
			isSending = false;
		}
	}

	function handleKeyDown(event: KeyboardEvent) {
		if (event.key === 'Enter' && !event.shiftKey) {
			event.preventDefault();
			handleSend();
		}
	}

	async function handleDeleteMessage(id: string) {
		if (!confirm('Delete this message?')) return;

		try {
			await deleteMessage(id);
			await invalidateAll();
		} catch (error) {
			console.error('Failed to delete message:', error);
		}
	}

	async function handleArchive() {
		if (!conversation) return;
		actionsOpen = false;

		try {
			await archiveConversation(conversation.id, !conversation.isArchived);
			await invalidateAll();
		} catch (error) {
			console.error('Failed to archive conversation:', error);
		}
	}

	async function handleMute() {
		if (!conversation) return;
		actionsOpen = false;

		// Get current muted state from participant
		const myParticipant = conversation.participants?.find((p) => {
			const id = p?.participant?.teamProfile?.id ?? p?.participant?.customerProfile?.id;
			return id === currentUserId;
		});
		const isMuted = myParticipant?.isMuted ?? false;

		try {
			await muteConversation(conversation.id, !isMuted);
			await invalidateAll();
		} catch (error) {
			console.error('Failed to mute conversation:', error);
		}
	}

	async function handleDelete() {
		if (!conversation) return;
		if (!confirm('Are you sure you want to delete this conversation? This cannot be undone.'))
			return;
		actionsOpen = false;

		try {
			await deleteConversation(conversation.id);
			unreadCounts.fetchCounts();
			goto('/messages');
		} catch (error) {
			console.error('Failed to delete conversation:', error);
		}
	}

	function formatMessageTime(dateString: string): string {
		try {
			return format(new Date(dateString), 'h:mm a');
		} catch {
			return '';
		}
	}

	function formatDateSeparator(dateString: string): string {
		try {
			const date = new Date(dateString);
			if (isToday(date)) return 'Today';
			if (isYesterday(date)) return 'Yesterday';
			return format(date, 'MMMM d, yyyy');
		} catch {
			return '';
		}
	}

	function shouldShowDateSeparator(index: number): boolean {
		if (index === 0) return true;
		const currentMsg = messages[index];
		const prevMsg = messages[index - 1];
		if (!currentMsg?.createdAt || !prevMsg?.createdAt) return false;
		return !isSameDay(new Date(currentMsg.createdAt), new Date(prevMsg.createdAt));
	}

	function isOwnMessage(senderId: string | null): boolean {
		return senderId === currentUserId;
	}

	function goBack() {
		goto('/messages');
	}

	let entityDisplay = $derived(
		conversation
			? getEntityDisplay(conversation.entity, { accountLookup, customerLookup, userType })
			: null
	);
	let myParticipant = $derived(
		conversation?.participants?.find((p) => {
			const id = p?.participant?.teamProfile?.id ?? p?.participant?.customerProfile?.id;
			return id === currentUserId;
		})
	);
	let isMuted = $derived(myParticipant?.isMuted ?? false);
</script>

<svelte:head>
	<title>{conversation?.subject ?? 'Conversation'} | Nexus</title>
</svelte:head>

<div class="flex h-[calc(100vh-3.5rem)] flex-col">
	<!-- Header -->
	<div class="flex items-center justify-between border-b border-theme bg-theme-card px-4 py-3">
		<div class="flex min-w-0 items-center gap-3">
			<button
				onclick={goBack}
				class="flex-shrink-0 rounded-lg interactive p-2"
				aria-label="Go back"
			>
				<svg
					class="h-5 w-5 text-theme-secondary"
					style="fill: none"
					stroke="currentColor"
					viewBox="0 0 24 24"
				>
					<path
						stroke-linecap="round"
						stroke-linejoin="round"
						stroke-width="2"
						d="M15 19l-7-7 7-7"
					/>
				</svg>
			</button>
			<div class="min-w-0">
				<h1 class="truncate text-lg font-semibold text-theme">
					{conversation?.subject || 'Conversation'}
				</h1>
				<p class="truncate text-xs text-theme-muted">
					{getConversationTypeLabel(conversation?.conversationType)}
					{#if entityDisplay}
						·
						{#if entityDisplay.link}
							<a
								href={entityDisplay.link}
								class="text-primary-600 hover:underline dark:text-primary-400"
							>
								{entityDisplay.type}: {entityDisplay.name}
							</a>
						{:else}
							{entityDisplay.type}: {entityDisplay.name}
						{/if}
					{/if}
				</p>
			</div>
		</div>

		<!-- Actions dropdown -->
		<div class="relative">
			<button
				onclick={() => (actionsOpen = !actionsOpen)}
				class="rounded-lg interactive p-2"
				aria-label="More actions"
			>
				<svg
					class="h-5 w-5 text-theme-secondary"
					style="fill: none"
					stroke="currentColor"
					viewBox="0 0 24 24"
				>
					<path
						stroke-linecap="round"
						stroke-linejoin="round"
						stroke-width="2"
						d="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z"
					/>
				</svg>
			</button>

			{#if actionsOpen}
				<!-- svelte-ignore a11y_no_static_element_interactions -->
				<div
					class="fixed inset-0 z-40"
					onclick={() => (actionsOpen = false)}
					onkeydown={(e) => e.key === 'Escape' && (actionsOpen = false)}
				></div>
				<div
					class="absolute top-full right-0 z-50 mt-1 w-48 overflow-hidden rounded-lg border border-theme bg-theme-card shadow-theme-lg"
				>
					<button
						onclick={handleMute}
						class="flex w-full items-center gap-2 interactive px-4 py-2.5 text-sm text-theme-secondary"
					>
						<svg class="h-4 w-4" style="fill: none" stroke="currentColor" viewBox="0 0 24 24">
							{#if isMuted}
								<path
									stroke-linecap="round"
									stroke-linejoin="round"
									stroke-width="2"
									d="M15.536 8.464a5 5 0 010 7.072M12 6v12m0 0l-4-4m4 4l4-4"
								/>
							{:else}
								<path
									stroke-linecap="round"
									stroke-linejoin="round"
									stroke-width="2"
									d="M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z"
								/>
								<path
									stroke-linecap="round"
									stroke-linejoin="round"
									stroke-width="2"
									d="M17 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2"
								/>
							{/if}
						</svg>
						{isMuted ? 'Unmute' : 'Mute'}
					</button>
					<button
						onclick={handleArchive}
						class="flex w-full items-center gap-2 interactive px-4 py-2.5 text-sm text-theme-secondary"
					>
						<svg class="h-4 w-4" style="fill: none" stroke="currentColor" viewBox="0 0 24 24">
							<path
								stroke-linecap="round"
								stroke-linejoin="round"
								stroke-width="2"
								d="M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4"
							/>
						</svg>
						{conversation?.isArchived ? 'Unarchive' : 'Archive'}
					</button>
					{#if conversation?.canDelete}
						<button
							onclick={handleDelete}
							class="flex w-full items-center gap-2 px-4 py-2.5 text-sm text-error-600 transition-colors hover:bg-error-50 dark:text-error-400 dark:hover:bg-error-900/20"
						>
							<svg class="h-4 w-4" style="fill: none" stroke="currentColor" viewBox="0 0 24 24">
								<path
									stroke-linecap="round"
									stroke-linejoin="round"
									stroke-width="2"
									d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
								/>
							</svg>
							Delete
						</button>
					{/if}
				</div>
			{/if}
		</div>
	</div>

	<!-- Messages -->
	<div bind:this={messagesContainer} class="flex-1 overflow-y-auto px-4 py-4">
		{#if !conversation}
			<div class="flex h-full items-center justify-center">
				<p class="text-theme-muted">Conversation not found</p>
			</div>
		{:else if messages.length === 0}
			<div class="flex h-full items-center justify-center">
				<p class="text-theme-muted">No messages yet. Start the conversation!</p>
			</div>
		{:else}
			<div class="mx-auto max-w-2xl space-y-4">
				{#each messages as message, index (message.id)}
					{@const senderId = getSenderId(message.sender)}
					{@const isOwn = isOwnMessage(senderId)}

					<!-- Date separator -->
					{#if shouldShowDateSeparator(index)}
						<div class="flex items-center justify-center py-2">
							<span
								class="rounded-full bg-black/5 px-3 py-1 text-xs font-medium text-theme-muted dark:bg-white/10"
							>
								{formatDateSeparator(message.createdAt)}
							</span>
						</div>
					{/if}

					<!-- Message bubble -->
					<div class="group flex {isOwn ? 'justify-end' : 'justify-start'}">
						<div class="max-w-[80%] {isOwn ? 'items-end' : 'items-start'}">
							<!-- Sender name (for received messages) -->
							{#if !isOwn && !message.isSystemMessage}
								<p class="mb-1 px-3 text-xs font-medium text-theme-muted">
									{getSenderName(message.sender)}
								</p>
							{/if}

							<div class="flex items-end gap-2 {isOwn ? 'flex-row-reverse' : ''}">
								<!-- Bubble -->
								<div
									class="rounded-2xl px-4 py-2 {isOwn
										? 'rounded-br-md bg-primary-600 text-white'
										: message.isSystemMessage
											? 'bg-warning-100 text-warning-800 dark:bg-warning-900/30 dark:text-warning-200'
											: 'rounded-bl-md bg-black/5 text-theme dark:bg-white/10'}"
								>
									{#if message.replyTo}
										<div class="mb-2 border-l-2 border-current/30 pl-2 text-xs opacity-70">
											<span class="font-medium">{getSenderName(message.replyTo.sender)}</span>
											<p class="line-clamp-1">{message.replyTo.body}</p>
										</div>
									{/if}
									<p class="break-words whitespace-pre-wrap">{message.body}</p>
								</div>

								<!-- Delete button (own messages only) -->
								{#if message.canDelete}
									<button
										onclick={() => handleDeleteMessage(message.id)}
										class="flex-shrink-0 rounded-lg p-1 text-theme-muted opacity-0 transition-all group-hover:opacity-100 hover:bg-error-100 hover:text-error-600 dark:hover:bg-error-900/30"
										aria-label="Delete message"
									>
										<svg
											class="h-3.5 w-3.5"
											style="fill: none"
											stroke="currentColor"
											viewBox="0 0 24 24"
										>
											<path
												stroke-linecap="round"
												stroke-linejoin="round"
												stroke-width="2"
												d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
											/>
										</svg>
									</button>
								{/if}
							</div>

							<!-- Time -->
							<p class="mt-1 px-3 text-xs text-theme-muted {isOwn ? 'text-right' : ''}">
								{formatMessageTime(message.createdAt)}
							</p>
						</div>
					</div>
				{/each}
			</div>
		{/if}
	</div>

	<!-- Message input -->
	<div class="border-t border-theme bg-theme-card p-4">
		<div class="mx-auto max-w-2xl">
			<div class="flex items-end gap-2">
				<textarea
					bind:value={messageInput}
					onkeydown={handleKeyDown}
					placeholder="Type a message..."
					rows="1"
					class="flex-1 resize-none rounded-xl border border-theme bg-theme px-4 py-3 text-sm text-theme transition-all outline-none placeholder:text-theme-muted focus:border-primary-500"
				></textarea>
				<button
					onclick={handleSend}
					disabled={!messageInput.trim() || isSending}
					class="flex h-11 w-11 flex-shrink-0 items-center justify-center rounded-xl bg-primary-600 text-white transition-colors hover:bg-primary-700 disabled:opacity-50"
					aria-label="Send message"
				>
					{#if isSending}
						<svg
							class="h-5 w-5 animate-spin"
							style="fill: none"
							stroke="currentColor"
							viewBox="0 0 24 24"
						>
							<circle class="opacity-25" cx="12" cy="12" r="10" stroke-width="4"></circle>
							<path
								class="opacity-75"
								d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
							></path>
						</svg>
					{:else}
						<svg class="h-5 w-5" style="fill: none" stroke="currentColor" viewBox="0 0 24 24">
							<path
								stroke-linecap="round"
								stroke-linejoin="round"
								stroke-width="2"
								d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8"
							/>
						</svg>
					{/if}
				</button>
			</div>
		</div>
	</div>
</div>
