<script lang="ts">
  // 공용 텍스트 입력. label/error/hint를 SSR-safe id로 ARIA 연결.
  // - value는 $bindable
  // - error 전달 시 빨간 보더 + 메시지 + aria-invalid
  // - leading/trailing 아이콘은 lucide 컴포넌트 참조로 전달
  import type { HTMLInputAttributes } from 'svelte/elements';

  // lucide-svelte v0.400 legacy 타입 호환을 위한 임시 IconComponent.
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  type IconComponent = any;

  interface Props {
    value?: string;
    label?: string;
    error?: string;
    hint?: string;
    leadingIcon?: IconComponent;
    trailingIcon?: IconComponent;
    type?: 'text' | 'password' | 'email' | 'url' | 'tel' | 'number' | 'search';
    placeholder?: string;
    id?: string;
    name?: string;
    disabled?: boolean;
    readonly?: boolean;
    required?: boolean;
    autocomplete?: HTMLInputAttributes['autocomplete'];
    class?: string;
  }

  let {
    value = $bindable(''),
    label,
    error,
    hint,
    leadingIcon: LeadingIcon,
    trailingIcon: TrailingIcon,
    type = 'text',
    placeholder,
    id: idProp,
    name,
    disabled = false,
    readonly = false,
    required = false,
    autocomplete,
    class: className = '',
    ...rest
  }: Props = $props();

  // SSR-safe 자동 id 생성 (Svelte 5.20+)
  const autoId = $props.id();
  let inputId = $derived(idProp ?? `input-${autoId}`);
  let hintId = $derived(`${inputId}-hint`);
  let errorId = $derived(`${inputId}-error`);
  let describedBy = $derived(
    [error ? errorId : null, hint && !error ? hintId : null].filter(Boolean).join(' ') || undefined
  );

  let inputClass = $derived(
    [
      'w-full h-9 rounded-md text-sm bg-bg text-text placeholder:text-faint',
      'border outline-none transition-colors',
      error
        ? 'border-error focus:border-error focus:ring-2 focus:ring-error/30'
        : 'border-default focus:border-accent focus:ring-2 focus:ring-accent-ring',
      'disabled:opacity-50 disabled:cursor-not-allowed',
      LeadingIcon ? 'pl-9' : 'px-3',
      TrailingIcon ? 'pr-9' : LeadingIcon ? 'pr-3' : '',
    ].join(' ')
  );
</script>

<div class={'flex flex-col gap-1 ' + className}>
  {#if label}
    <label for={inputId} class="text-xs font-medium text-dim">
      {label}
      {#if required}<span class="text-error">*</span>{/if}
    </label>
  {/if}

  <div class="relative">
    {#if LeadingIcon}
      <div class="absolute inset-y-0 left-0 flex items-center pl-2.5 text-faint pointer-events-none">
        <LeadingIcon size={16} />
      </div>
    {/if}

    <input
      id={inputId}
      {type}
      {name}
      bind:value
      {placeholder}
      {disabled}
      {readonly}
      {required}
      {autocomplete}
      class={inputClass}
      aria-invalid={error ? 'true' : undefined}
      aria-describedby={describedBy}
      {...rest}
    />

    {#if TrailingIcon}
      <div class="absolute inset-y-0 right-0 flex items-center pr-2.5 text-faint pointer-events-none">
        <TrailingIcon size={16} />
      </div>
    {/if}
  </div>

  {#if error}
    <p id={errorId} class="text-xs text-error">{error}</p>
  {:else if hint}
    <p id={hintId} class="text-xs text-faint">{hint}</p>
  {/if}
</div>
