"use client";

import { useState } from "react";
import { z } from "zod";

const empty = { name: "", email: "", company: "", message: "", website: "" };

const contactSchema = z.object({
  name: z.string().trim().min(1, "Please enter your name").max(200),
  email: z.string().trim().email("Please enter a valid email").max(320),
  company: z.string().trim().max(200).optional(),
  message: z
    .string()
    .trim()
    .min(10, "Tell me a little more about what you need")
    .max(5000),
  website: z.string().optional(),
});

export function ContactForm() {
  const [form, setForm] = useState(empty);
  const [isPending, setIsPending] = useState(false);
  const [isSuccess, setIsSuccess] = useState(false);
  const [serverError, setServerError] = useState<string | null>(null);
  const [fieldErrors, setFieldErrors] = useState<
    Partial<Record<keyof typeof empty, string>>
  >({});

  function update(field: keyof typeof empty) {
    return (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) =>
      setForm((f) => ({ ...f, [field]: e.target.value }));
  }

  async function onSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault();
    setServerError(null);

    const parsed = contactSchema.safeParse(form);
    if (!parsed.success) {
      const flat = parsed.error.flatten().fieldErrors;
      setFieldErrors({
        name: flat.name?.[0],
        email: flat.email?.[0],
        company: flat.company?.[0],
        message: flat.message?.[0],
        website: flat.website?.[0],
      });
      return;
    }

    setFieldErrors({});
    setIsPending(true);

    try {
      const res = await fetch("/api/contact", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify(form),
      });

      const data = (await res.json()) as
        | { ok: true }
        | {
            ok: false;
            message?: string;
            fieldErrors?: Record<string, string[]>;
          };

      if (!res.ok || !data.ok) {
        if ("fieldErrors" in data && data.fieldErrors) {
          setFieldErrors({
            name: data.fieldErrors.name?.[0],
            email: data.fieldErrors.email?.[0],
            company: data.fieldErrors.company?.[0],
            message: data.fieldErrors.message?.[0],
            website: data.fieldErrors.website?.[0],
          });
        }
        setServerError(
          ("message" in data ? data.message : undefined) ??
            "Something went wrong sending that. Please try again.",
        );
        return;
      }

      setIsSuccess(true);
      setForm(empty);
    } catch {
      setServerError("Something went wrong sending that. Please try again.");
    } finally {
      setIsPending(false);
    }
  }

  if (isSuccess) {
    return (
      <div className="border-accent-border bg-accent-bg-soft border p-10 text-center">
        <div className="border-accent-border bg-accent-bg text-accent mx-auto flex h-12 w-12 items-center justify-center border">
          <svg viewBox="0 0 24 24" fill="none" className="h-6 w-6">
            <path
              d="M5 13l4 4L19 7"
              stroke="currentColor"
              strokeWidth="2"
              strokeLinecap="round"
              strokeLinejoin="round"
            />
          </svg>
        </div>
        <h3 className="text-text mt-5 text-xl font-semibold">
          Message received.
        </h3>
        <p className="text-muted mx-auto mt-2 max-w-sm text-sm">
          Thank you for reaching out. I will get back to you shortly. This
          message went straight to Hadlock. No third-party form service handled
          it.
        </p>
        <button
          type="button"
          onClick={() => {
            setIsSuccess(false);
            setServerError(null);
            setFieldErrors({});
          }}
          className="text-accent hover:text-accent-faint mt-6 text-sm font-medium transition"
        >
          Send another →
        </button>
      </div>
    );
  }

  return (
    <form
      onSubmit={onSubmit}
      className="grid gap-5 text-left sm:grid-cols-2"
      noValidate
    >
      <Field label="Name" error={fieldErrors?.name?.[0]}>
        <input
          type="text"
          autoComplete="name"
          value={form.name}
          onChange={update("name")}
          className={inputClass}
          placeholder="Your name"
        />
      </Field>

      <Field label="Email" error={fieldErrors?.email?.[0]}>
        <input
          type="email"
          autoComplete="email"
          value={form.email}
          onChange={update("email")}
          className={inputClass}
          placeholder="you@company.com"
        />
      </Field>

      <div className="sm:col-span-2">
        <Field label="Company" optional error={fieldErrors?.company?.[0]}>
          <input
            type="text"
            autoComplete="organization"
            value={form.company}
            onChange={update("company")}
            className={inputClass}
            placeholder="Where you work (optional)"
          />
        </Field>
      </div>

      <div className="sm:col-span-2">
        <Field label="What do you need?" error={fieldErrors?.message?.[0]}>
          <textarea
            rows={5}
            value={form.message}
            onChange={update("message")}
            className={`${inputClass} resize-y`}
            placeholder="Networks, servers, a website, a store, or something that does not exist yet. Tell me what you run and where it hurts."
          />
        </Field>
      </div>

      {/* A honeypot. Hidden from humans and off the tab order */}
      <div className="hidden" aria-hidden="true">
        <label>
          Website
          <input
            type="text"
            tabIndex={-1}
            autoComplete="off"
            value={form.website}
            onChange={update("website")}
          />
        </label>
      </div>

      <div className="flex flex-col gap-3 sm:col-span-2 sm:flex-row sm:items-center">
        <button
          type="submit"
          disabled={isPending}
          className="bg-accent text-on-accent hover:bg-accent-hover px-7 py-3.5 text-sm font-semibold transition disabled:cursor-not-allowed disabled:opacity-60"
        >
          {isPending ? "Sending..." : "Send message"}
        </button>
        {serverError && <p className="text-sm text-red-400">{serverError}</p>}
      </div>
    </form>
  );
}

const inputClass =
  "w-full border border-border bg-surface/40 px-4 py-3 text-sm text-text placeholder:text-faint transition focus:border-accent/60 focus:bg-surface/60 focus:ring-2 focus:ring-accent/20 focus:outline-none";

function Field({
  label,
  optional,
  error,
  children,
}: {
  label: string;
  optional?: boolean;
  error?: string;
  children: React.ReactNode;
}) {
  return (
    <label className="block">
      <span className="text-text-secondary mb-1.5 flex items-center gap-2 text-sm font-medium">
        {label}
        {optional && (
          <span className="text-faint text-xs font-normal">optional</span>
        )}
      </span>
      {children}
      {error && (
        <span className="mt-1.5 block text-xs text-red-400">{error}</span>
      )}
    </label>
  );
}
