import "./OnDemandEditorModal.scss";
import React, { useRef, useState, useMemo, useCallback } from "react";
import { Row } from "antd/lib/grid";
import Modal from "components/Modal";
import Button from "antd/lib/button";
import { MediaUpload } from "redux/Common/types";
import CoverUpload from "./components/CoverUpload/CoverUpload";
import { Formik, FormikProps } from "formik";
import OnDemandEditorForm from "./components/Form/Form";
import * as yup from "yup";
import { useEffect } from "react";
import isEmpty from "lodash/isEmpty";
import pick from "lodash/pick";
import notification from "utils/notification";
import { useTypedSelector } from "redux/rootReducer";
import { selectExchangeRates } from "redux/User/selector";
import VideoUpload from "./components/VideoUpload/VideoUpload";
import { OnDemandVideoItem } from "models/talent/talent-profile-module.model";
import { getPriceWithExchangeRate } from "utils/currency";
import useMiniumPrice from "hooks/useMinimumPrice";
import { JSONService } from "utils/json-patch";
import { EXPERIENCE_STATUS, EXPERIENCE_TYPE } from "redux/Experience/types";
import FormProducts from "./components/Form/FormProducts";
import { URL_REG } from "../../constants/regexp";

export type OnDemandVideoEditorModalFormValues = Pick<
  OnDemandVideoItem,
  | "name"
  | "description"
  | "experiencePrice"
  | "duration"
  | "productSectionTitle"
  | "products"
>;

interface OnDemandEditorModalProps {
  show: boolean;
  isEdit: boolean;
  item?: OnDemandVideoItem;
  toggleModal: (value: boolean) => void;
  onConfirmCallback: (item: OnDemandVideoItem) => void;
}

const initialOnDemandValues: OnDemandVideoItem = {
  name: "",
  description: "",
  experiencePrice: undefined,
  productSectionTitle: "",
  products: [],
  visible: true,
};

const OnDemandEditorModal: React.FC<OnDemandEditorModalProps> = ({
  show,
  isEdit,
  item,
  toggleModal,
  onConfirmCallback,
}) => {
  const [step, setStep] = useState(1);
  const [minimumPrice, minimumPriceFormat] = useMiniumPrice();
  const formRef = useRef<FormikProps<OnDemandVideoEditorModalFormValues>>(null);
  const formProductsRef =
    useRef<FormikProps<OnDemandVideoEditorModalFormValues>>(null);
  const exchangeRate = useTypedSelector(selectExchangeRates);
  const [photo, setPhoto] = useState<MediaUpload>({});
  const [video, setVideo] = useState<MediaUpload>({});
  const [initialValues, setInitialValues] = useState<OnDemandVideoItem>({
    visible: true,
  });
  const title = useMemo(() => {
    if (step === 1) {
      return isEdit ? "Edit On-demand Video" : "Add New On-demand Video";
    }
    return isEdit ? "Edit Products (optional)" : "Add Products (optional)";
  }, [step, isEdit]);
  const validateSchema = yup.object().shape({
    // Validate form field
    name: yup.string().required("Enter your On-demand name"),
    description: yup.string().required("Enter your On-demand description"),
    experiencePrice: yup
      .number()
      .typeError("Please enter the On-demand price")
      .required("Please enter the On-demand price")
      .test(
        "minimum",
        `The On-demand price must be at least ${minimumPriceFormat}.`,
        (val) => Number(val) >= minimumPrice || Number(val) === 0
      ),
  });
  const validateProductsSchema = yup.object().shape({
    // Validate form field
    products: yup.array().of(
      yup.object().shape({
        image: yup.string().required("Please add the Cover Photo"),
        name: yup.string().required("Enter your product name"),
        link: yup
          .string()
          .matches(URL_REG, "Wrong Format URL")
          .required("Please fill the product link"),
        price: yup
          .number()
          .typeError("Please enter the product price")
          .min(0, "Please enter the product price")
          .required("Please enter the product price"),
      })
    ),
  });

  const isBooked = useMemo(() => {
    if (item?.bookings?.length) return true;
    return false;
  }, [item]);

  useEffect(() => {
    if (!show) return;
    setStep(1);

    if (isEdit && item) {
      if (
        !!exchangeRate &&
        item?.experienceCreationCurrency?.toLowerCase() !==
          exchangeRate?.localCurrency.toLowerCase()
      ) {
        item.experiencePrice = getPriceWithExchangeRate(
          item.gbpExperiencePrice || 0,
          exchangeRate
        );
      }
      setInitialValues({
        ...pick(item, [
          "name",
          "description",
          "experiencePrice",
          "duration",
          "order",
          "productSectionTitle",
          "products",
          "visible",
        ]),
      });

      setPhoto({ url: item.covers?.[0] });
      setVideo({ url: item.video, duration: item.duration });
    } else {
      setInitialValues(initialOnDemandValues);
      setPhoto({});
      setVideo({});
    }
  }, [show, isEdit, item]);

  const uploadPhotoSuccess = (file: MediaUpload) => {
    setPhoto(file);
  };

  const removePhoto = () => {
    setPhoto({});
  };

  const uploadVideoSuccess = async (file: MediaUpload) => {
    setVideo(file);
  };

  const removeVideo = () => {
    setVideo({});
  };
  const handleGoBackClick = useCallback(() => {
    if (step === 1) {
      toggleModal(false);
      return;
    }
    setStep(1);
  }, [step]);
  const handleClickAction = useCallback(() => {
    if (step === 1) {
      formRef.current?.handleSubmit();
      return;
    }
    formProductsRef.current?.handleSubmit();
  }, [formProductsRef, formRef, step]);

  const handleSubmit = async (
    formProps: OnDemandVideoEditorModalFormValues
  ) => {
    if (!photo.url) {
      notification.warn({ message: "Please add the Cover Photo" });
      return;
    }
    if (!video.url) {
      notification.warn({ message: "Please add the On-demand video" });
      return;
    }
    if (step === 1) {
      setStep(step + 1);
      return;
    }
    const products = formProps.products?.map((el) => ({
      ...el,
      price: Number(el.price),
    }));
    const itemUpdate = {
      ...item,
      ...formProps,
      products,
      covers: [photo.url as string],
      video: video.url as string,
      duration: video.duration,
      experiencePrice: Number(formProps.experiencePrice),
      experienceCreationCurrency:
        item?.experienceCreationCurrency || exchangeRate?.localCurrency,
      status: EXPERIENCE_STATUS.PUBLISHED,
      type: EXPERIENCE_TYPE.EXCLUSIVE_CONTENT,
    };

    const patch = JSONService.getPatch(itemUpdate, item, {
      actions: ["add", "remove", "replace"], // actions
    });

    onConfirmCallback({
      ...itemUpdate,
      isUpdate: item?.isUpdate ? item.isUpdate : !isEmpty(patch),
      visible: itemUpdate ? itemUpdate.visible : true,
    });
  };

  return (
    <React.Fragment>
      <Modal
        width={664}
        closable
        centered
        className="on-demand-editor-modal"
        title={title}
        visible={show}
        onCancel={() => toggleModal(false)}
        destroyOnClose
        maskClosable={false}
      >
        <div className="on-demand-editor__content">
          {step === 1 ? (
            <Formik
              innerRef={formRef}
              initialValues={initialValues}
              onSubmit={handleSubmit}
              validationSchema={validateSchema}
            >
              {(props) => (
                <React.Fragment>
                  <>
                    <div className="m__b--32">
                      <CoverUpload
                        photo={photo}
                        onUploadSuccess={uploadPhotoSuccess}
                        onRemove={removePhoto}
                      />
                    </div>
                    <OnDemandEditorForm
                      {...props}
                      exchangeRate={exchangeRate}
                    />
                    <Row>
                      <VideoUpload
                        disableUpload={isBooked}
                        video={video}
                        onUploadSuccess={uploadVideoSuccess}
                        onRemove={removeVideo}
                      />
                    </Row>
                  </>
                </React.Fragment>
              )}
            </Formik>
          ) : (
            <Formik
              innerRef={formProductsRef}
              initialValues={initialValues}
              onSubmit={handleSubmit}
              validationSchema={validateProductsSchema}
            >
              {(props) => (
                <React.Fragment>
                  <FormProducts {...props} exchangeRate={exchangeRate} />
                </React.Fragment>
              )}
            </Formik>
          )}
          <div className="on-demand-editor__actions m__t--16">
            <Button
              className="ant-btn-xl ant-btn-uppercase"
              onClick={handleGoBackClick}
            >
              {step === 1 ? "Cancel" : "Go Back"}
            </Button>
            <Button
              className="ant-btn-xl ant-btn-uppercase"
              type="primary"
              onClick={handleClickAction}
            >
              {step === 1 ? "Next" : isEdit ? "Save" : "Done"}
            </Button>
          </div>
        </div>
      </Modal>
    </React.Fragment>
  );
};

export default OnDemandEditorModal;
