import Joi from "joi";
import React, { useEffect } from "react";
import { Navigate, useParams } from "react-router-dom";
import { toast } from "react-toastify";
import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import { useForm } from "../../../components/common/useForm";
import { InputType } from "../../../components/common/Input";
import {
  renderInput,
  renderButton,
  renderError,
  renderSelect,
  renderInputNumber,
} from "../../../components/common/formHelpers";
import sequenceService from "./services/sequenceService";
import Option from "../../../components/common/option";
import { MakeGeneralIdRef } from "../../../utils/GeneralIdRef";
import Loading from "../../../components/common/Loading";
import { useFormWithGuard } from "../../../components/common/useFormRouter";

interface SequenceDetailsProps {
  editMode?: boolean;
}

const SequenceDetails: React.FC<SequenceDetailsProps> = ({
  editMode = false,
}) => {
  const { sequenceId } = useParams<{ sequenceId: string }>();
  const { t } = useTranslation(Namespaces.Common);

  const labelName = t("Name");
  const labelSeed = t("Seed");
  const labelIncrement = t("Increment");
  const labelPattern = t("Pattern");
  const labelRolloverType = t("RolloverType");

  const labelApply = t("Save");
  const labelSave = t("SaveAndClose");

  const form = useFormWithGuard({
    loaded: false,
    data: {
      name: "",
      seed: 1,
      increment: 1,
      pattern: "[0]",
      rolloverType: "Continuous",
    },
    errors: {},
    redirect: "",
  });

  form.schema = {
    name: Joi.string().required().max(450).label(labelName),
    seed: Joi.number().required().label(labelSeed),
    increment: Joi.number().required().label(labelIncrement),
    pattern: Joi.string().required().label(labelPattern),
    rolloverType: Joi.string().required().label(labelRolloverType),
  };

  useEffect(() => {
    const loadData = async () => {
      if (sequenceId !== undefined) {
        try {
          const loadedData = await sequenceService.getSequence(
            BigInt(sequenceId),
          );
          if (loadedData) {
            const newData = { ...form.state.data };
            newData.increment = loadedData.increment;
            newData.name = loadedData.name;
            newData.pattern = loadedData.pattern;
            newData.rolloverType = loadedData.rolloverType;
            newData.seed = loadedData.seed;
            form.setState({ loaded: true, data: newData });
          } else {
            form.setState({ loaded: false });
          }
        } catch (ex: any) {
          form.handleGeneralError(ex);
        }
      }

      if (!editMode) {
        form.setState({ loaded: true });
      }
    };

    loadData();
  }, [sequenceId, editMode]); // eslint-disable-line react-hooks/exhaustive-deps

  const doSubmit = async (buttonName: string) => {
    try {
      const { name, seed, increment, pattern, rolloverType } = form.state.data;
      const nameStr = typeof name === "string" ? name : "";
      const patternStr = typeof pattern === "string" ? pattern : "";
      const rolloverTypeStr =
        typeof rolloverType === "string" ? rolloverType : "";
      const seedValue = typeof seed === "number" ? seed : Number(seed);
      const incrementValue =
        typeof increment === "number" ? increment : Number(increment);

      if (editMode) {
        const generalIdRef = MakeGeneralIdRef(
          sequenceId ? BigInt(sequenceId) : undefined,
        );
        const response = await sequenceService.putSequence(
          generalIdRef,
          nameStr,
          seedValue,
          incrementValue,
          patternStr,
          rolloverTypeStr,
        );
        if (response) {
          toast.info(t("SequenceEdited"));
        }
      } else {
        const response = await sequenceService.postSequence(
          nameStr,
          seedValue,
          incrementValue,
          patternStr,
          rolloverTypeStr,
        );
        if (response) {
          toast.info(t("NewSequenceAdded"));
        }
      }

      if (buttonName === "save") {
        form.setState({ redirect: "/sequence" });
      }
      form.markAsSaved();
    } catch (ex: any) {
      form.handleGeneralError(ex);
    }
  };

  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    form.handleSubmit(e, doSubmit);
  };

  const { loaded, redirect } = form.state;
  if (redirect) return <Navigate to={redirect} />;

  const rolloverOptions: Option[] = [
    { _id: "Continuous", name: t("Continuous") },
    { _id: "Day", name: t("Day") },
    { _id: "Month", name: t("Month") },
    { _id: "Year", name: t("Year") },
  ];

  const mode = editMode ? t("Edit") : t("Add");

  return (
    <Loading loaded={loaded}>
      <h1>
        {mode} {t("Sequence")}
      </h1>
      <form onSubmit={handleSubmit}>
        {renderError("_general", form.state.errors)}
        {renderInput(
          "name",
          labelName,
          form.state.data,
          form.state.errors,
          InputType.text,
          false,
          "",
          "",
          0,
          true,
          undefined,
          form.handleChange,
        )}
        {renderInputNumber(
          "seed",
          labelSeed,
          form.state.data,
          form.state.errors,
          false,
          "",
          undefined,
          undefined,
          1,
          form.handleChange,
        )}
        {renderInputNumber(
          "increment",
          labelIncrement,
          form.state.data,
          form.state.errors,
          false,
          "",
          undefined,
          undefined,
          1,
          form.handleChange,
        )}
        {renderInput(
          "pattern",
          labelPattern,
          form.state.data,
          form.state.errors,
          InputType.text,
          false,
          "",
          "",
          0,
          true,
          undefined,
          form.handleChange,
        )}
        {renderSelect(
          "rolloverType",
          labelRolloverType,
          form.state.data,
          form.state.errors,
          rolloverOptions,
          form.handleSelectChange,
        )}
        {editMode && renderButton(labelApply, form.state.errors, "save")}
        {renderButton(labelSave, form.state.errors, "save")}
      </form>
    </Loading>
  );
};

export default SequenceDetails;
