<script lang="ts">
	import { untrack } from "svelte";
	import { now as tidNow } from "@atcute/tid";
	import CirclePlus from "$icon/circle-plus";
	import Pencil from "$icon/pencil";
	import X from "$icon/x";
	import { putIssue } from "$lib/api/issue";
	import { getAuth } from "$lib/auth.svelte";
	import Button from "$lib/components/ui/Button.svelte";
	import ErrorAlert from "$lib/components/ui/Error.svelte";
	import Input from "$lib/components/ui/Input.svelte";
	import MarkdownEditor from "$lib/components/ui/MarkdownEditor.svelte";
	import Spinner from "$lib/components/ui/Spinner.svelte";
	import { type MarkupContext } from "$lib/markup";
	import type { IssueRecord, RecordView } from "$lib/api/records";

	interface Props {
		repoDid: string;
		markup: MarkupContext;
		mode?: "create" | "edit";
		rkey?: string;
		createdAt?: string;
		title?: string;
		body?: string;
		submitLabel?: string;
		bodyPlaceholder?: string;
		onsaved: (saved: RecordView<IssueRecord>) => void;
		oncancel: () => void;
	}

	let {
		repoDid,
		markup,
		mode = "create",
		rkey,
		createdAt,
		title: initialTitle = "",
		body: initialBody = "",
		submitLabel,
		bodyPlaceholder = "Describe your issue. Markdown is supported.",
		onsaved,
		oncancel
	}: Props = $props();

	const auth = getAuth();

	let title = $state(untrack(() => initialTitle));
	let body = $state(untrack(() => initialBody));
	let isPublishing = $state(false);
	let error = $state<string | null>(null);

	const submitText = $derived(submitLabel ?? (mode === "edit" ? "Save" : "Create issue"));
	const submitIcon = $derived(mode === "edit" ? Pencil : CirclePlus);
	const canSubmit = $derived(title.trim() !== "" && !isPublishing);

	const handleSubmit = async (e: SubmitEvent) => {
		e.preventDefault();
		const agent = auth.agent;
		if (!agent || !canSubmit) return;
		isPublishing = true;
		error = null;
		try {
			const targetRkey = rkey ?? tidNow();
			const record: IssueRecord = {
				$type: "sh.tangled.repo.issue",
				repo: repoDid as IssueRecord["repo"],
				title,
				body,
				createdAt: createdAt ?? new Date().toISOString()
			};
			const saved = await putIssue(agent, targetRkey, record);
			onsaved(saved);
		} catch (err) {
			error = err instanceof Error ? err.message : "Failed to save issue";
		} finally {
			isPublishing = false;
		}
	};
</script>

<form onsubmit={handleSubmit} class="flex flex-col gap-4">
	<div class="flex flex-col gap-1.5">
		<label for="issue-title" class="text-sm text-foreground-default">Title</label>
		<Input id="issue-title" name="title" required bind:value={title} disabled={isPublishing} />
	</div>

	<div class="flex flex-col gap-1.5">
		<span class="text-sm text-foreground-default">Body</span>

		<MarkdownEditor
			id="issue-body"
			name="body"
			rows={12}
			placeholder={bodyPlaceholder}
			{markup}
			bind:value={body}
			disabled={isPublishing}
		/>
	</div>

	{#if error}
		<ErrorAlert label={error} />
	{/if}

	<div class="flex items-center justify-end gap-2">
		<Button type="button" variant="default" icon={X} disabled={isPublishing} onclick={oncancel}>
			Cancel
		</Button>
		<Button
			type="submit"
			variant="primary"
			icon={isPublishing ? Spinner : submitIcon}
			disabled={!canSubmit}
		>
			{submitText}
		</Button>
	</div>
</form>
