<script lang="ts">
	import { untrack } from "svelte";
	import { now as tidNow } from "@atcute/tid";
	import Button from "$lib/components/ui/Button.svelte";
	import Spinner from "$lib/components/ui/Spinner.svelte";
	import ErrorAlert from "$lib/components/ui/Error.svelte";
	import ArrowUp from "$icon/arrow-up";
	import X from "$icon/x";
	import { getAuth } from "$lib/auth.svelte";
	import { putString } from "$lib/api/strings";
	import type { StringRecord } from "$lib/api/records";
	import { createAction } from "$lib/action.svelte";

	interface Props {
		mode?: "create" | "edit";
		rkey?: string;
		createdAt?: string;
		filename?: string;
		description?: string;
		content?: string;
		onsaved: (rkey: string) => void;
		oncancel?: () => void;
	}

	let {
		mode = "create",
		rkey,
		createdAt,
		filename: initialFilename = "",
		description: initialDescription = "",
		content: initialContent = "",
		onsaved,
		oncancel
	}: Props = $props();

	const auth = getAuth();

	let filename = $state(untrack(() => initialFilename));
	let description = $state(untrack(() => initialDescription));
	let content = $state(untrack(() => initialContent));

	const lineCount = $derived(content === "" ? 0 : content.split("\n").length);
	const byteCount = $derived(new TextEncoder().encode(content).length);

	const publish = createAction(async (event: SubmitEvent) => {
		event.preventDefault();
		const agent = auth.agent;
		if (!agent) return;
		const targetRkey = rkey ?? tidNow();
		const record: StringRecord = {
			$type: "sh.tangled.string",
			filename,
			description,
			contents: content,
			createdAt: createdAt ?? new Date().toISOString()
		};
		await putString(agent, targetRkey, record);
		onsaved(targetRkey);
	});
</script>

<div class="rounded-sm border border-border-default bg-background-default">
	<form onsubmit={publish.run}>
		<div class="flex flex-col gap-2 p-4">
			<div class="flex flex-col gap-2 md:flex-row">
				<input
					type="text"
					id="filename"
					name="filename"
					placeholder="Filename"
					required
					bind:value={filename}
					disabled={publish.loading}
					class="rounded-sm border border-border-default bg-background-default p-2 text-sm text-foreground-default placeholder:text-foreground-placeholder focus:ring-1 focus:ring-border-strong focus:outline-none disabled:opacity-50 md:max-w-64"
				/>
				<input
					type="text"
					id="description"
					name="description"
					placeholder="Description ..."
					maxlength={280}
					bind:value={description}
					disabled={publish.loading}
					class="flex-1 rounded-sm border border-border-default bg-background-default p-2 text-sm text-foreground-default placeholder:text-foreground-placeholder focus:ring-1 focus:ring-border-strong focus:outline-none disabled:opacity-50"
				/>
			</div>

			<textarea
				id="content"
				name="content"
				placeholder="Paste your string here!"
				required
				rows={20}
				spellcheck={false}
				bind:value={content}
				disabled={publish.loading}
				class="w-full resize-y rounded-sm border border-border-default bg-background-default p-2 font-mono text-sm text-foreground-default placeholder:text-foreground-placeholder focus:ring-1 focus:ring-border-strong focus:outline-none disabled:opacity-50"
			></textarea>
		</div>

		<div class="flex items-center justify-between px-4 py-3">
			<div class="text-sm text-foreground-subtle">
				<span>{lineCount} line{lineCount !== 1 ? "s" : ""}</span>
				<span class="px-1 select-none">·</span>
				<span>{byteCount} byte{byteCount !== 1 ? "s" : ""}</span>
			</div>

			<div class="flex items-center gap-2">
				{#if mode === "edit"}
					<Button
						type="button"
						variant="default"
						icon={X}
						disabled={publish.loading}
						onclick={oncancel}
					>
						Cancel
					</Button>
				{/if}
				<Button
					type="submit"
					variant="primary"
					icon={publish.loading ? Spinner : ArrowUp}
					disabled={publish.loading}
				>
					Publish
				</Button>
			</div>
		</div>

		{#if publish.error}
			<div class="px-4 pb-4">
				<ErrorAlert label={publish.error} />
			</div>
		{/if}
	</form>
</div>
