import { AutoSaveTextarea } from "@/components/AutoSaveTextarea";
import { pb } from "@/lib/pocketbase";
import { getDocumentType, type AnyDocument } from "@/lib/types";
import { useDocumentCache } from "@/context/document/hooks";
import {
  getFieldsForType,
  type DocumentField,
  type FieldType,
} from "@/lib/fields";
import { ToggleInput } from "../form/ToggleInput";

export type GenericFieldType = "multiline" | "singleline" | "checkbox";

export type Props<T extends AnyDocument> = {
  doc: T;
};

export const GenericEditForm = <T extends AnyDocument>({ doc }: Props<T>) => {
  const docType = getDocumentType(doc) as T["type"];
  const fields = getFieldsForType(docType);

  return (
    <div className="">
      {
        // The type checker seems to lose the types when using Object.entries here.
        fields.map((documentField) => (
          <GenericEditFormField doc={doc} field={documentField} />
        ))
      }
    </div>
  );
};

const GenericEditFormField = <T extends AnyDocument>({
  doc,
  field,
}: {
  doc: T;
  field: DocumentField<T["type"], FieldType>;
}) => {
  const { dispatch } = useDocumentCache();

  // The type checker really doesn't like indexing into this type implicitly, so we'll store it in a temporary to give it the right hints.
  const data = doc.data as T["data"];

  async function saveField(value: string | boolean) {
    const updated: T = await pb.collection("documents").update(doc.id, {
      data: field.setter(value, doc.data),
    });
    dispatch({ type: "setDocument", doc: updated });
  }

  switch (field.fieldType) {
    case "longText":
      return (
        <AutoSaveTextarea
          multiline={true}
          value={field.getter(data) as string}
          onSave={saveField}
          id={field.name}
        />
      );
    case "shortText":
      return (
        <AutoSaveTextarea
          multiline={false}
          value={field.getter(data) as string}
          onSave={saveField}
          id={field.name}
        />
      );
    case "toggle":
      return (
        <ToggleInput
          label={field.name}
          value={!!field.getter(data)}
          onChange={saveField}
          placeholder={field.name}
        />
      );
  }
};
