<script lang="ts">
	import type { UiNode, UiNodeInputAttributes } from '@ory/client';
	import { getNodeLabel } from '$lib/utils';
	import { onMount } from 'svelte';

	let { node }: { node: UiNode } = $props();

	// Filter out metadata_public fields from registration forms
	const shouldHideField = $derived(() => {
		const inputAttrs = node.type === 'input' ? (node.attributes as UiNodeInputAttributes) : null;
		if (!inputAttrs) return false;
		
		// Hide metadata_public fields (these should be set programmatically, not by users)
		return inputAttrs.name?.startsWith('metadata_public.');
	});

	// Check if this is the profile_type field that should be a select
	const isProfileTypeSelect = $derived(() => {
		const inputAttrs = node.type === 'input' ? (node.attributes as UiNodeInputAttributes) : null;
		return inputAttrs?.name === 'traits.profile_type';
	});

	const label = $derived(getNodeLabel(node));
	const messages = $derived(node.messages || []);
	const hasError = $derived(messages.some((m) => m.type === 'error'));

	// Get typed attributes based on node type
	const inputAttrs = $derived(
		node.type === 'input' ? (node.attributes as UiNodeInputAttributes) : null
	);
	const imageAttrs = $derived(
		node.type === 'img' ? (node.attributes as any) : null
	);
	const textAttrs = $derived(
		node.type === 'text' ? (node.attributes as any) : null
	);
	const scriptAttrs = $derived(
		node.type === 'script' ? (node.attributes as any) : null
	);

	// Handle script nodes by dynamically injecting them into the DOM
	onMount(() => {
		if (scriptAttrs) {
			const script = document.createElement('script');
			script.src = scriptAttrs.src;
			script.async = scriptAttrs.async;
			script.type = scriptAttrs.type;
			if (scriptAttrs.integrity) script.integrity = scriptAttrs.integrity;
			if (scriptAttrs.crossorigin) script.crossOrigin = scriptAttrs.crossorigin;
			if (scriptAttrs.referrerpolicy) script.referrerPolicy = scriptAttrs.referrerpolicy;

			document.body.appendChild(script);

			return () => {
				// Cleanup on unmount
				if (script.parentNode) {
					script.parentNode.removeChild(script);
				}
			};
		}
	});

	// Provide appropriate autocomplete values for better accessibility (only for input nodes)
	const autocompleteValue = $derived.by((): any => {
		if (!inputAttrs) return undefined;

		// If Kratos provides autocomplete, use it (but filter out invalid values)
		if (inputAttrs.autocomplete) {
			const autocompleteStr = String(inputAttrs.autocomplete);
			// Filter out OpenAPI unknown default values
			if (autocompleteStr === '11184809') return undefined;
			return autocompleteStr;
		}

		// Fallback autocomplete values based on field name and type
		if (inputAttrs.name === 'identifier') return 'username';
		if (inputAttrs.name === 'password')
			return inputAttrs.type === 'password' ? 'current-password' : 'new-password';
		if (inputAttrs.name === 'traits.email') return 'email';
		if (inputAttrs.name === 'traits.name.first') return 'given-name';
		if (inputAttrs.name === 'traits.name.last') return 'family-name';
		if (inputAttrs.name === 'traits.phone') return 'tel';

		return undefined;
	});

	// Handle WebAuthn button clicks
	function handleButtonClick(e: MouseEvent) {
		if (!inputAttrs) return;

		// Handle WebAuthn triggers
		if (inputAttrs.onclickTrigger) {
			const triggerFn = (window as any)[inputAttrs.onclickTrigger];
			if (typeof triggerFn === 'function') {
				triggerFn(e.currentTarget);
			}
		} else if (inputAttrs.onclick) {
			// Deprecated onclick - use eval (security risk, but Kratos provides this)
			eval(inputAttrs.onclick);
		}
	}
</script>

{#if shouldHideField()}
	<!-- Hidden metadata_public fields - don't render -->
{:else}
<div class="form-field">
	{#if node.type === 'script' && scriptAttrs}
		<!-- Script node (e.g., WebAuthn scripts) - injected dynamically via onMount into document.body -->
	{:else if node.type === 'img' && imageAttrs}
		<!-- Image node (e.g., TOTP QR code) -->
		<div class="qr-code-container">
			{#if label}
				<p class="form-label">{label}</p>
			{/if}
			<img src={imageAttrs.src} alt="QR Code" width={imageAttrs.width} height={imageAttrs.height} />
		</div>
	{:else if node.type === 'text' && textAttrs}
		<!-- Text node (e.g., TOTP secret) -->
		<div class="text-node">
			<p class="text-sm text-theme-secondary">{textAttrs.text.text}</p>
		</div>
	{:else if node.type === 'input' && inputAttrs}
		<!-- Input nodes -->
		{#if inputAttrs.type === 'hidden'}
			<input
				type="hidden"
				name={inputAttrs.name}
				value={inputAttrs.value}
				required={inputAttrs.required}
				disabled={inputAttrs.disabled}
			/>
		{:else if inputAttrs.type === 'submit' || inputAttrs.type === 'button'}
			<button
				type={inputAttrs.type}
				name={inputAttrs.name}
				value={inputAttrs.value}
				disabled={inputAttrs.disabled}
				data-onclicktrigger={inputAttrs.onclickTrigger}
				data-onclick-raw={inputAttrs.onclick}
				onclick={handleButtonClick}
				class="btn-primary w-full disabled:opacity-50"
			>
				{label || inputAttrs.value}
			</button>
		{:else if isProfileTypeSelect()}
			<!-- Custom select dropdown for profile_type -->
			<label for={inputAttrs.name} class="form-label">
				{label}
				{#if inputAttrs.required}
					<span class="text-error-500">*</span>
				{/if}
			</label>
			<select
				name={inputAttrs.name}
				required={inputAttrs.required}
				disabled={inputAttrs.disabled}
				class="input-base disabled:opacity-50"
				class:border-error-500={hasError}
			>
				<option value="">Select profile type...</option>
				<option value="team" selected={inputAttrs.value === 'team'}>Team</option>
				<option value="customer" selected={inputAttrs.value === 'customer'}>Customer</option>
			</select>
		{:else if inputAttrs.type === 'checkbox'}
			<div class="flex items-center">
				<input
					type="checkbox"
					name={inputAttrs.name}
					checked={inputAttrs.value === true}
					required={inputAttrs.required}
					disabled={inputAttrs.disabled}
					class="h-4 w-4 rounded border-input text-primary-500 focus:ring-primary-500"
				/>
				<label for={inputAttrs.name} class="ml-2 text-sm text-theme">
					{label}
				</label>
			</div>
		{:else}
			<label for={inputAttrs.name} class="form-label">
				{label}
				{#if inputAttrs.required}
					<span class="text-error-500">*</span>
				{/if}
			</label>
			<!-- @ts-expect-error: autocomplete string values are valid but TS has strict typing -->
			<input
				type={inputAttrs.type}
				name={inputAttrs.name}
				value={inputAttrs.value || ''}
				required={inputAttrs.required}
				disabled={inputAttrs.disabled}
				{...(autocompleteValue ? { autocomplete: autocompleteValue } : {})}
				pattern={inputAttrs.pattern}
				class="input-base disabled:opacity-50"
				class:border-error-500={hasError}
			/>
		{/if}
	{/if}

	{#if messages.length > 0}
		<div class="mt-1 space-y-1">
			{#each messages as message}
				<p
					class="text-sm"
					class:text-error-600={message.type === 'error'}
					class:text-theme-secondary={message.type === 'info'}
				>
					{message.text}
				</p>
			{/each}
		</div>
	{/if}
</div>
{/if}

<style>
	.form-field {
		margin-bottom: 1rem;
	}

	.qr-code-container {
		display: flex;
		flex-direction: column;
		align-items: center;
		padding: 1rem;
		background-color: var(--theme-card);
		border-radius: 0.5rem;
		border: 1px solid var(--theme-border);
	}

	.qr-code-container img {
		max-width: 100%;
		height: auto;
	}

	.text-node {
		padding: 0.75rem;
		background-color: var(--theme-bg-secondary);
		border-radius: 0.375rem;
		border: 1px solid var(--theme-border);
	}
</style>
