"use client";
import { useCallback, useRef, useState } from "react";
import { Toaster, toast } from "sonner";
import {
  enquirySchema,
  contactResponseSchema,
  interests,
} from "@/lib/contact-schema";
import { Turnstile } from "./turnstile";
import { CHECK_FIELDS, useFieldValidation } from "./use-field-validation";
const fields = [
  {
    name: "name",
    label: "Your Name",
    type: "text",
    autoComplete: "name",
    max: 100,
  },
  {
    name: "email",
    label: "Your Email",
    type: "email",
    autoComplete: "email",
    max: 254,
  },
  {
    name: "phone",
    label: "Your Contact Number",
    type: "tel",
    autoComplete: "tel",
    max: 30,
  },
  {
    name: "subject",
    label: "Subject",
    type: "text",
    autoComplete: "off",
    max: 160,
  },
] as const;
const SECURITY_CHECK = "Please complete the security check before sending.";
export function ContactForm({
  mock,
  siteKey,
}: {
  mock: boolean;
  siteKey?: string;
}) {
  const { errors, flush, onChange, onBlur, report, clear, reset } =
    useFieldValidation(enquirySchema);
  const [status, setStatus] = useState("");
  const [busy, setBusy] = useState(false);
  const [token, setToken] = useState("");
  const [resetKey, setResetKey] = useState(0);
  const pending = useRef(false),
    intent = useRef<{ data: string; id: string } | null>(null);
  if (status === CHECK_FIELDS && !Object.keys(errors).length) setStatus("");
  const onToken = useCallback(
    (value: string) => {
      setToken(value);
      if (value) {
        setStatus((s) => (s === SECURITY_CHECK ? "" : s));
        flush(true);
      }
    },
    [flush],
  );
  async function submit(event: React.SubmitEvent<HTMLFormElement>) {
    event.preventDefault();
    if (pending.current) return;
    const form = event.currentTarget,
      data = Object.fromEntries(new FormData(form));
    const parsed = enquirySchema.safeParse(data);
    if (!parsed.success) {
      const first = report(parsed.error.issues);
      setStatus(CHECK_FIELDS);
      form.querySelector<HTMLInputElement>(`[name="${first}"]`)?.focus();
      return;
    }
    clear();
    if (siteKey && !token) {
      setStatus(SECURITY_CHECK);
      return;
    }
    const serialized = JSON.stringify(parsed.data);
    if (intent.current?.data !== serialized)
      intent.current = { data: serialized, id: crypto.randomUUID() };
    pending.current = true;
    setBusy(true);
    setStatus("");
    try {
      const response = await fetch("/api/contact", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        signal: AbortSignal.timeout(25000),
        body: JSON.stringify({
          ...parsed.data,
          website: data.website || "",
          turnstileToken: token || "contact-unchallenged",
          requestId: intent.current.id,
        }),
      });
      const result = contactResponseSchema.parse(await response.json());
      setStatus(result.message);
      if (response.ok && result.ok) {
        form.reset();
        reset();
        intent.current = null;
        toast.success(result.message);
      }
    } catch {
      setStatus(
        "We could not confirm your enquiry was sent. Your details are still here; please retry or call 6336 4144.",
      );
    } finally {
      pending.current = false;
      setBusy(false);
      setToken("");
      setResetKey((n) => n + 1);
    }
  }
  return (
    <section className="enquiry-section" aria-labelledby="enquiry-title">
      <div className="inner-container">
        <h2 id="enquiry-title">Enquiry Form</h2>
        <form
          className="contact-form"
          noValidate
          onSubmit={submit}
          onChange={onChange}
          onBlur={onBlur}
        >
          <fieldset disabled={busy}>
            <legend className="sr-only">Your enquiry</legend>
            {fields.map((field) => (
              <div className="contact-field form-field" key={field.name}>
                <label htmlFor={`contact-${field.name}`}>
                  {field.label} <span>*</span>
                </label>
                <input
                  id={`contact-${field.name}`}
                  name={field.name}
                  type={field.type}
                  autoComplete={field.autoComplete}
                  maxLength={field.max}
                  required
                  aria-invalid={Boolean(errors[field.name])}
                  aria-describedby={
                    errors[field.name] ? `error-${field.name}` : undefined
                  }
                />
                {errors[field.name] && (
                  <p className="form-error" id={`error-${field.name}`}>
                    {errors[field.name]}
                  </p>
                )}
              </div>
            ))}
            <div className="contact-field form-field">
              <label htmlFor="contact-interest">
                Interested In <span>*</span>
              </label>
              <select
                id="contact-interest"
                name="interest"
                defaultValue=""
                required
                aria-invalid={Boolean(errors.interest)}
                aria-describedby={
                  errors.interest ? "error-interest" : undefined
                }
              >
                <option value="">--- Select Choice ---</option>
                {interests.map((interest) => (
                  <option key={interest}>{interest}</option>
                ))}
              </select>
              {errors.interest && (
                <p className="form-error" id="error-interest">
                  {errors.interest}
                </p>
              )}
            </div>
            <div className="contact-field form-field">
              <label htmlFor="contact-message">
                Your Message <span>*</span>
              </label>
              <textarea
                id="contact-message"
                name="message"
                rows={6}
                maxLength={3000}
                required
                aria-invalid={Boolean(errors.message)}
                aria-describedby={errors.message ? "error-message" : undefined}
              />
              {errors.message && (
                <p className="form-error" id="error-message">
                  {errors.message}
                </p>
              )}
            </div>
            <div className="contact-honeypot" aria-hidden="true">
              <label htmlFor="contact-website">Leave this field empty</label>
              <input
                id="contact-website"
                name="website"
                tabIndex={-1}
                autoComplete="off"
              />
            </div>
            <Turnstile
              mock={mock}
              siteKey={siteKey}
              resetKey={resetKey}
              onToken={onToken}
            />
            <button className="site-button" type="submit">
              {busy ? "Sending…" : "Submit"}
            </button>
          </fieldset>
          <p className="contact-status" role="status" aria-live="polite">
            {status}
          </p>
        </form>
        <Toaster />
      </div>
    </section>
  );
}
