"use client";

import { useId, useState } from "react";
import type { FormField } from "@/lib/forms/schema";
import { HONEYPOT_FIELD } from "@/lib/forms/schema";
import type { Messages } from "@/lib/i18n/catalog";

type Values = Record<string, string | boolean | string[]>;
const fieldCls = "w-full rounded-md border border-border bg-[var(--background)] px-3 py-2 text-sm aria-[invalid=true]:border-red-600";

/** Visitor-facing form. Posts JSON to the tenant's own origin; validation errors come back per field. */
export function PublicForm({ formId, fields, consentText, token, disabled, text }: { formId: string; fields: FormField[]; consentText: string | null; token: string; disabled: boolean; text: Messages }) {
  const uid = useId();
  const [values, setValues] = useState<Values>(() => Object.fromEntries(fields.map((f) => [f.id, f.type === "checkbox" ? false : f.type === "checkboxGroup" ? [] : ""])));
  const [consent, setConsent] = useState(false);
  const [trap, setTrap] = useState("");
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [state, setState] = useState<"idle" | "sending" | "done">("idle");
  const [message, setMessage] = useState<string | null>(null);
  const set = (id: string, v: string | boolean | string[]) => setValues((s) => ({ ...s, [id]: v }));

  async function submit(e: React.FormEvent) {
    e.preventDefault();
    if (disabled || state === "sending") return;
    setState("sending");
    setErrors({});
    setMessage(null);
    try {
      const res = await fetch(`/api/public/forms/${formId}`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ values, consent, token, [HONEYPOT_FIELD]: trap }) });
      const body = (await res.json().catch(() => ({}))) as { ok?: boolean; message?: string; error?: string; fieldErrors?: Record<string, string> };
      if (res.ok && body.ok) {
        setState("done");
        setMessage(body.message ?? text["forms.thanks"] ?? "");
        return;
      }
      setErrors(body.fieldErrors ?? {});
      setMessage(body.error ?? text["forms.error"] ?? "");
    } catch {
      setMessage(text["forms.network"] ?? "");
    }
    setState("idle");
  }

  if (state === "done") return <p role="status" className="rounded-md border border-border p-4">{message}</p>;

  return (
    <form onSubmit={submit} noValidate className="mx-auto max-w-xl space-y-4 text-left">
      {message ? <p role="alert" className="rounded-md border border-red-600 p-3 text-sm">{message}</p> : null}
      {fields.map((f) => {
        const id = `${uid}-${f.id}`;
        const err = errors[f.id];
        const describedBy = [f.helpText ? `${id}-help` : null, err ? `${id}-err` : null].filter(Boolean).join(" ") || undefined;
        const common = { id, name: f.id, disabled, "aria-invalid": err ? true : undefined, "aria-describedby": describedBy, "aria-required": f.required || undefined } as const;
        const v = values[f.id];
        let control: React.ReactNode;
        if (f.type === "textarea") control = <textarea {...common} rows={5} maxLength={f.maxLength ?? 2000} placeholder={f.placeholder} value={String(v)} onChange={(e) => set(f.id, e.target.value)} className={fieldCls} />;
        else if (f.type === "select") control = <select {...common} value={String(v)} onChange={(e) => set(f.id, e.target.value)} className={fieldCls}><option value="">{text["forms.choose"]}</option>{f.options.map((o) => <option key={o} value={o}>{o}</option>)}</select>;
        else if (f.type === "radio") control = <div role="radiogroup" aria-labelledby={`${id}-label`} className="space-y-1">{f.options.map((o) => <label key={o} className="flex items-center gap-2 text-sm"><input type="radio" name={f.id} disabled={disabled} checked={v === o} onChange={() => set(f.id, o)} />{o}</label>)}</div>;
        else if (f.type === "checkbox") control = <label className="flex items-center gap-2 text-sm"><input {...common} type="checkbox" checked={v === true} onChange={(e) => set(f.id, e.target.checked)} />{f.placeholder || "Yes"}</label>;
        else if (f.type === "checkboxGroup") control = <div role="group" aria-labelledby={`${id}-label`} className="space-y-1">{f.options.map((o) => <label key={o} className="flex items-center gap-2 text-sm"><input type="checkbox" disabled={disabled} checked={(v as string[]).includes(o)} onChange={(e) => set(f.id, e.target.checked ? [...(v as string[]), o] : (v as string[]).filter((x) => x !== o))} />{o}</label>)}</div>;
        else control = <input {...common} type={f.type === "email" ? "email" : f.type === "phone" ? "tel" : f.type === "number" ? "number" : f.type === "date" ? "date" : "text"} inputMode={f.type === "number" ? "decimal" : undefined} autoComplete={f.type === "email" ? "email" : f.type === "phone" ? "tel" : undefined} maxLength={f.type === "text" ? (f.maxLength ?? 200) : undefined} placeholder={f.placeholder} value={String(v)} onChange={(e) => set(f.id, e.target.value)} className={fieldCls} />;
        const grouped = f.type === "radio" || f.type === "checkboxGroup";
        return (
          <div key={f.id} className="space-y-1">
            {grouped ? <span id={`${id}-label`} className="block text-sm font-medium">{f.label}{f.required ? <span aria-hidden> *</span> : null}</span> : <label id={`${id}-label`} htmlFor={id} className="block text-sm font-medium">{f.label}{f.required ? <span aria-hidden> *</span> : null}{f.required ? <span className="sr-only"> (required)</span> : null}</label>}
            {control}
            {f.helpText ? <p id={`${id}-help`} className="text-xs opacity-70">{f.helpText}</p> : null}
            {err ? <p id={`${id}-err`} role="alert" className="text-xs text-red-700">{err}</p> : null}
          </div>
        );
      })}
      {/* Honeypot: hidden from people and assistive tech; bots tend to fill every input. */}
      <div aria-hidden style={{ position: "absolute", left: "-10000px", width: 1, height: 1, overflow: "hidden" }}>
        <label>Leave this empty<input type="text" name={HONEYPOT_FIELD} tabIndex={-1} autoComplete="off" value={trap} onChange={(e) => setTrap(e.target.value)} /></label>
      </div>
      {consentText ? (
        <div className="space-y-1">
          <label className="flex items-start gap-2 text-sm"><input type="checkbox" checked={consent} disabled={disabled} onChange={(e) => setConsent(e.target.checked)} aria-invalid={errors._consent ? true : undefined} aria-describedby={errors._consent ? `${uid}-consent-err` : undefined} /><span>{consentText}</span></label>
          {errors._consent ? <p id={`${uid}-consent-err`} role="alert" className="text-xs text-red-700">{errors._consent}</p> : null}
        </div>
      ) : null}
      <button type="submit" disabled={disabled || state === "sending"} className="blk-btn disabled:opacity-60">{state === "sending" ? text["forms.sending"] : text["forms.submit"]}</button>
    </form>
  );
}
