<script lang="ts">
	import * as Table from '$lib/components/ui/table/index.js';
	import * as Card from '$lib/components/ui/card/index.js';
	import * as Dialog from '$lib/components/ui/dialog/index.js';
	import * as DropdownMenu from '$lib/components/ui/dropdown-menu/index.js';
	import * as AlertDialog from '$lib/components/ui/alert-dialog/index.js';
	import * as Empty from '$lib/components/ui/empty/index.js';
	import { Button, buttonVariants } from '$lib/components/ui/button/index.js';
	import {
		EllipsisVertical,
		Plus,
		Eye,
		EyeOff,
		Copy,
		RefreshCw,
		Trash2,
		Smartphone
	} from '@lucide/svelte';
	import DeviceCreateForm from '$lib/components/forms/device-create-form.svelte';
	import { deleteDevice, regenerateDeviceApiKey } from '$lib/api/device.remote';
	import { toast } from 'svelte-sonner';
	import { invalidateAll } from '$app/navigation';
	import type { Device } from '$lib/schema/device';
	import { SvelteSet } from 'svelte/reactivity';

	let { data } = $props();

	let createDialogOpen = $state(false);
	const visibleApiKeys = new SvelteSet<string>();
	let deleteConfirmDevice = $state<Device | null>(null);
	let regenerateConfirmDevice = $state<Device | null>(null);

	function toggleApiKeyVisibility(deviceId: string) {
		if (visibleApiKeys.has(deviceId)) {
			visibleApiKeys.delete(deviceId);
		} else {
			visibleApiKeys.add(deviceId);
		}
	}

	function maskApiKey(apiKey: string): string {
		return '•'.repeat(Math.min(apiKey.length, 32));
	}

	async function copyToClipboard(text: string) {
		try {
			await navigator.clipboard.writeText(text);
			toast.success('API key copied to clipboard');
		} catch {
			toast.error('Failed to copy to clipboard');
		}
	}

	async function handleDelete(device: Device) {
		try {
			await deleteDevice(String(device.id));
			toast.success(`Device '${device.name}' deleted`);
			deleteConfirmDevice = null;
			await invalidateAll();
		} catch {
			toast.error('Failed to delete device');
		}
	}

	async function handleRegenerate(device: Device) {
		try {
			await regenerateDeviceApiKey(String(device.id));
			toast.success(`API key regenerated for '${device.name}'`);
			regenerateConfirmDevice = null;
			await invalidateAll();
		} catch {
			toast.error('Failed to regenerate API key');
		}
	}

	function handleDeviceCreated() {
		createDialogOpen = false;
		invalidateAll();
	}
</script>

<div class="mb-4 flex items-center justify-between">
	<div>
		<h2 class="text-lg font-semibold">Devices</h2>
		<p class="text-sm text-muted-foreground">Manage your KOReader devices</p>
	</div>
	<Dialog.Root bind:open={createDialogOpen}>
		<Dialog.Trigger class={buttonVariants({ variant: 'outline' })}>
			<Plus />
			Add Device
		</Dialog.Trigger>

		<Dialog.Content>
			<Dialog.Header>
				<Dialog.Title>Add a new device</Dialog.Title>
				<Dialog.Description>
					Create a device to sync your KOReader reading progress.
				</Dialog.Description>
			</Dialog.Header>
			<DeviceCreateForm onSuccess={handleDeviceCreated} />
		</Dialog.Content>
	</Dialog.Root>
</div>

{#if data.devices.length === 0}
	<Empty.Root class="py-12">
		<Empty.Header>
			<Empty.Media variant="icon">
				<Smartphone />
			</Empty.Media>
			<Empty.Title>No devices</Empty.Title>
			<Empty.Description>Add a device to sync your KOReader reading progress.</Empty.Description>
		</Empty.Header>
		<Empty.Content>
			<Button onclick={() => (createDialogOpen = true)}>
				<Plus />
				Add Device
			</Button>
		</Empty.Content>
	</Empty.Root>
{:else}
	<Card.Root>
		<Card.Content class="p-0">
			<Table.Root>
				<Table.Header>
					<Table.Row>
						<Table.Head class="pl-4">Name</Table.Head>
						<Table.Head>API Key</Table.Head>
						<Table.Head class="w-16"></Table.Head>
					</Table.Row>
				</Table.Header>
				<Table.Body>
					{#each data.devices as device (device.id)}
						{@const isVisible = visibleApiKeys.has(String(device.id))}
						<Table.Row class="h-14">
							<Table.Cell class="pl-4 font-medium">
								{device.name}
							</Table.Cell>
							<Table.Cell>
								<div class="flex items-center gap-2">
									<code class="rounded bg-muted px-2 py-1 font-mono text-sm">
										{isVisible ? device.api_key : maskApiKey(device.api_key)}
									</code>
									<Button
										variant="ghost"
										size="icon"
										class="h-8 w-8"
										onclick={() => toggleApiKeyVisibility(String(device.id))}
									>
										{#if isVisible}
											<EyeOff class="h-4 w-4" />
										{:else}
											<Eye class="h-4 w-4" />
										{/if}
									</Button>
									<Button
										variant="ghost"
										size="icon"
										class="h-8 w-8"
										onclick={() => copyToClipboard(device.api_key)}
									>
										<Copy class="h-4 w-4" />
									</Button>
								</div>
							</Table.Cell>
							<Table.Cell class="text-center">
								<DropdownMenu.Root>
									<DropdownMenu.Trigger>
										<Button variant="ghost" size="icon" class="h-8 w-8">
											<EllipsisVertical class="h-4 w-4" />
										</Button>
									</DropdownMenu.Trigger>
									<DropdownMenu.Content align="end">
										<DropdownMenu.Item onclick={() => (regenerateConfirmDevice = device)}>
											<RefreshCw class="mr-2 h-4 w-4" />
											Regenerate API Key
										</DropdownMenu.Item>
										<DropdownMenu.Separator />
										<DropdownMenu.Item
											class="text-destructive focus:text-destructive"
											onclick={() => (deleteConfirmDevice = device)}
										>
											<Trash2 class="mr-2 h-4 w-4" />
											Delete
										</DropdownMenu.Item>
									</DropdownMenu.Content>
								</DropdownMenu.Root>
							</Table.Cell>
						</Table.Row>
					{/each}
				</Table.Body>
			</Table.Root>
		</Card.Content>
	</Card.Root>
{/if}

<!-- Delete Confirmation Dialog -->
<AlertDialog.Root open={deleteConfirmDevice !== null}>
	<AlertDialog.Content>
		<AlertDialog.Header>
			<AlertDialog.Title>Delete device?</AlertDialog.Title>
			<AlertDialog.Description>
				Are you sure you want to delete "{deleteConfirmDevice?.name}"? This action cannot be undone.
				The device will no longer be able to sync reading progress.
			</AlertDialog.Description>
		</AlertDialog.Header>
		<AlertDialog.Footer>
			<AlertDialog.Cancel onclick={() => (deleteConfirmDevice = null)}>Cancel</AlertDialog.Cancel>
			<AlertDialog.Action
				class={buttonVariants({ variant: 'destructive' })}
				onclick={() => deleteConfirmDevice && handleDelete(deleteConfirmDevice)}
			>
				Delete
			</AlertDialog.Action>
		</AlertDialog.Footer>
	</AlertDialog.Content>
</AlertDialog.Root>

<!-- Regenerate API Key Confirmation Dialog -->
<AlertDialog.Root open={regenerateConfirmDevice !== null}>
	<AlertDialog.Content>
		<AlertDialog.Header>
			<AlertDialog.Title>Regenerate API key?</AlertDialog.Title>
			<AlertDialog.Description>
				This will invalidate the current API key for "{regenerateConfirmDevice?.name}". You will
				need to update the key in your KOReader device settings.
			</AlertDialog.Description>
		</AlertDialog.Header>
		<AlertDialog.Footer>
			<AlertDialog.Cancel onclick={() => (regenerateConfirmDevice = null)}
				>Cancel</AlertDialog.Cancel
			>
			<AlertDialog.Action
				onclick={() => regenerateConfirmDevice && handleRegenerate(regenerateConfirmDevice)}
			>
				Regenerate
			</AlertDialog.Action>
		</AlertDialog.Footer>
	</AlertDialog.Content>
</AlertDialog.Root>
