"use client";

import type { FieldConfig, SelectOption } from "@/types/form";
import type { UseFormRegister, FieldValues, FieldErrors } from "react-hook-form";

interface FieldRendererProps {
  field: FieldConfig;
  register: UseFormRegister<FieldValues>;
  errors: FieldErrors;
  /** For readonly display fields, the value to render. */
  readonlyValue?: unknown;
  /**
   * Options resolved at runtime (from /api/data). When `field.optionGroupId`
   * is set, look up options here first; fall back to the field's hard-coded
   * `options` array if absent.
   */
  resolvedOptions?: SelectOption[];
}

/**
 * Renders a single field appropriate to its `type`. All inputs share a common
 * accessibility scaffold: a real <label htmlFor>, aria-describedby pointing
 * to help/error text, aria-invalid set when in error, and visible focus.
 *
 * Currency, percent, and number all use input type="number" with appropriate
 * `step` and inputMode for mobile keyboards. We keep formatting light — the
 * server is the source of truth for normalization.
 */
export function FieldRenderer({
  field,
  register,
  errors,
  readonlyValue,
  resolvedOptions,
}: FieldRendererProps) {
  const id = `field-${field.name}`;
  const helpId = field.help ? `${id}-help` : undefined;
  const errorId = errors[field.name] ? `${id}-error` : undefined;
  const describedBy = [helpId, errorId].filter(Boolean).join(" ") || undefined;
  const errorMsg = errors[field.name]?.message as string | undefined;
  const effectiveOptions = resolvedOptions ?? field.options ?? [];

  const baseInputClass =
    "w-full rounded-md border border-stone-300 bg-white px-3 py-2 text-stone-900 " +
    "placeholder:text-stone-400 shadow-sm transition " +
    "focus:border-leaf-600 focus:outline-none focus:ring-2 focus:ring-leaf-500/40 " +
    "disabled:bg-stone-50 disabled:text-stone-500 " +
    "aria-invalid:border-red-500 aria-invalid:ring-red-500/30";

  // ── Readonly display field ──────────────────────────────────────────────
  if (field.type === "readonly") {
    // Look up the human label if this readonly references an option-group field.
    const opt = effectiveOptions.find((o) => o.value === readonlyValue);
    const display =
      readonlyValue == null || readonlyValue === ""
        ? "—"
        : opt?.label ?? String(readonlyValue);
    return (
      <div className="space-y-1">
        <Label id={id} field={field} />
        <div
          id={id}
          role="textbox"
          aria-readonly="true"
          className="rounded-md border border-stone-200 bg-stone-50 px-3 py-2 text-stone-700"
        >
          {display}
        </div>
        {field.help && <Help id={helpId!}>{field.help}</Help>}
      </div>
    );
  }

  // ── Boolean (checkbox) ──────────────────────────────────────────────────
  if (field.type === "boolean") {
    return (
      <div className="flex items-start gap-3 py-1">
        <input
          id={id}
          type="checkbox"
          aria-describedby={describedBy}
          aria-invalid={errorMsg ? true : undefined}
          {...register(field.name)}
          className="mt-0.5 h-4 w-4 rounded border-stone-400 text-leaf-700 focus:ring-2 focus:ring-leaf-500/40"
        />
        <div className="flex-1">
          <label htmlFor={id} className="font-medium text-stone-800 cursor-pointer">
            {field.label}
            {field.required && <RequiredMark />}
          </label>
          {field.help && <Help id={helpId!}>{field.help}</Help>}
          {errorMsg && <ErrorText id={errorId!}>{errorMsg}</ErrorText>}
        </div>
      </div>
    );
  }

  // ── Textarea ────────────────────────────────────────────────────────────
  if (field.type === "textarea") {
    return (
      <div className="space-y-1">
        <Label id={id} field={field} />
        <textarea
          id={id}
          aria-describedby={describedBy}
          aria-invalid={errorMsg ? true : undefined}
          aria-required={field.required || undefined}
          placeholder={field.placeholder}
          maxLength={field.maxLength}
          rows={4}
          {...register(field.name, { required: field.required })}
          className={baseInputClass + " min-h-[7rem] leading-6"}
        />
        {field.help && <Help id={helpId!}>{field.help}</Help>}
        {errorMsg && <ErrorText id={errorId!}>{errorMsg}</ErrorText>}
      </div>
    );
  }

  // ── Select ──────────────────────────────────────────────────────────────
  if (field.type === "select") {
    return (
      <div className="space-y-1">
        <Label id={id} field={field} />
        <select
          id={id}
          aria-describedby={describedBy}
          aria-invalid={errorMsg ? true : undefined}
          aria-required={field.required || undefined}
          {...register(field.name, { required: field.required })}
          className={baseInputClass + " bg-white"}
          defaultValue=""
        >
          <option value="" disabled>
            Select…
          </option>
          {effectiveOptions.map((o) => (
            <option key={o.value} value={o.value}>
              {o.label}
            </option>
          ))}
        </select>
        {field.help && <Help id={helpId!}>{field.help}</Help>}
        {errorMsg && <ErrorText id={errorId!}>{errorMsg}</ErrorText>}
      </div>
    );
  }

  // ── Multiselect (rendered as a checkbox group) ─────────────────────────
  if (field.type === "multiselect") {
    return (
      <fieldset
        aria-describedby={describedBy}
        aria-invalid={errorMsg ? true : undefined}
        className="space-y-2"
      >
        <legend className="block text-sm font-medium text-stone-800">
          {field.label}
          {field.required && <RequiredMark />}
        </legend>
        <div className="grid grid-cols-1 gap-1.5 sm:grid-cols-2">
          {effectiveOptions.map((o, idx) => {
            const optId = `${id}-${idx}`;
            return (
              <label
                key={o.value}
                htmlFor={optId}
                className="flex items-start gap-2 rounded border border-stone-200 px-3 py-2 hover:bg-stone-50 cursor-pointer"
              >
                <input
                  id={optId}
                  type="checkbox"
                  value={o.value}
                  {...register(field.name)}
                  className="mt-0.5 h-4 w-4 rounded border-stone-400 text-leaf-700 focus:ring-2 focus:ring-leaf-500/40"
                />
                <span className="text-sm text-stone-800">{o.label}</span>
              </label>
            );
          })}
        </div>
        {field.help && <Help id={helpId!}>{field.help}</Help>}
        {errorMsg && <ErrorText id={errorId!}>{errorMsg}</ErrorText>}
      </fieldset>
    );
  }

  // ── File ────────────────────────────────────────────────────────────────
  if (field.type === "file") {
    return (
      <div className="space-y-1">
        <Label id={id} field={field} />
        <input
          id={id}
          type="file"
          aria-describedby={describedBy}
          aria-invalid={errorMsg ? true : undefined}
          aria-required={field.required || undefined}
          {...register(field.name, { required: field.required })}
          className="block w-full text-sm text-stone-700 file:mr-3 file:rounded-md file:border-0 file:bg-leaf-100 file:px-3 file:py-2 file:text-leaf-800 file:text-sm file:font-medium hover:file:bg-leaf-200 cursor-pointer"
        />
        {field.help && <Help id={helpId!}>{field.help}</Help>}
        {errorMsg && <ErrorText id={errorId!}>{errorMsg}</ErrorText>}
      </div>
    );
  }

  // ── Numeric family: number / currency / percent ─────────────────────────
  if (field.type === "number" || field.type === "currency" || field.type === "percent") {
    const prefix = field.type === "currency" ? "$" : null;
    const suffix = field.type === "percent" ? "%" : null;
    return (
      <div className="space-y-1">
        <Label id={id} field={field} />
        <div className="relative">
          {prefix && (
            <span
              aria-hidden
              className="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-stone-500"
            >
              {prefix}
            </span>
          )}
          <input
            id={id}
            type="number"
            inputMode="decimal"
            aria-describedby={describedBy}
            aria-invalid={errorMsg ? true : undefined}
            aria-required={field.required || undefined}
            placeholder={field.placeholder}
            step={field.step ?? (field.type === "number" ? 1 : 0.01)}
            min={field.min}
            max={field.max}
            {...register(field.name, {
              required: field.required,
              valueAsNumber: true,
            })}
            className={
              baseInputClass +
              (prefix ? " pl-7" : "") +
              (suffix ? " pr-8" : "")
            }
          />
          {suffix && (
            <span
              aria-hidden
              className="pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-stone-500"
            >
              {suffix}
            </span>
          )}
        </div>
        {field.help && <Help id={helpId!}>{field.help}</Help>}
        {errorMsg && <ErrorText id={errorId!}>{errorMsg}</ErrorText>}
      </div>
    );
  }

  // ── Default: text-like (text / email / phone / date) ────────────────────
  const inputType =
    field.type === "email" ? "email" :
    field.type === "phone" ? "tel" :
    field.type === "date" ? "date" :
    "text";

  return (
    <div className="space-y-1">
      <Label id={id} field={field} />
      <input
        id={id}
        type={inputType}
        aria-describedby={describedBy}
        aria-invalid={errorMsg ? true : undefined}
        aria-required={field.required || undefined}
        placeholder={field.placeholder}
        maxLength={field.maxLength}
        autoComplete={
          field.type === "email" ? "email" :
          field.type === "phone" ? "tel" :
          undefined
        }
        {...register(field.name, { required: field.required })}
        className={baseInputClass}
      />
      {field.help && <Help id={helpId!}>{field.help}</Help>}
      {errorMsg && <ErrorText id={errorId!}>{errorMsg}</ErrorText>}
    </div>
  );
}

function Label({ id, field }: { id: string; field: FieldConfig }) {
  return (
    <label htmlFor={id} className="block text-sm font-medium text-stone-800">
      {field.label}
      {field.required && <RequiredMark />}
    </label>
  );
}

function RequiredMark() {
  return (
    <span aria-label="required" className="ml-1 text-red-600">
      *
    </span>
  );
}

function Help({ id, children }: { id: string; children: React.ReactNode }) {
  return (
    <p id={id} className="text-xs text-stone-600">
      {children}
    </p>
  );
}

function ErrorText({ id, children }: { id: string; children: React.ReactNode }) {
  return (
    <p id={id} role="alert" className="text-xs font-medium text-red-700">
      {children}
    </p>
  );
}
