<script lang="ts">
	import CreateContractDialog from './create-contract-dialog.svelte';
	import ContractsTable from './contracts-table.svelte';
	import EditContractDialog from './edit-contract-dialog.svelte';
	import ArchiveContractDialog from './archive-contract-dialog.svelte';
	import { toast } from 'svelte-sonner';
	import { superForm } from 'sveltekit-superforms';
	import { zod4Client } from 'sveltekit-superforms/adapters';
	import { archiveSchema } from '$lib/schemas/shared.schema';
	import {
		contractCreateSchema,
		contractEditSchema,
		contractTransitionSchema
	} from '$lib/schemas/contracts.schema';
	import type { PageData } from './$types';
	type RecordRow = PageData['records'][number];
	let { data }: { data: PageData } = $props();

	let createOpen = $state(false);
	let editingId = $state<string | null>(null);
	let archivingId = $state<string | null>(null);

	const editingRecord = $derived(data.records.find((record) => record.id === editingId));
	const archivingRecord = $derived(data.records.find((record) => record.id === archivingId));

	// svelte-ignore state_referenced_locally
	const createForm = superForm(data.createForm, {
		validators: zod4Client(contractCreateSchema),
		onUpdated: ({ form }) => handleFormToast(form, 'contracts-create', () => (createOpen = false)),
		onError: ({ result }) => toast.error(result.error.message, { id: 'contracts-create' })
	});
	// svelte-ignore state_referenced_locally
	const editForm = superForm(data.editForm, {
		validators: zod4Client(contractEditSchema),
		resetForm: false,
		onUpdated: ({ form }) => handleFormToast(form, 'contracts-edit', () => (editingId = null)),
		onError: ({ result }) => toast.error(result.error.message, { id: 'contracts-edit' })
	});
	// svelte-ignore state_referenced_locally
	const archiveForm = superForm(data.archiveForm, {
		validators: zod4Client(archiveSchema),
		resetForm: false,
		onUpdated: ({ form }) => handleFormToast(form, 'contracts-archive', () => (archivingId = null)),
		onError: ({ result }) => toast.error(result.error.message, { id: 'contracts-archive' })
	});
	// svelte-ignore state_referenced_locally
	const transitionForm = superForm(data.transitionForm, {
		validators: zod4Client(contractTransitionSchema),
		resetForm: false,
		onUpdated: ({ form }) =>
			handleFormToast(form, 'contracts-transition', () => (editingId = null)),
		onError: ({ result }) => toast.error(result.error.message, { id: 'contracts-transition' })
	});

	const { form: createData, enhance: enhanceCreate } = createForm;
	const { form: editData, enhance: enhanceEdit } = editForm;
	const { form: archiveData, enhance: enhanceArchive } = archiveForm;
	const { enhance: enhanceTransition } = transitionForm;

	function handleFormToast(
		form: { valid: boolean; message?: string; errors: Record<string, unknown> },
		id: string,
		onSuccess: () => void
	) {
		if (form.valid) {
			if (form.message) toast.success(form.message, { id });
			onSuccess();
			return;
		}

		toast.error(form.message ?? firstError(form.errors), { id });
	}

	function firstError(errors: Record<string, unknown>) {
		for (const value of Object.values(errors)) {
			if (Array.isArray(value) && typeof value[0] === 'string') return value[0];
		}

		return 'Check the highlighted fields.';
	}

	function formatValue(value: unknown) {
		if (value === null || value === undefined || value === '') return 'Not set';
		return String(value);
	}

	function formatDate(value: unknown, withTime = false) {
		if (!value || typeof value !== 'string') return 'Not set';
		const date = new Date(value);
		if (Number.isNaN(date.getTime())) return value;
		return new Intl.DateTimeFormat('en-GB', {
			day: '2-digit',
			month: 'short',
			year: 'numeric',
			...(withTime ? { hour: '2-digit', minute: '2-digit' } : {})
		}).format(date);
	}

	function openEdit(record: RecordRow) {
		editForm.reset({ data: record.formValues as never });
		transitionForm.reset({
			data: {
				id: record.id,
				targetStatus: record.status === 'active' ? 'expired' : 'active'
			}
		});
		editingId = record.id;
	}

	function openArchive(record: RecordRow) {
		archiveForm.reset({ data: { id: record.id } });
		archivingId = record.id;
	}

	function recordName(record: Partial<RecordRow> | undefined) {
		return String(record?.roomName ?? record?.serviceName ?? 'this contract');
	}
</script>

<svelte:head>
	<title>Contracts | Clearity</title>
</svelte:head>

<div class="flex flex-col gap-6">
	<div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
		<div>
			<h1 class="text-2xl font-semibold tracking-tight">Contracts</h1>
			<p class="text-sm text-muted-foreground">Manage client agreements and commercial terms.</p>
		</div>

		<CreateContractDialog
			bind:open={createOpen}
			options={data.options}
			{createForm}
			{createData}
			{enhanceCreate}
		/>
	</div>

	<ContractsTable {data} {openEdit} {openArchive} {formatValue} {formatDate} {recordName} />
</div>

<EditContractDialog
	{editingRecord}
	options={data.options}
	{editForm}
	{editData}
	{enhanceEdit}
	{enhanceTransition}
	onClose={() => (editingId = null)}
/>

<ArchiveContractDialog
	{archivingRecord}
	{archiveData}
	{enhanceArchive}
	{recordName}
	onClose={() => (archivingId = null)}
/>
