<script lang="ts">
import { onMount } from 'svelte';
import { invalidateAll } from '$app/navigation';
import { m } from '$lib/paraglide/messages.js';
import { chipLabel, otherName, inferredRelationshipLabel } from '$lib/person/relationshipLabels';
import AddRelationshipForm from '$lib/person/relationship/AddRelationshipForm.svelte';
import type { RelFormData } from '$lib/person/relationship/AddRelationshipForm.svelte';
import type { components } from '$lib/generated/api';

type PersonNodeDTO = components['schemas']['PersonNodeDTO'];
type RelationshipDTO = components['schemas']['RelationshipDTO'];
type InferredRelationshipWithPersonDTO = components['schemas']['InferredRelationshipWithPersonDTO'];

interface Props {
	node: PersonNodeDTO;
	onClose: () => void;
	/** When provided, a "centre on this person" control appears in the title row (US-PAN-005). */
	onCentre?: () => void;
	canWrite?: boolean;
}

let { node, onClose, onCentre, canWrite = false }: Props = $props();

let directRels = $state<RelationshipDTO[]>([]);
let derivedRels = $state<InferredRelationshipWithPersonDTO[]>([]);
let loading = $state(false);
let error = $state<string | null>(null);

$effect(() => {
	const id = node.id;
	loadFor(id);
});

async function loadFor(id: string) {
	loading = true;
	error = null;
	try {
		const [directRes, derivedRes] = await Promise.all([
			fetch(`/api/persons/${id}/relationships`),
			fetch(`/api/persons/${id}/inferred-relationships`)
		]);
		if (!directRes.ok || !derivedRes.ok) {
			error = m.error_internal_error();
			return;
		}
		directRels = await directRes.json();
		derivedRels = await derivedRes.json();
	} catch {
		error = m.error_internal_error();
	} finally {
		loading = false;
	}
}

async function handleAddRelationship(data: RelFormData) {
	const body: Record<string, string | number> = {
		relatedPersonId: data.relatedPersonId,
		relationType: data.relationType
	};
	if (data.fromYear !== undefined) body.fromYear = data.fromYear;
	if (data.toYear !== undefined) body.toYear = data.toYear;
	const res = await fetch(`/api/persons/${node.id}/relationships`, {
		method: 'POST',
		headers: { 'Content-Type': 'application/json' },
		body: JSON.stringify(body)
	});
	if (!res.ok) throw new Error('Failed to add relationship');
	await loadFor(node.id);
	await invalidateAll();
}

function handleEscape(event: KeyboardEvent) {
	if (event.key === 'Escape') onClose();
}

onMount(() => {
	const handler = (e: KeyboardEvent) => handleEscape(e);
	window.addEventListener('keydown', handler);
	return () => window.removeEventListener('keydown', handler);
});

const directOtherIds = $derived(
	new Set(directRels.map((r) => (r.personId === node.id ? r.relatedPersonId : r.personId)))
);
const topDerived = $derived(
	derivedRels.filter((d) => !directOtherIds.has(d.person.id)).slice(0, 5)
);
</script>

<div class="flex h-full flex-col p-5">
	<div class="mb-4 flex items-start justify-between gap-2">
		<div class="min-w-0">
			<h2 class="font-serif text-lg text-ink">{node.displayName}</h2>
			{#if node.birthYear || node.deathYear}
				<p class="font-sans text-xs text-ink-3">
					{node.birthYear ?? '?'}–{node.deathYear ?? ''}
				</p>
			{/if}
		</div>
		<div class="flex shrink-0 items-center gap-1">
			{#if onCentre}
				<button
					type="button"
					onclick={onCentre}
					aria-label={m.stammbaum_centre_on_person()}
					class="inline-flex h-11 w-11 items-center justify-center rounded-sm text-ink-3 transition hover:bg-muted hover:text-ink focus-visible:ring-2 focus-visible:ring-focus-ring focus-visible:outline-none"
				>
					<svg
						class="h-4 w-4"
						viewBox="0 0 16 16"
						fill="none"
						stroke="currentColor"
						stroke-width="1.5"
						aria-hidden="true"
					>
						<circle cx="8" cy="8" r="2" />
						<path stroke-linecap="round" d="M8 1v2M8 13v2M1 8h2M13 8h2" />
					</svg>
				</button>
			{/if}
			<button
				type="button"
				onclick={onClose}
				aria-label={m.comp_dismiss()}
				class="inline-flex h-11 w-11 items-center justify-center rounded-sm text-ink-3 transition hover:bg-muted hover:text-ink focus-visible:ring-2 focus-visible:ring-focus-ring focus-visible:outline-none"
			>
				<svg
					class="h-4 w-4"
					viewBox="0 0 16 16"
					fill="none"
					stroke="currentColor"
					stroke-width="2"
					aria-hidden="true"
				>
					<path stroke-linecap="round" d="M3 3l10 10M13 3L3 13" />
				</svg>
			</button>
		</div>
	</div>

	{#if error}
		<p class="mb-3 text-sm text-red-700" role="alert">{error}</p>
	{:else if loading}
		<p class="font-sans text-xs text-ink-3 italic">…</p>
	{:else}
		<section class="mb-5">
			<h3 class="mb-2 font-sans text-xs font-bold tracking-widest text-ink-3 uppercase">
				{m.stammbaum_panel_direct_rels()}
			</h3>
			{#if directRels.length === 0}
				<p class="text-xs text-ink-2 italic">{m.person_relationships_empty()}</p>
			{:else}
				<ul class="space-y-1.5">
					{#each directRels as rel (rel.id)}
						<li class="flex items-center gap-2">
							<span
								class="inline-flex shrink-0 items-center rounded-full border border-accent/40 bg-accent/15 px-2 py-0.5 font-sans text-xs font-bold tracking-widest text-ink uppercase"
							>
								{chipLabel(rel, node.id)}
							</span>
							<span class="min-w-0 flex-1 truncate font-serif text-xs text-ink">
								{otherName(rel, node.id)}
							</span>
						</li>
					{/each}
				</ul>
			{/if}

			{#if canWrite}
				{#key node.id}
					<AddRelationshipForm personId={node.id} onSubmit={handleAddRelationship} />
				{/key}
			{/if}
		</section>

		{#if topDerived.length > 0}
			<section class="mb-5">
				<h3 class="mb-2 font-sans text-xs font-bold tracking-widest text-ink-3 uppercase">
					{m.stammbaum_panel_derived_rels()}
				</h3>
				<ul class="space-y-1.5">
					{#each topDerived as derived (derived.person.id)}
						<li class="flex items-center gap-2">
							<span
								class="inline-flex shrink-0 items-center rounded-full border border-line bg-muted/50 px-2 py-0.5 font-sans text-xs font-bold tracking-widest text-ink-2 uppercase"
							>
								{inferredRelationshipLabel(derived.label)}
							</span>
							<span class="min-w-0 flex-1 truncate font-serif text-xs text-ink-2">
								{derived.person.displayName}
							</span>
						</li>
					{/each}
				</ul>
			</section>
		{/if}
	{/if}

	<div class="mt-auto">
		<a
			href="/persons/{node.id}"
			class="block w-full rounded-sm border border-line bg-surface px-3 py-2 text-center font-sans text-xs font-medium text-primary transition hover:bg-muted"
		>
			{m.stammbaum_panel_to_person()}
		</a>
	</div>
</div>
