"use client";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
import {
  useState,
  useEffect,
  useRef,
  useMemo,
  forwardRef,
  useImperativeHandle
} from "react";
import { Formik, getIn } from "formik";
import { Check12 } from "../../icons/Check12";
import { getSizeHeight as getInputSizeHeight } from "./components/Field/components/Input";
import {
  Sizes,
  Provider as FormContextProvider,
  Alignments
} from "./context/FormContext";
import Placeholder from "./components/Placeholder";
import Field from "./components/Field";
import Spinner from "./components/Spinner";
import Button from "../Button";
import { Link } from "../../shared/Link";
import { getBox } from "../../../state/modules/box-models";
import { useTableFormFieldRefs } from "../../hooks/useTableFormFieldRefs";
import { cx } from "@emotion/css";
import { useResponsiveGridItem, useResponsiveStyle } from "../../utils/responsive-style";
import { useMakeswiftHostApiClient } from "../../../runtimes/react/host-api-client";
import { useStyle } from "../../../runtimes/react/use-style";
import { useTable } from "../../../runtimes/react/hooks/makeswift-api";
const LOCAL_STORAGE_NAMESPACE = "@@makeswift/components/form";
function getSizeFontSize(size) {
  switch (size) {
    case Sizes.SMALL:
      return 12;
    case Sizes.MEDIUM:
      return 14;
    case Sizes.LARGE:
      return 18;
    default:
      throw new Error(`Invalid form size "${size}"`);
  }
}
const GridForm = forwardRef(function GridFrom({ className, size, ...restOfProps }, ref) {
  return /* @__PURE__ */ jsx(
    "form",
    {
      ...restOfProps,
      ref,
      className: cx(
        useStyle({ display: "flex", flexWrap: "wrap", width: "100%" }),
        useStyle(
          useResponsiveStyle([size], ([size2 = Sizes.MEDIUM]) => ({
            fontSize: getSizeFontSize(size2)
          }))
        ),
        className
      )
    }
  );
});
const GridItem = forwardRef(function GridItem2({ className, grid, index, rowGap, columnGap, ...restOfProps }, ref) {
  return /* @__PURE__ */ jsx(
    "div",
    {
      ...restOfProps,
      ref,
      className: cx(
        useStyle({ alignSelf: "flex-end", flexDirection: "column" }),
        useStyle(useResponsiveGridItem({ grid, index, rowGap, columnGap })),
        className
      )
    }
  );
});
function getAlignmentMargin(alignment) {
  switch (alignment) {
    case Alignments.LEFT:
      return "0 auto 0 0";
    case Alignments.RIGHT:
      return "0 0 0 auto";
    default:
      return "0 auto";
  }
}
function StyledButton({ className, size, alignment, ...restOfProps }) {
  return /* @__PURE__ */ jsx(
    Button,
    {
      ...restOfProps,
      as: "button",
      className: cx(
        useStyle({ display: "flex", alignItems: "center", justifyContent: "center" }),
        useStyle(
          useResponsiveStyle(
            [size, alignment],
            ([size2 = Sizes.MEDIUM, alignment2 = Alignments.CENTER]) => ({
              minHeight: getInputSizeHeight(size2),
              maxHeight: getInputSizeHeight(size2),
              margin: getAlignmentMargin(alignment2),
              paddingTop: 0,
              paddingBottom: 0
            })
          )
        ),
        className
      )
    }
  );
}
function ErrorContainer({ className, ...restOfProps }) {
  return /* @__PURE__ */ jsx(
    "div",
    {
      ...restOfProps,
      className: cx(
        useStyle({
          padding: "8px 16px",
          backgroundColor: "#f19eb9",
          borderRadius: 4,
          marginTop: 16
        }),
        className
      )
    }
  );
}
function IconContainer({ className, ...restOfProps }) {
  return /* @__PURE__ */ jsx("div", { ...restOfProps, className: cx(useStyle({ fill: "currentColor" }), className) });
}
function ErrorMessage({ className, ...restOfProps }) {
  return /* @__PURE__ */ jsx(
    "p",
    {
      ...restOfProps,
      className: cx(
        useStyle({ fontSize: 12, margin: "8px 0", color: "rgba(127, 0, 0, 0.95)" }),
        className
      )
    }
  );
}
function getTableColumnDefaultValue(tableColumn) {
  switch (tableColumn.__typename) {
    case "CheckboxTableColumn":
      return false;
    case "MultipleSelectTableColumn":
      return [];
    case "SingleLineTextTableColumn":
    case "LongTextTableColumn":
    case "SingleSelectTableColumn":
    case "PhoneNumberTableColumn":
    case "EmailTableColumn":
    case "URLTableColumn":
    case "NumberTableColumn":
    default:
      return "";
  }
}
const Form = forwardRef(function Form2({
  id,
  tableId,
  fields: fieldsProp,
  submitLabel = "Submit",
  submitLink,
  shape,
  size,
  contrast,
  brandColor,
  gap,
  width,
  margin,
  submitTextStyle,
  submitVariant,
  submitTextColor,
  submitWidth,
  submitAlignment,
  labelTextStyle,
  labelTextColor
}, ref) {
  const fields = useMemo(() => fieldsProp?.fields ?? [], [fieldsProp]);
  const grid = useMemo(() => fieldsProp?.grid ?? [], [fieldsProp]);
  const table = useTable(tableId ?? null);
  const client = useMakeswiftHostApiClient();
  const [refEl, setRefEl] = useState(null);
  const [propControllers, setPropControllers] = useState(null);
  const [initialValues, setInitialValues] = useState(
    () => fields.reduce((acc, formField) => {
      const tableColumn = table && table.columns.find((field) => field.id === formField.tableColumnId);
      const defaultValue = formField ? formField.defaultValue : null;
      if (tableColumn) {
        acc[tableColumn.name] = defaultValue == null ? getTableColumnDefaultValue(tableColumn) : defaultValue;
      }
      return acc;
    }, {})
  );
  const controller = propControllers?.fields;
  const { container, items } = useTableFormFieldRefs(controller, { fieldsCount: fields.length });
  const [isDone, setIsDone] = useState(false);
  const linkRef = useRef(null);
  useImperativeHandle(
    ref,
    () => ({
      getDomNode() {
        return refEl instanceof Element ? refEl : null;
      },
      getBoxModel() {
        return refEl instanceof Element ? getBox(refEl) : null;
      },
      setPropControllers
    }),
    [refEl, setPropControllers]
  );
  useEffect(() => {
    container(refEl);
  }, [container, refEl]);
  useEffect(() => {
    if (!isDone)
      return;
    let timeoutId = setTimeout(() => setIsDone(false), 2500);
    return () => clearTimeout(timeoutId);
  }, [isDone]);
  function getTableColumn({ tableColumnId }) {
    return table && table.columns.find((field) => tableColumnId === field.id);
  }
  async function handleSubmit(values, { setSubmitting, resetForm, setStatus }) {
    if (table) {
      const columns = [];
      fields.forEach((field) => {
        const tableColumn = getTableColumn(field);
        if (tableColumn) {
          const data = values[tableColumn.name];
          if (data) {
            columns.push({ columnId: field.tableColumnId, data });
            if (field.autofill) {
              localStorage.setItem(
                `${LOCAL_STORAGE_NAMESPACE}/${tableColumn.name}`,
                JSON.stringify(data)
              );
            }
          }
        }
      });
      try {
        await client.createTableRecord(table.id, columns);
        setIsDone(true);
        setInitialValues(
          (prev) => fields.reduce(
            (acc, field) => {
              const tableColumn = getTableColumn(field);
              if (tableColumn) {
                const data = values[tableColumn.name];
                if (data && field.autofill)
                  return { ...acc, [tableColumn.name]: data };
              }
              return acc;
            },
            { ...prev }
          )
        );
        resetForm();
        if (linkRef.current != null)
          linkRef.current.click();
      } catch (error) {
        setStatus({ error: "An unexpected error has occurred, please try again later" });
      } finally {
        setSubmitting(false);
      }
    }
  }
  useEffect(() => {
    setInitialValues(
      (prev) => fields.reduce(
        (acc, formField) => {
          const tableColumn = table && table.columns.find((field) => field.id === formField.tableColumnId);
          if (tableColumn && formField.autofill) {
            const storedValue = localStorage.getItem(
              `${LOCAL_STORAGE_NAMESPACE}/${tableColumn.name}`
            );
            if (storedValue) {
              try {
                acc[tableColumn.name] = JSON.parse(storedValue);
              } catch (e) {
              }
            }
          }
          return acc;
        },
        { ...prev }
      )
    );
  }, [fields, table]);
  return /* @__PURE__ */ jsx(
    FormContextProvider,
    {
      value: { shape, size, contrast, brandColor, labelTextStyle, labelTextColor },
      children: tableId == null ? /* @__PURE__ */ jsx(Placeholder, { ref: setRefEl, width, margin }) : /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
        Formik,
        {
          onSubmit: handleSubmit,
          initialValues,
          initialStatus: { error: null },
          enableReinitialize: true,
          children: (formik) => {
            const error = formik.status && formik.status.error;
            const errors = fields.map((field) => {
              const tableColumn = getTableColumn(field);
              return tableColumn && getIn(formik.touched, tableColumn.name) && getIn(formik.errors, tableColumn.name);
            }).filter((message) => typeof message === "string");
            return /* @__PURE__ */ jsxs(Fragment, { children: [
              /* @__PURE__ */ jsxs(
                GridForm,
                {
                  ref: setRefEl,
                  id,
                  className: cx(width, margin),
                  size,
                  onSubmit: formik.handleSubmit,
                  onReset: formik.handleReset,
                  noValidate: true,
                  children: [
                    fields.map((field, index) => {
                      const tableColumn = getTableColumn(field);
                      return /* @__PURE__ */ jsx(
                        GridItem,
                        {
                          ref: items[index],
                          grid,
                          index,
                          rowGap: gap,
                          columnGap: gap,
                          children: /* @__PURE__ */ jsx(Field, { tableColumn, tableFormField: field })
                        },
                        field.id
                      );
                    }),
                    /* @__PURE__ */ jsxs(
                      GridItem,
                      {
                        ref: items[fields.length],
                        grid,
                        index: fields.length,
                        rowGap: gap,
                        columnGap: gap,
                        children: [
                          /* @__PURE__ */ jsx(
                            StyledButton,
                            {
                              type: "submit",
                              disabled: formik.isSubmitting || isDone,
                              shape,
                              size,
                              color: brandColor,
                              variant: submitVariant,
                              textColor: submitTextColor,
                              width: submitWidth,
                              alignment: submitAlignment,
                              textStyle: submitTextStyle,
                              children: formik.isSubmitting ? /* @__PURE__ */ jsx(Spinner, {}) : isDone ? /* @__PURE__ */ jsx(IconContainer, { children: /* @__PURE__ */ jsx(Check12, {}) }) : submitLabel
                            }
                          ),
                          (errors.length > 0 || error) && /* @__PURE__ */ jsxs(ErrorContainer, { children: [
                            errors.map((message) => /* @__PURE__ */ jsx(ErrorMessage, { children: message }, message)),
                            error != null && /* @__PURE__ */ jsx(ErrorMessage, { children: error })
                          ] })
                        ]
                      }
                    )
                  ]
                }
              ),
              submitLink != null && /* @__PURE__ */ jsx(Link, { ref: linkRef, hidden: true, link: submitLink })
            ] });
          }
        }
      ) })
    }
  );
});
var Form_default = Form;
export {
  Form_default as default
};
//# sourceMappingURL=Form.js.map