"use client";
import { useCallback, useRef, useState } from "react";
import { useForm, useWatch } from "react-hook-form";
import type { SubmitHandler, UseFormRegister } from "react-hook-form";
import { ArrowRight, LoaderCircle } from "lucide-react";
import { demoCopy } from "@/components/demo/demo-copy";
import DatePicker from "@/components/demo/DatePicker";
import TimePicker from "@/components/demo/TimePicker";
import NumericPhoneInput from "@/components/forms/NumericPhoneInput";
import { useDemoMutation } from "@/features/demo/demo.hooks";
import { demoSchema } from "@/features/demo/demo.schemas";
import { getApiErrorMessage } from "@/lib/api/api-error";
import { showErrorAlert, showSuccessAlert } from "@/lib/alerts";
import {
  getFirstFormError,
  getFormErrors,
  type FormErrors,
} from "@/lib/form-errors";
import type { Locale } from "@/lib/locales";
import { getProductId } from "@/lib/product-map";
import type { ProductSlug } from "@/lib/routes";
const fieldClass =
  "mt-1.5 h-11 w-full rounded-lg border border-[#dde4f1] bg-white px-3 text-[13px] text-[#253052] outline-none transition placeholder:text-[#a7b0c0] focus:border-[#6b72f2] focus:ring-3 focus:ring-[#e9eaff]";
type DemoFormValues = {
  name: string;
  phone: string;
  email: string;
  demo_date: string;
  demo_time: string;
  description: string;
};
function pad(value: number) {
  return String(value).padStart(2, "0");
}
function getTodayString() {
  const today = new Date();
  return `${today.getFullYear()}-${pad(today.getMonth() + 1)}-${pad(today.getDate())}`;
}
function getDefaultValues(): DemoFormValues {
  return {
    name: "",
    phone: "",
    email: "",
    demo_date: getTodayString(),
    demo_time: "09:00",
    description: "",
  };
}
export default function DemoForm({
  locale,
  onSuccess,
  productSlug,
}: {
  locale: Locale;
  onSuccess?: () => void;
  productSlug?: ProductSlug;
}) {
  const copy = demoCopy[locale];
  const demoMutation = useDemoMutation();
  const formRef = useRef<HTMLFormElement | null>(null);
  const [errors, setErrors] = useState<FormErrors>({});
  const { control, register, reset, setValue, handleSubmit } =
    useForm<DemoFormValues>({
      defaultValues: getDefaultValues(),
      mode: "onChange",
    });
  const demoDate = useWatch({ control, name: "demo_date" }) || getTodayString();
  const demoTime = useWatch({ control, name: "demo_time" }) || "09:00";
  const clearFieldError = useCallback((field: string) => {
    setErrors((prev) => {
      if (!prev[field]) return prev;
      const next = { ...prev };
      delete next[field];
      return next;
    });
  }, []);
  const handleDateChange = useCallback(
    (value: string) => {
      setValue("demo_date", value, {
        shouldDirty: true,
        shouldTouch: true,
        shouldValidate: true,
      });
      clearFieldError("demo_date");
    },
    [clearFieldError, setValue],
  );
  const handleTimeChange = useCallback(
    (value: string) => {
      setValue("demo_time", value, {
        shouldDirty: true,
        shouldTouch: true,
        shouldValidate: true,
      });
      clearFieldError("demo_time");
    },
    [clearFieldError, setValue],
  );
  const handleDemoSubmit: SubmitHandler<DemoFormValues> = (values) => {
    if (demoMutation.isPending) return;
    const htmlForm = formRef.current;
    if (!htmlForm) {
      void showErrorAlert("Please refresh the page and try again.", { locale });
      return;
    }
    const formValues = Object.fromEntries(new FormData(htmlForm).entries());
    const parsed = demoSchema.safeParse({
      name: String(formValues.name || values.name || "").trim(),
      phone: String(formValues.phone || values.phone || "").trim(),
      email: String(formValues.email || values.email || "").trim(),
      demo_date: String(formValues.demo_date || values.demo_date || "").trim(),
      demo_time: String(formValues.demo_time || values.demo_time || "").trim(),
      description: String(
        formValues.description || values.description || "",
      ).trim(),
    });
    if (!parsed.success) {
      setErrors(getFormErrors(parsed.error));
      void showErrorAlert(getFirstFormError(parsed.error), { locale });
      return;
    }
    setErrors({});
    demoMutation.mutate(
      {
        ...parsed.data,
        product: getProductId(productSlug),
        demo_time:
          parsed.data.demo_time.length === 5
            ? `${parsed.data.demo_time}:00`
            : parsed.data.demo_time,
      },
      {
        onSuccess: async (response) => {
          await showSuccessAlert(response.message || copy.success, { locale });
          reset(getDefaultValues());
          htmlForm.reset();
          setErrors({});
          onSuccess?.();
        },
        onError: (error) =>
          void showErrorAlert(getApiErrorMessage(error, locale), { locale }),
      },
    );
  };
  return (
    <form
      ref={formRef}
      noValidate
      onSubmit={handleSubmit(handleDemoSubmit)}
      className="rounded-2xl border border-[#e2e7f2] bg-white p-5 shadow-[0_16px_45px_rgba(40,55,105,0.08)] sm:p-6"
    >
      {" "}
      <h2 className="text-xl font-extrabold tracking-[-0.04em] text-[#17214d]">
        {" "}
        {copy.title}{" "}
      </h2>{" "}
      <p className="mt-2 text-[13px] leading-6 text-[#72809a]">
        {" "}
        {copy.subtitle}{" "}
      </p>{" "}
      <div className="mt-5 grid gap-4 sm:grid-cols-2">
        {" "}
        <Field
          error={errors.name}
          label={copy.name}
          name="name"
          register={register}
          onValueChange={clearFieldError}
        />{" "}
        <Field
          error={errors.phone}
          label={copy.phone}
          name="phone"
          numericPhone
          onValueChange={clearFieldError}
        />{" "}
        <Field
          error={errors.email}
          label={copy.email}
          name="email"
          register={register}
          onValueChange={clearFieldError}
          type="email"
        />{" "}
        <DatePicker
          error={errors.demo_date}
          label={copy.date}
          name="demo_date"
          value={demoDate}
          onChange={handleDateChange}
          minDate={getTodayString()}
        />{" "}
        <TimePicker
          error={errors.demo_time}
          label={copy.time}
          name="demo_time"
          value={demoTime}
          selectedDate={demoDate}
          onChange={handleTimeChange}
        />{" "}
      </div>{" "}
      <label
        className="mt-4 block text-[12px] font-bold text-[#34405d]"
        onInput={() => clearFieldError("description")}
      >
        {" "}
        {copy.description}{" "}
        <textarea
          {...register("description")}
          className={`${fieldClass} h-auto resize-y py-3`}
          placeholder={copy.descriptionPlaceholder}
          rows={3}
        />{" "}
        <ErrorText errors={errors.description} />{" "}
      </label>{" "}
      <button
        type="submit"
        disabled={demoMutation.isPending}
        className="mt-5 inline-flex h-12 w-full items-center justify-center gap-2 rounded-lg bg-gradient-to-r from-[#5264ee] to-[#6555e9] px-5 text-[13px] font-bold text-white shadow-[0_8px_18px_rgba(93,91,238,0.24)] disabled:cursor-wait disabled:opacity-70"
      >
        {" "}
        {demoMutation.isPending ? (
          <LoaderCircle size={17} className="animate-spin" />
        ) : (
          <ArrowRight size={17} />
        )}{" "}
        {demoMutation.isPending ? copy.sending : copy.submit}{" "}
      </button>{" "}
      <p className="mt-3 text-[10px] leading-5 text-[#8c97aa]">
        {" "}
        {copy.privacy}{" "}
      </p>{" "}
    </form>
  );
}
function Field({
  error,
  label,
  min,
  name,
  numericPhone = false,
  onValueChange,
  register,
  type = "text",
}: {
  error?: string[];
  label: string;
  min?: string;
  name: keyof DemoFormValues;
  numericPhone?: boolean;
  onValueChange?: (field: string) => void;
  register?: UseFormRegister<DemoFormValues>;
  type?: string;
}) {
  return (
    <label
      className="text-[12px] font-bold text-[#34405d]"
      onInput={() => onValueChange?.(name)}
    >
      {" "}
      {label}{" "}
      {numericPhone ? (
        <NumericPhoneInput className={fieldClass} name={name} />
      ) : (
        <input
          {...register?.(name)}
          className={fieldClass}
          min={min}
          type={type}
        />
      )}{" "}
      <ErrorText errors={error} />{" "}
    </label>
  );
}
function ErrorText({ errors }: { errors?: string[] }) {
  return errors?.[0] ? (
    <span className="mt-1 block text-[11px] text-rose-600"> {errors[0]} </span>
  ) : null;
}
