"use client";

import { FormEvent, useState } from "react";
import { submitDynamicForm, submitDynamicFormMultipart, type PublicFormFieldDto } from "@/lib/api";
import { Button } from "@/components/ui/Button";

type Status = "idle" | "submitting" | "success" | "error";

export default function DynamicForm({
  formKey,
  fields,
  successMessage
}: {
  formKey: string;
  fields: PublicFormFieldDto[];
  successMessage?: string | null;
}) {
  const [status, setStatus] = useState<Status>("idle");
  const [error, setError] = useState<string | null>(null);

  async function handleSubmit(e: FormEvent<HTMLFormElement>) {
    e.preventDefault();
    setStatus("submitting");
    setError(null);

    const formEl = e.currentTarget;
    const data = new FormData(formEl);
    const fileField = fields.find((f) => f.fieldType === "file");

    try {
      if (fileField) {
        // Backend expects every non-file field as its own part (named by fieldKey) plus at
        // most one file part under the fixed name "file" — see
        // PublicWebController.submitMultipart. Rebuilding the FormData (rather than reusing
        // `data` as-is) lets the file field's own fieldKey stay whatever the schema calls it.
        const multipartData = new FormData();
        for (const field of fields) {
          if (field === fileField) continue;
          const value = field.fieldType === "checkbox" ? (data.get(field.fieldKey) === "on" ? "true" : "false") : String(data.get(field.fieldKey) || "");
          multipartData.append(field.fieldKey, value);
        }
        const file = data.get(fileField.fieldKey);
        if (file instanceof File && file.size > 0) {
          multipartData.append("file", file);
        }
        await submitDynamicFormMultipart(formKey, multipartData);
      } else {
        const payload: Record<string, unknown> = {};
        for (const field of fields) {
          payload[field.fieldKey] =
            field.fieldType === "checkbox" ? data.get(field.fieldKey) === "on" : String(data.get(field.fieldKey) || "");
        }
        await submitDynamicForm(formKey, payload);
      }
      setStatus("success");
      formEl.reset();
    } catch (err) {
      setStatus("error");
      setError(err instanceof Error ? err.message : "Something went wrong. Please try again.");
    }
  }

  if (status === "success") {
    return (
      <div className="rounded-xl2 border border-neutral-200 bg-neutral-100 p-8 text-center">
        <p className="text-neutral-900 font-medium">{successMessage || "Thanks — your submission is in."}</p>
      </div>
    );
  }

  return (
    <form onSubmit={handleSubmit} className="flex flex-col gap-5">
      {fields.map((field) => (
        <FormField key={field.fieldKey} field={field} />
      ))}

      {error ? <p className="text-sm text-red-600">{error}</p> : null}

      <Button type="submit" disabled={status === "submitting"}>
        {status === "submitting" ? "Submitting…" : "Submit"}
      </Button>
    </form>
  );
}

function FormField({ field }: { field: PublicFormFieldDto }) {
  const labelEl = (
    <label className="text-xs font-semibold uppercase tracking-wide text-neutral-600">
      {field.label}
      {field.isRequired ? " *" : ""}
    </label>
  );

  if (field.fieldType === "textarea") {
    return (
      <div>
        {labelEl}
        <textarea
          name={field.fieldKey}
          required={field.isRequired}
          rows={5}
          className="mt-2 w-full rounded-lg border border-neutral-300 px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-accent-500"
        />
      </div>
    );
  }

  if (field.fieldType === "checkbox") {
    return (
      <label className="flex items-start gap-3 text-sm text-neutral-700">
        <input
          type="checkbox"
          name={field.fieldKey}
          required={field.isRequired}
          className="mt-1 h-4 w-4 rounded border-neutral-300 text-accent-500 focus:ring-accent-500"
        />
        <span>
          {field.label}
          {field.isRequired ? " *" : ""}
        </span>
      </label>
    );
  }

  if (field.fieldType === "file") {
    return (
      <div>
        {labelEl}
        <input
          name={field.fieldKey}
          type="file"
          required={field.isRequired}
          accept=".pdf,.png,.jpg,.jpeg,.doc,.docx"
          className="mt-2 w-full text-sm text-neutral-600 file:mr-4 file:rounded-full file:border-0 file:bg-neutral-100 file:px-4 file:py-2 file:text-xs file:font-semibold file:uppercase file:tracking-wide"
        />
      </div>
    );
  }

  return (
    <div>
      {labelEl}
      <input
        name={field.fieldKey}
        type={field.fieldType || "text"}
        required={field.isRequired}
        className="mt-2 w-full rounded-lg border border-neutral-300 px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-accent-500"
      />
    </div>
  );
}
