import { useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";

import { useFieldDefinitions } from "../api/queries";
import { FieldInput } from "./field-input";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";

export type ObjectCore = {
  object_number: string;
  object_name: string;
  number_of_objects: number;
  brief_description: string | null;
  current_location: string | null;
  current_owner: string | null;
  recorder: string | null;
  recording_date: string | null;
};

export type ObjectFormValues = {
  core: ObjectCore;
  visibility?: "draft" | "internal";
  fields: Record<string, unknown>;
};

type FormShape = {
  core: ObjectCore;
  visibility: "draft" | "internal";
  fields: Record<string, unknown>;
} & Record<string, unknown>;

const EMPTY_CORE: ObjectCore = {
  object_number: "",
  object_name: "",
  number_of_objects: 1,
  brief_description: null,
  current_location: null,
  current_owner: null,
  recorder: null,
  recording_date: null,
};

export function ObjectForm({
  mode,
  defaults,
  onSubmit,
  onCancel,
  formError,
}: {
  mode: "create" | "edit";
  defaults?: { core: ObjectCore; fields: Record<string, unknown> };
  onSubmit: (values: ObjectFormValues) => void;
  onCancel: () => void;
  formError?: string | null;
}) {
  const { t } = useTranslation();

  const { data: definitions } = useFieldDefinitions();

  const form = useForm<FormShape>({
    defaultValues: {
      core: defaults?.core ?? EMPTY_CORE,
      visibility: "draft",
      fields: defaults?.fields ?? {},
    },
  });

  const { register, handleSubmit, formState: { errors } } = form;

  const submit = handleSubmit((data) => {
    const fields = pruneFields(data.fields);

    onSubmit(
      mode === "create"
        ? { core: data.core, visibility: data.visibility, fields }
        : { core: data.core, fields },
    );
  });

  const coreField = (
    key: keyof ObjectCore,
    labelKey: string,
    opts?: { type?: string; required?: boolean },
  ) => (
    <div className="space-y-1">
      <Label htmlFor={key}>{t(`fieldsLabels.${labelKey}`)}</Label>

      <Input
        id={key}
        type={opts?.type ?? "text"}
        {...register(
          `core.${key}` as const,
          opts?.type === "number"
            ? { valueAsNumber: true, required: opts?.required }
            : { required: opts?.required },
        )}
      />

      {errors.core?.[key] && (
        <p role="alert" className="text-xs text-red-600">
          {t("form.required")}
        </p>
      )}
    </div>
  );

  return (
    <form onSubmit={submit} className="space-y-4 overflow-auto p-4">
      {formError && (
        <p role="alert" className="text-sm text-red-600">
          {formError}
        </p>
      )}

      {coreField("object_number", "objectNumber", { required: true })}
      {coreField("object_name", "objectName", { required: true })}
      {coreField("number_of_objects", "count", { type: "number", required: true })}
      {coreField("brief_description", "briefDescription")}
      {coreField("current_location", "currentLocation")}
      {coreField("current_owner", "currentOwner")}
      {coreField("recorder", "recorder")}
      {coreField("recording_date", "recordingDate", { type: "date" })}

      {mode === "create" && (
        <div className="space-y-1">
          <Label htmlFor="visibility">{t("form.visibility")}</Label>

          <select
            id="visibility"
            className="w-full rounded border px-2 py-1 text-sm"
            {...register("visibility")}
          >
            <option value="draft">{t("form.draft")}</option>
            <option value="internal">{t("form.internal")}</option>
          </select>
        </div>
      )}

      {definitions && definitions.length > 0 && (
        <fieldset className="space-y-3 border-t pt-3">
          <legend className="text-xs font-medium uppercase text-neutral-500">
            {t("form.flexibleHeading")}
          </legend>

          {definitions.map((def) => (
            <div key={def.key}>
              <FieldInput definition={def} form={form} />

              {errors.fields?.[def.key] && (
                <p role="alert" className="text-xs text-red-600">
                  {t("form.required")}
                </p>
              )}
            </div>
          ))}
        </fieldset>
      )}

      <div className="flex gap-2 pt-2">
        <Button type="submit">
          {mode === "create" ? t("form.create") : t("form.save")}
        </Button>

        <Button type="button" variant="ghost" onClick={onCancel}>
          {t("form.cancel")}
        </Button>
      </div>
    </form>
  );
}

function pruneFields(fields: Record<string, unknown>): Record<string, unknown> {
  const out: Record<string, unknown> = {};

  for (const [key, value] of Object.entries(fields)) {
    if (value === undefined || value === null || value === "") continue;

    if (typeof value === "object" && !Array.isArray(value)) {
      const inner = Object.fromEntries(
        Object.entries(value as Record<string, unknown>).filter(
          ([, v]) => v !== undefined && v !== null && v !== "",
        ),
      );

      if (Object.keys(inner).length > 0) out[key] = inner;

      continue;
    }

    out[key] = value;
  }

  return out;
}
