<script lang="ts">
  // v0.2 Phase 5 primitive — labelled form field. Two modes:
  //   1. Plain mode (default): native <input>/<textarea> with label
  //      + optional error text. Used by 80% of Settings rows.
  //   2. Formsnap mode: when given a `form` prop, mounts inside a
  //      formsnap <Field>/<Control>/<Label>/<FieldErrors> tree so the
  //      Superforms validation flow drives error rendering.
  //
  // The two modes share the same visible markup so a row can opt
  // into Formsnap without changing layout.
  import { Field, Control, Label as FsLabel, FieldErrors } from "formsnap";
  import type { Snippet } from "svelte";

  type FieldType = "text" | "email" | "password" | "url" | "number" | "textarea";

  interface Props {
    label: string;
    name?: string;
    type?: FieldType;
    value?: string | number;
    placeholder?: string;
    description?: string;
    error?: string;
    disabled?: boolean;
    required?: boolean;
    rows?: number;
    form?: unknown;          // SuperForm — kept loose to avoid leaking generic
    children?: Snippet;
  }

  let {
    label,
    name,
    type = "text" as FieldType,
    value = $bindable(""),
    placeholder,
    description,
    error,
    disabled = false,
    required = false,
    rows = 3,
    form,
    children,
  }: Props = $props();

  const id = $derived(name ? `lumotia-field-${name}` : undefined);
</script>

{#if form && name}
  <Field form={form as never} {name}>
    <Control>
      {#snippet children({ props })}
        <div class="lumotia-field flex flex-col gap-1.5">
          <FsLabel class="text-[12px] font-medium text-text-secondary uppercase tracking-wider">{label}</FsLabel>
          {#if description}
            <p class="text-[12px] text-text-tertiary -mt-1">{description}</p>
          {/if}
          {#if type === "textarea"}
            <textarea
              {...props}
              bind:value
              {placeholder}
              {disabled}
              {required}
              {rows}
              class="bg-bg-input border border-border-subtle rounded-md px-3 py-2 text-[13px] text-text resize-y focus:outline-none focus:border-accent"
            ></textarea>
          {:else}
            <input
              {...props}
              bind:value
              {type}
              {placeholder}
              {disabled}
              {required}
              class="bg-bg-input border border-border-subtle rounded-md px-3 py-2 text-[13px] text-text focus:outline-none focus:border-accent"
            />
          {/if}
          <FieldErrors class="text-[12px] text-danger" />
        </div>
      {/snippet}
    </Control>
  </Field>
{:else}
  <div class="lumotia-field flex flex-col gap-1.5">
    <label
      for={id}
      class="text-[12px] font-medium text-text-secondary uppercase tracking-wider"
    >{label}</label>
    {#if description}
      <p class="text-[12px] text-text-tertiary -mt-1">{description}</p>
    {/if}
    {#if type === "textarea"}
      <textarea
        {id}
        {name}
        bind:value
        {placeholder}
        {disabled}
        {required}
        {rows}
        class="bg-bg-input border border-border-subtle rounded-md px-3 py-2 text-[13px] text-text resize-y focus:outline-none focus:border-accent"
        aria-invalid={error ? "true" : undefined}
        aria-describedby={error ? `${id}-err` : undefined}
      ></textarea>
    {:else}
      <input
        {id}
        {name}
        bind:value
        {type}
        {placeholder}
        {disabled}
        {required}
        class="bg-bg-input border border-border-subtle rounded-md px-3 py-2 text-[13px] text-text focus:outline-none focus:border-accent"
        aria-invalid={error ? "true" : undefined}
        aria-describedby={error ? `${id}-err` : undefined}
      />
    {/if}
    {#if error}
      <p id={`${id}-err`} class="text-[12px] text-danger">{error}</p>
    {/if}
    {#if children}
      <div>{@render children()}</div>
    {/if}
  </div>
{/if}
