import { parseGenField } from "@/gen/utils";
import get from "lodash.get";
import { AlertTriangle, Check, ChevronLeft, Loader2, Plus } from "lucide-react";
import { FMLocal, FMProps } from "../typings";
import { editorFormData } from "./ed-data";
import { formError } from "./error";
import { toast } from "lib/comps/ui/toast";
import { Button } from "lib/comps/ui/button";
import { MDLocal } from "lib/comps/md/utils/typings";
import { masterDetailApplyParams } from "lib/comps/md/utils/md-hash";

export const formInit = (fm: FMLocal, props: FMProps) => {
  for (const [k, v] of Object.entries(props)) {
    if (["PassProp", "body", "meta", "item"].includes(k)) continue;
    (fm.props as any)[k] = v;
  }
  const { on_load, sonar } = fm.props;
  fm.error = formError(fm);
  fm.field_def = {};
  const defs = parseGenField(fm.props.gen_fields);
  for (const d of defs) {
    fm.field_def[d.name] = d;
  }

  const toastSuccess = (opt: { addNewText: string }) => {
    const md = fm.deps.md as MDLocal;
    if (md) {
      toast.success(
        <div
          className={cx(
            "c-flex c-flex-col c-select-none c-items-stretch c-flex-1 c-w-full"
          )}
          onClick={() => {
            toast.dismiss();
          }}
        >
          <div className="c-flex c-text-green-700 c-items-center success-title c-font-semibold">
            <Check className="c-h-6 c-w-6 c-mr-1 " />
            Record Saved
          </div>
          <div
            className={cx(
              "c-flex c-items-center c-justify-between c-space-x-2 c-p-3",
              css`
                border-radius: 10px;
                margin: 0px -10px -10px -10px;
                background: white;
                border: 1px solid rgb(164, 208, 180);
                padding-left: 5px !important;
                .button {
                  font-size: 13px;
                }
              `
            )}
          >
            <Button
              variant={"link"}
              size={"xs"}
              className={cx(
                css`
                  color: gray !important;
                `,
                "c-cursor-pointer"
              )}
              onClick={() => {
                const md = fm.deps.md as MDLocal;
                toast.dismiss();
                md.selected = null;
                md.tab.active = "master";
                md.params.apply();
                md.render();
                md.master.reload();
              }}
            >
              <ChevronLeft size={18} />{" "}
              <div className="c-px-1">Back To List</div>
            </Button>

            <Button
              variant={"outline"}
              className={cx(
                css`
                  color: green;
                  border: 1px solid green !important;
                  background: #f1fff6 !important;
                `,
                "c-cursor-pointer"
              )}
              size={"xs"}
              onClick={() => {
                const md = fm.deps.md as MDLocal;
                toast.dismiss();

                md.params.hash[md.name] = "+";
                md.selected = {};
                md.internal.reset_detail = true;
                md.tab.active = "detail";
                md.params.apply();
              }}
            >
              <div className="c-px-1">{opt.addNewText}</div> <Plus size={18} />
            </Button>
          </div>
        </div>,
        {
          duration: 60 * 1000,
          className: css`
            background: #e4ffed;
            border: 2px solid green;

            .success-title {
              margin-bottom: 20px;
            }
          `,
        }
      );
    } else {
      toast.success(
        <div
          className={cx("c-flex c-flex-col c-select-none")}
          onClick={() => {}}
        >
          <div className="c-flex c-text-green-700 c-items-center">
            <Check className="c-h-4 c-w-4 c-mr-1 " />
            Saved
          </div>
        </div>,
        {
          duration: 60 * 1000,
          className: css`
            background: #e4ffed;
            border: 2px solid green;
          `,
        }
      );
    }
  };

  fm.reload = async () => {
    fm.status = isEditor ? "ready" : "loading";
    fm.render();

    if (sonar === "on" && !isEditor) {
      toast.dismiss();
      toast.loading(
        <>
          <Loader2 className="c-h-4 c-w-4 c-animate-spin" />
          Loading data...
        </>
      );
    }

    let should_load = true;
    if (isEditor) {
      const item_id = props.item.id;
      if (item_id) {
        const cache = editorFormData[item_id];
        if (
          cache &&
          cache.on_load === get(props.item, "component.props.on_load.value")
        ) {
          fm.data = cache.data;
          should_load = false;
        }
      }
    }
    if (should_load) {
      if (!on_load) {
        console.error("Form on_load is empty. Please re-generate the form.");
      } else {
        const on_load_result = on_load({ fm });
        let result = undefined;
        if (
          typeof on_load_result === "object" &&
          on_load_result instanceof Promise
        ) {
          result = await on_load_result;
        } else {
          result = on_load_result;
        }

        fm.data = result;

        if (result === undefined) fm.data = {};

        if (isEditor) {
          const item_id = props.item.id;
          if (item_id) {
            editorFormData[item_id] = {
              data: fm.data,
              on_load: get(props.item, "component.props.on_load.value"),
            };
          }
        }
      }
    }

    toast.dismiss();

    if (fm.is_newly_created) {
      fm.is_newly_created = false;
      toastSuccess({ addNewText: "Add Another" });
    }

    fm.status = "ready";
    fm.render();
  };

  fm.submit = async () => {
    if (fm.status !== "ready") {
      return;
    }
    if (typeof fm.props.on_submit === "function") {
      fm.status = "saving";
      fm.render();

      if (fm.props.sonar === "on" && !isEditor) {
        toast.loading(
          <>
            <Loader2 className="c-h-4 c-w-4 c-animate-spin" />
            Submitting...
          </>
        );
      }

      const form = JSON.parse(JSON.stringify(fm.data));

      if (fm.deps.md) {
        const md = fm.deps.md;
        const last = md.params.links[md.params.links.length - 1];
        if (last) {
          const pk = Object.values(fm.field_def).find((e) => e.is_pk);
          if (pk) {
            let obj = last.update;
            if (!fm.data[pk.name]) {
              obj = last.create;
            }

            if (typeof obj === "object" && obj) {
              for (const [k, v] of Object.entries(obj)) {
                form[k] = v;
              }
            }
          }
        }
      }

      const success = await fm.props.on_submit({
        fm,
        form,
        error: fm.error.object,
      });

      toast.dismiss();

      if (!success) {
        fm.status = "ready";
        fm.render();
      }

      if (fm.props.sonar === "on" && !isEditor) {
        toast.dismiss();

        if (!success) {
          const errors = Object.keys(fm.error.list);
          const count = errors.length;
          toast.error(
            <div className="c-flex c-text-red-600 c-items-center">
              <AlertTriangle className="c-h-4 c-w-4 c-mr-1" />
              Save Failed
              {count > 0 &&
                `, please correct
                    ${count} errors`}
              .
            </div>,
            {
              dismissible: true,
              className: css`
                background: #ffecec;
                border: 2px solid red;
              `,
            }
          );
        } else {
          toastSuccess({ addNewText: "Add New" });
        }
      }
      return success;
    }
  };
  if (typeof fm.props.on_init === "function") {
    fm.props.on_init({ fm, submit: fm.submit, reload: fm.reload });
  }
};
