"use client";

import { useEffect, useState, type ChangeEvent, type FormEvent } from "react";
import { ChevronDownIcon } from "@/components/ui/Icons";
import { cn } from "@/lib/cn";
import { contactForm } from "@/data/home";
import { useAppDispatch, useAppSelector } from "@/store/hooks";
import { resetContact, submitContactForm } from "@/store/slices/contactSlice";

const SUCCESS_VISIBLE_MS = 5000;

const fieldClasses =
  "w-full rounded-lg border border-slate-200 bg-slate-50 px-4 py-[14px] text-[0.95rem] outline-none transition-[border-color,box-shadow,background-color] duration-200 placeholder:text-slate-400 placeholder:opacity-100 focus:border-[#a5b4fc] focus:bg-white focus:shadow-[0_0_0_3px_rgba(165,180,252,0.15)]";

const initialValues = {
  firstName: "",
  lastName: "",
  email: "",
  phone: "",
  companySize: "",
  topic: "",
  message: "",
};

type FormValues = typeof initialValues;

function validate(values: FormValues): string | null {
  const digits = values.phone.replace(/\D/g, "");
  if (digits.length < contactForm.phoneMinDigits || digits.length > contactForm.phoneMaxDigits) {
    return `Phone number must contain between ${contactForm.phoneMinDigits} and ${contactForm.phoneMaxDigits} digits.`;
  }
  if (values.message.trim().length < contactForm.messageMinLength) {
    return `Message must be at least ${contactForm.messageMinLength} characters long.`;
  }
  return null;
}

const labelFor = (options: ReadonlyArray<{ value: string; label: string }>, value: string) =>
  options.find((option) => option.value === value)?.label ?? value;

function Field({
  label,
  htmlFor,
  children,
  isRequired = true,
}: {
  label: string;
  htmlFor: string;
  children: React.ReactNode;
  isRequired?: boolean;
}) {
  return (
    <div className="flex flex-col gap-2">
      <label htmlFor={htmlFor} className="text-[0.88rem] font-semibold text-ink">
        {label} <span className="text-[#ef4444]">{isRequired ? "*" : ""}</span>
      </label>
      {children}
    </div>
  );
}

function SelectField({
  id,
  value,
  onChange,
  placeholder,
  options,
}: {
  id: string;
  value: string;
  onChange: (event: ChangeEvent<HTMLSelectElement>) => void;
  placeholder: string;
  options: ReadonlyArray<{ value: string; label: string }>;
}) {
  return (
    <div className="relative">
      <select
        id={id}
        value={value}
        onChange={onChange}
        required
        className={cn(
          fieldClasses,
          "cursor-pointer appearance-none pr-10",
          value ? "text-ink" : "text-slate-400",
        )}
      >
        <option value="" disabled>
          {placeholder}
        </option>
        {options.map((option) => (
          <option key={option.value} value={option.value}>
            {option.label}
          </option>
        ))}
      </select>
      <ChevronDownIcon className="pointer-events-none absolute top-1/2 right-4 -translate-y-1/2 text-slate-500" />
    </div>
  );
}

export function ContactForm() {
  const dispatch = useAppDispatch();
  const { status, error, lastSubmission } = useAppSelector((state) => state.contact);
  const [values, setValues] = useState<FormValues>(initialValues);
  const [validationError, setValidationError] = useState<string | null>(null);

  // After a successful send, show the thank-you card briefly, then show a fresh form.
  useEffect(() => {
    if (status !== "succeeded") return;
    const timer = setTimeout(() => {
      setValues(initialValues);
      dispatch(resetContact());
    }, SUCCESS_VISIBLE_MS);
    return () => clearTimeout(timer);
  }, [status, dispatch]);

  const set =
    (key: keyof FormValues) =>
      (event: ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) =>
        setValues((current) => ({ ...current, [key]: event.target.value }));

  const submitting = status === "submitting";
  const messageLength = values.message.length;

  const onSubmit = (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    const problem = validate(values);
    setValidationError(problem);
    if (problem) return;

    dispatch(
      submitContactForm({
        fn: values.firstName.trim(),
        ln: values.lastName.trim(),
        e: values.email.trim(),
        p: values.phone.trim(),
        cs: labelFor(contactForm.companySizes, values.companySize),
        t: labelFor(contactForm.topics, values.topic),
        m: values.message.trim(),
      }),
    );
  };

  if (status === "succeeded" && lastSubmission) {
    return (
      <div
        role="status"
        className="mt-[10px] animate-fade-in rounded-xl border border-slate-200 bg-slate-50 px-5 py-[60px] text-center"
      >
        <div className="mb-6 text-[3rem] text-accent">✓</div>
        <h3 className="mb-3 text-[1.8rem] font-semibold text-ink">
          Thank you, {lastSubmission.firstName}!
        </h3>
        <p className="mx-auto max-w-[480px] text-[1.05rem] leading-[1.6] text-slate-500">
          We have received your message regarding <strong>{lastSubmission.topic}</strong> and will
          get back to you at <strong>{lastSubmission.email}</strong> as soon as possible.
        </p>
      </div>
    );
  }

  const errorMessage = validationError ?? (status === "failed" ? error : null);

  return (
    <form onSubmit={onSubmit} className="flex flex-col gap-6">
      <div className="grid grid-cols-2 gap-5 max-[601px]:grid-cols-1 max-[601px]:gap-6">
        <Field label="First name" htmlFor="form-first-name">
          <input
            id="form-first-name"
            type="text"
            placeholder="First name"
            required
            value={values.firstName}
            onChange={set("firstName")}
            className={cn(fieldClasses, "text-ink")}
          />
        </Field>
        <Field label="Last name" htmlFor="form-last-name">
          <input
            id="form-last-name"
            type="text"
            placeholder="Last name"
            required
            value={values.lastName}
            onChange={set("lastName")}
            className={cn(fieldClasses, "text-ink")}
          />
        </Field>
      </div>

      <div className="grid grid-cols-2 gap-5 max-[601px]:grid-cols-1 max-[601px]:gap-6">
        <Field label="Work email" htmlFor="form-email">
          <input
            id="form-email"
            type="email"
            placeholder="you@company.com"
            required
            value={values.email}
            onChange={set("email")}
            className={cn(fieldClasses, "text-ink")}
          />
        </Field>
        <Field label="Work phone" htmlFor="form-phone">
          <input
            id="form-phone"
            type="tel"
            inputMode="tel"
            placeholder="+5 (555) 555-5555"
            required
            value={values.phone}
            onChange={set("phone")}
            className={cn(fieldClasses, "text-ink")}
          />
        </Field>
      </div>

      <div className="grid grid-cols-2 gap-5 max-[601px]:grid-cols-1 max-[601px]:gap-6">
        <Field label="Company size" htmlFor="form-company-size" isRequired={false}>
          <SelectField
            id="form-company-size"
            value={values.companySize}
            onChange={set("companySize")}
            placeholder="Select company size"
            options={contactForm.companySizes}
          />
        </Field>
        <Field label="Conversation topic" htmlFor="form-topic">
          <SelectField
            id="form-topic"
            value={values.topic}
            onChange={set("topic")}
            placeholder="Select a topic"
            options={contactForm.topics}
          />
        </Field>
      </div>

      <Field label="Compose message " htmlFor="form-message">
        <textarea
          id="form-message"
          placeholder="Write a message..."
          required
          value={values.message}
          onChange={set("message")}
          className={cn(fieldClasses, "min-h-[140px] resize-y leading-[1.5] text-ink")}
        />
        <div className="mt-1 flex justify-between text-xs text-slate-500">
          <span
            className={cn(
              messageLength > 0 && messageLength < contactForm.messageMinLength && "text-red-500",
            )}
          >
            Minimum {contactForm.messageMinLength} characters
          </span>
          <span className={cn(messageLength > contactForm.messageMaxLength && "text-red-500")}>
            {messageLength}/{contactForm.messageMaxLength}
          </span>
        </div>
      </Field>

      {errorMessage && (
        <p role="alert" className="text-sm whitespace-pre-line text-red-500">
          {errorMessage}
        </p>
      )}

      <button
        type="submit"
        disabled={submitting}
        className={cn(
          "w-full rounded-lg bg-[#e8f0fe] px-6 py-4 text-center text-[1.05rem] font-medium text-accent shadow-[0_4px_6px_-1px_rgba(0,0,0,0.05)] transition-[background-color,transform,box-shadow] duration-200",
          "hover:-translate-y-px hover:bg-[#dbeafe] hover:shadow-[0_10px_15px_-3px_rgba(0,0,0,0.05)] active:translate-y-px",
          submitting && "cursor-not-allowed opacity-70",
        )}
      >
        {submitting ? "Sending..." : "Send message"}
      </button>
    </form>
  );
}
