import { useState, useEffect, useRef } from "react";
import "./dynamicForm.scss";
import CustomInput from "../Inputs";

// import context.
import { useSetting } from "../../../contexts/SettingContext";
import { useModules } from '../../../contexts/ModuleContext.jsx';

// import services function
import { getApiLink, sendApiResponse } from "../../../services/apiService";
import Dialog from "@mui/material/Dialog";
import Popoup from "../../PopupContent/PopupContent";
import ModulePopoup from "../../PopupContent/ModulePopup";
import FormCustomizer from "../Inputs/Special/FormCustomizer";
import FreeProFormCustomizer from "../Inputs/Special/FreeProFormCustomizer/FormCustomizer";
import ToggleSetting from "../Inputs/Special/ToggleSetting";
//Product page builder
import CatalogCustomizer from "../Inputs/Special/CatalogCustomizer/CatalogCustomizer";
//Table component in settings
import MultiCheckboxTable from "../Inputs/Special/MultiCheckboxTable/MultiCheckboxTable";
//Merge select box and text box component
import MergeComponent from "../Inputs/Special/MergeComponent/MergeComponent";
//Shortcode list table
import ShortCodeTable from "../Inputs/Special/ShortCodeTable/ShortCodeTable";
//customize form builder
import FromBuilder from "../Inputs/Special/RegistrationForm/RegistrationForm";
//Merge SyncNow and ConnectButton component later
import SyncNow from "../Inputs/Special/SyncNow/SyncNow";
import ConnectButton from "../Inputs/Special/ConnectButton/ConnectButton";
//Attribute mapping component
import SyncMap from "../Inputs/Special/SyncMap/SyncMap";
//Generate SSO key 
import AutoGeneratedDefaultInput from "../Inputs/Special/AutoGeneratedDefaultInput/AutoGeneratedDefaultInput";
//Show Log file in settings
import Log from "../Inputs/Special/Log/Log";
//Checkbox with custom image 
import CheckboxCustomImg from "../Inputs/Special/CheckboxCustomImg/CheckboxCustomImg";

// Variable for controll coldown effect submit time
const PENALTY  = 10;
const COOLDOWN = 1;

const DynamicForm = (props) => {
  const { modal, submitUrl, id } = props.setting;
  const { setting, updateSetting } = useSetting();
  const [successMsg, setSuccessMsg] = useState("");
  const [countryState, setCountryState] = useState([]);
  const settingChanged = useRef(false);
  const [modelOpen, setModelOpen] = useState(false);
  const [modelModuleOpen, setModelModuleOpen] = useState(false);
  const [modulePopupData, setModulePopupData] = useState({
    name: '',
    settings: '',
    plugin: '',
});
  const { modules } = useModules();

  const counter = useRef(0);
  const counterId = useRef(0);

  // Submit the setting to backend when setting Change.
  useEffect(() => {
    if (settingChanged.current) {
      settingChanged.current = false;

      // Set counter by penalti
      counter.current = PENALTY;
      // Clear previous counter.
      if (counterId.current) {
        clearInterval(counterId.current);
      }

      // Create new interval
      const intervalId = setInterval(() => {
        counter.current -= COOLDOWN;
        // Cooldown compleate time for db request.
        if (counter.current < 0) {
          sendApiResponse(getApiLink(submitUrl), {
            setting: setting,
            settingName: id,
            vendor_id: props.vendorId || "",
            announcement_id: props.announcementId || "",
            knowladgebase_id: props.knowladgebaseId || "",
          }).then((response) => {
            // Set success messaage for 2second.
            setSuccessMsg(response.error);
            setTimeout(() => setSuccessMsg(""), 2000);
    
            // If response has redirect link then redirect.
            if (response.redirect_link) {
              window.location.href = response.data.redirect_link;
            }
          });

          clearInterval(intervalId);
          counterId.current = 0;
        }
      }, 50);
    
      // Store the interval id.
      counterId.current = intervalId;
    }
  }, [setting]);

  const isProSetting = (proDependent) => {
    return proDependent && !appLocalizer.khali_dabba;
  }

  const proSettingChanged = (isProSetting) => {
    if (isProSetting && !appLocalizer.khali_dabba) {
      setModelOpen(true);
      return true;
    }
    return false;
  }

  const moduleEnabledChanged = (moduleEnabled, dependentSetting = "", dependentPlugin = false) => {
    let popupData = { name: '', settings: '', plugin: '' };
    if (moduleEnabled && !modules.includes(moduleEnabled)) {
        popupData.name = moduleEnabled;
    }
    if (dependentSetting && Array.isArray(setting[dependentSetting]) && setting[dependentSetting].length === 0) {
        popupData.settings = dependentSetting;
    }
    if (dependentPlugin) {
        popupData.plugin = 'notifima';
    }
    if (popupData.name || popupData.settings || popupData.plugin) {
      setModulePopupData(popupData);
      setModelModuleOpen(true);
      return true;
    }
    return false;
  }



  const handleChange = (event, key, type = 'single', fromType = 'simple', arrayValue = []) => {
    settingChanged.current = true;

    if ( type === 'single' ) {
        if (fromType === 'simple') {
            updateSetting( key, event.target.value );
        } else if (fromType === 'calender') {
            let formattedDate;
            if (Array.isArray(event)) {
              // Check if all elements are ranges
              if (event.every(item => Array.isArray(item) && item.length === 2)) {
                // Handle one or multiple ranges
                formattedDate = event
                  .map(range => {
                    const startDate = range[0]?.toString();
                    const endDate = range[1]?.toString();
                    return `${startDate} - ${endDate}`;
                  })
                  .join(', '); 
              } else {
                formattedDate = event.map(item => item.toString()).join(','); // Multiple dates format
              }
            } else {
              formattedDate = event.toString();
            }

            updateSetting( key, formattedDate );
        } else if (fromType === 'select') {
            updateSetting( key, arrayValue[ event.index ] );
        } else if (fromType === 'multi-select') {
          updateSetting( key, event );
        } else if (fromType === 'wpeditor') {
            updateSetting( key, event );
        } else if (fromType === 'country') {
            updateSetting( key, arrayValue[ event.index ] );
            const statefromcountrycode = JSON.parse(
                appLocalizer.countries.replace(/&quot;/g, '"')
            )[event.value];
            const country_list_array = [];
            for (const key_country in statefromcountrycode) {
                country_list_array.push({
                    label: key_country,
                    value: statefromcountrycode[key_country],
                });
            }
            setCountryState( country_list_array );
        }
    } else {
      let prevData = setting[key] || [];
      if ( ! prevData || typeof prevData == 'string' || prevData == true ) {
        prevData = [ key ];
      }
      prevData = prevData.filter((data) => data != event.target.value);
      if ( event.target.checked ) {
        prevData.push( event.target.value );
      }
      updateSetting( key, prevData );
    }
}

  const handleMultiNumberChange = (e, key, optionKey, index) => {
    settingChanged.current = true;
    const mulipleOptions = setting[key] || {};
    mulipleOptions[index] = {
      key: optionKey,
      value: e.target.value,
    };
    updateSetting(key, mulipleOptions);
  };

  const handlMultiSelectDeselectChange = (key, options, type='') => {
    settingChanged.current = true;

    if (Array.isArray(setting[key]) && setting[key].length > 0) {
      updateSetting(key, []);
    } else {
        const newValue = options
          .filter((option) => type === 'multi-select' || !isProSetting(option.proSetting))
          .map(({ value }) => value);
        updateSetting(key, newValue);
    }
  };

  const runUploader = (key) => {
    settingChanged.current = true;
    // Create a new media frame
    const frame = wp.media({
      title: "Select or Upload Media Of Your Chosen Persuasion",
      button: {
        text: "Use this media",
      },
      multiple: false, // Set to true to allow multiple files to be selected
    });

    frame.on("select", function () {
      // Get media attachment details from the frame state
      const attachment = frame.state().get("selection").first().toJSON();
      updateSetting(key, attachment.url);
    });
    // Finally, open the modal on click
    frame.open();
  };

  const isContain = ( key, value = null ) => {
    let settingValue = setting[key];
    
    // If setting value is a array
    if (Array.isArray(settingValue)) {
      // Setting value is set
      if (value === null && settingValue.length ) {
        return true;
      }
      
      return settingValue.includes( value )
    }
    
    // Setting value is not a array
    if (value === null && settingValue) {
      return true;
    }

    return settingValue === value;
  }

  const shouldRender = (dependent) => {
    if ( dependent.set === true && ! isContain( dependent.key) ) {
      return false;
    }
    if ( dependent.set === false && isContain( dependent.key) ) {
      return false;
    }
    if ( dependent.value && ! isContain( dependent.key, dependent.value ) ) {
      return false;
    }
    return true;
  }

  const renderForm = () => {
    return modal.map((inputField, index) => {
      let value = setting[inputField.key] ?? "";
      let input = "";

      // Filter dependent 
      if ( Array.isArray(inputField.dependent) ) {
        for ( let dependent of inputField.dependent ) {
          if ( ! shouldRender(dependent) ) {
            return;
          }
        }
      } else if ( inputField.dependent ) {
        if ( ! shouldRender(inputField.dependent) ) {
          return;
        }
      }

      // Set input fild based on their type.
      switch (inputField.type) {
        case "text":
        case "url":
        case "password":
        case "email":
        case "number":
        case "range":
          input = (
            <CustomInput.BasicInput
              wrapperClass={`setting-form-input`}
              descClass="settings-metabox-description"
              description={inputField.desc}
              key={inputField.key}
              id={inputField.id}
              name={inputField.name}
              type={inputField.type}
              placeholder={inputField.placeholder}
              inputLabel={inputField.inputLabel} // for range input label
              rangeUnit={inputField.rangeUnit} // for range parameter
              min={inputField.min || 0} // for range min value
              max={inputField.max || 50} // for range max value
              value={value}
              proSetting={isProSetting(inputField.proSetting)}
              onChange={(e) => {
                if (!proSettingChanged(inputField.proSetting) && !moduleEnabledChanged(inputField.moduleEnabled)) {
                  handleChange(e, inputField.key);
                }
              }}
              parameter={inputField.parameter} //for show text beside text box
            />
          );
          break;

        case "textarea":
          input = (
            <CustomInput.TextArea
              wrapperClass="setting-from-textarea"
              inputClass={inputField.class || "form-input"}
              descClass="settings-metabox-description"
              description={inputField.desc}
              key={inputField.key}
              id={inputField.id}
              name={inputField.name}
              placeholder={inputField.placeholder}
              rowNumber={inputField.rowNumber} // for row number value
              colNumber={inputField.colNumber} // for column number value
              value={value}
              proSetting={isProSetting(inputField.proSetting)}
              onChange={(e) => {
                if ( !proSettingChanged(inputField.proSetting) && !moduleEnabledChanged(inputField.moduleEnabled) ) {
                  handleChange(e, inputField.key);
                }
              }}
            />
          );
          break;

        case "normalfile":
          input = (
            <CustomInput.BasicInput
              inputClass="setting-form-input"
              type="file"
              key={inputField.key}
              name={inputField.name}
              value={value}
              proSetting={isProSetting(inputField.proSetting)}
              onChange={(e) => {
                if ( !proSettingChanged(inputField.proSetting) && !moduleEnabledChanged(inputField.moduleEnabled) ) {
                  handleChange(e, inputField.key);
                }
              }}
            />
          );
          break;

        case "file":
          input = (
            <CustomInput.FileInput
              wrapperClass="setting-file-uploader-class"
              descClass="settings-metabox-description"
              description={inputField.desc}
              inputClass={`${inputField.key} form-input`}
              imageSrc={value || appLocalizer.default_logo} // default logo upload
              imageWidth={inputField.width} // for width
              imageHeight={inputField.height} // for height
              buttonClass="btn btn-purple"
              openUploader={appLocalizer.open_uploader} // for upload button text
              type="hidden"
              key={inputField.key}
              name={inputField.name}
              value={value}
              proSetting={isProSetting(inputField.proSetting)}
              onChange={(e) => {
                if ( !proSettingChanged(inputField.proSetting) && !moduleEnabledChanged(inputField.moduleEnabled) ) {
                  handleChange(e, inputField.key);
                }
              }}
              onButtonClick={(e) => {
                runUploader(inputField.key);
              }}
            />
          );
          break;

        case "color":
          input = (
            <CustomInput.BasicInput
              wrapperClass="settings-color-picker-parent-class"
              inputClass="setting-color-picker"
              descClass="settings-metabox-description"
              description={inputField.desc}
              key={inputField.key}
              id={inputField.id}
              name={inputField.name}
              type={inputField.type}
              value={value || "#000000"}
              proSetting={isProSetting(inputField.proSetting)}
              onChange={(e) => {
                if ( !proSettingChanged(inputField.proSetting) && !moduleEnabledChanged(inputField.moduleEnabled) ) {
                  handleChange(e, inputField.key);
                }
              }}
            />
          );
          break;

        case "calender":
          input = (
            <CustomInput.CalendarInput
              wrapperClass="settings-calender"
              inputClass="teal"
              multiple={inputField.multiple || false} //for single or mutiple input (true/false)
              range={inputField.range || false} // for range select (true/false)
              value={setting[inputField.key] || ""}
              proSetting={isProSetting(inputField.proSetting)}
              onChange={(e) => {
                if ( !proSettingChanged(inputField.proSetting) && !moduleEnabledChanged(inputField.moduleEnabled) ) {
                  handleChange(e, inputField.key, "single", inputField.type);
                }
              }}
            />
          );
          break;

        // Mapbox support
        case "map":
          input = (
            <CustomInput.MapsInput
              wrapperClass="settings-basic-input-class"
              inputClass="regular-text"
              descClass="settings-metabox-description"
              description={inputField.desc}
              id="searchStoreAddress"
              placeholder="Enter location"
              containerId="store-maps"
              containerClass="store-maps gmap"
              proSetting={isProSetting(inputField.proSetting)}
              Lat={inputField.Lat} //for latitude
              Lng={inputField.Lng} // for longitude
            />
          );
          break;

          //Google Map support
          case "google-map":
            input = (
              <CustomInput.GoogleMap
                wrapperClass="settings-basic-input-class"
                description={inputField.desc}
                id={inputField.key}
                placeholder="Enter location"
                center={inputField.center} // for default location
                proSetting={isProSetting(inputField.proSetting)}
              />
            );
            break;

        case "button":
          input = (
            <div className="form-button-group">
              <div className="setting-section-divider">&nbsp;</div>
              <label className="settings-form-label"></label>
              <div className="settings-input-content">
                <CustomInput.BasicInput
                  wrapperClass="settings-basic-input-class"
                  inputClass="btn default-btn"
                  descClass="settings-metabox-description"
                  description={inputField.desc}
                  type={inputField.type}
                  placeholder={inputField.placeholder}
                  proSetting={isProSetting(inputField.proSetting)}
                  // onChange={handleChange}
                />
              </div>
            </div>
          );
          break;

        case "multi-number":
          input = (
            <CustomInput.MultiNumInput
              parentWrapperClass="settings-basic-input-class"
              childWrapperClass="settings-basic-child-wrap"
              inputWrapperClass="settings-basic-input-child-class"
              innerInputWrapperClass="setting-form-input"
              inputLabelClass="setting-form-input-label"
              idPrefix="setting-integer-input"
              keyName={inputField.key}
              inputClass={inputField.class}
              value={setting[inputField.key]}
              options={inputField.options} // pass the array of fields (in array include label, type, key, value)
              onChange={handleMultiNumberChange}
              proSetting={isProSetting(inputField.proSetting)}
            />
          );
          break;

        case "radio":
          input = (
            <CustomInput.RadioInput
              wrapperClass="settings-form-group-radio"
              inputWrapperClass="radio-input-label-wrap"
              inputClass="setting-form-input"
              descClass="settings-metabox-description"
              activeClass="radio-select-active"
              description={inputField.desc}
              value={value}
              name={inputField.name}
              keyName={inputField.key}
              options={inputField.options} //  pass the array of options
              proSetting={isProSetting(inputField.proSetting)}
              onChange={(e) => {
                if ( !proSettingChanged(inputField.proSetting) && !moduleEnabledChanged(inputField.moduleEnabled) ) {
                  handleChange(e, inputField.key);
                }
              }}
            />
          );
          break;

        // for radio select button with image hover
        case "radio-select":
          input = (
            <CustomInput.RadioInput
              wrapperClass="form-group-radio-select"
              inputWrapperClass="radioselect-class"
              inputClass="setting-form-input"
              radiSelectLabelClass="radio-select-under-label-class"
              labelImgClass="section-img-fluid"
              labelOverlayClass="radioselect-overlay-text"
              labelOverlayText="Select your Store"
              idPrefix="radio-select-under"
              descClass="settings-metabox-description"
              activeClass="radio-select-active"
              description={inputField.desc}
              type="radio-select"
              value={value}
              name={inputField.name}
              keyName={inputField.key}
              options={inputField.options} // in array includes image
              proSetting={isProSetting(inputField.proSetting)}
              onChange={(e) => {
                if ( !proSettingChanged(inputField.proSetting) && !moduleEnabledChanged(inputField.moduleEnabled) ) {
                  handleChange(e, inputField.key);
                }
              }}
            />
          );
          break;

        // for radio color input 
        case "radio-color":
          input = (
            <CustomInput.RadioInput
              wrapperClass="form-group-radio-color"
              inputWrapperClass="settings-radio-color "
              inputClass="setting-form-input"
              idPrefix="radio-color-under"
              activeClass="radio-color-active"
              descClass="settings-metabox-description"
              description={inputField.desc}
              type="radio-color"
              value={value}
              name={inputField.name}
              keyName={inputField.key}
              options={inputField.options} // in array includes color 
              proSetting={isProSetting(inputField.proSetting)}
              onChange={(e) => {
                if ( !proSettingChanged(inputField.proSetting) && !moduleEnabledChanged(inputField.moduleEnabled) ) {
                  handleChange(e, inputField.key);
                }
              }}
            />
          );
          break;

          // Normal select box
          case "select":
            let options = inputField.options;
            input = (
              <CustomInput.SelectInput
                wrapperClass="form-select-field-wrapper"
                descClass="settings-metabox-description"
                description={inputField.desc}
                inputClass={inputField.key}
                options={options}
                value={value}
                proSetting={isProSetting(inputField.proSetting)}
                onChange={(data) => {
                  if ( !proSettingChanged(inputField.proSetting) && !moduleEnabledChanged(inputField.moduleEnabled) ) {
                    settingChanged.current = true;
                    updateSetting(inputField.key, data.value)
                  }
                }}
              />
            );
          break;

        // for multiple select box with select/deselect button
        case "multi-select":
            input = (
              <CustomInput.SelectInput
                wrapperClass="settings-from-multi-select"
                descClass="settings-metabox-description"
                selectDeselectClass="btn-purple select-deselect-trigger"
                selectDeselect={inputField.select_deselect}
                selectDeselectValue="Select / Deselect All"
                description={inputField.desc}
                inputClass={inputField.key}
                options={inputField.options}
                type="multi-select"
                value={value}
                proSetting={isProSetting(inputField.proSetting)}
                onChange={(e, data) => {
                  if ( !proSettingChanged(inputField.proSetting) && !moduleEnabledChanged(inputField.moduleEnabled) ) {
                    handleChange(e, inputField.key, "single", "multi-select", data);
                  }
                }}
                onMultiSelectDeselectChange={(e) =>
                  handlMultiSelectDeselectChange(inputField.key, inputField.options, "multi-select")
                }
              />
            );
        break;

        case "country":
          input = (
            <CustomInput.SelectInput
              wrapperClass="country-choice-class"
              descClass="settings-metabox-description"
              description={inputField.desc}
              inputClass={inputField.key}
              options={inputField.options}
              value={value}
              proSetting={isProSetting(inputField.proSetting)}
              onChange={(e, data) => {
                if ( !proSettingChanged(inputField.proSetting) && !moduleEnabledChanged(inputField.moduleEnabled) ) {
                  handleChange(e, inputField.key, "single", "country", data);
                }
              }}
            />
          );
          break;

        case "state":
          input = (
            <CustomInput.SelectInput
              wrapperClass="state-choice-class"
              descClass="settings-metabox-description"
              description={inputField.desc}
              inputClass={inputField.key}
              options={countryState}
              value={value}
              proSetting={isProSetting(inputField.proSetting)}
              onChange={(e, data) => {
                if ( !proSettingChanged(inputField.proSetting) && !moduleEnabledChanged(inputField.moduleEnabled) ) {
                  handleChange(e, inputField.key, "single", "select", data);
                }
              }}
            />
          );
          break;

        // For single or multiple checkbox (free / pro or some free some pro)
        case "checkbox":
          input = (
            <CustomInput.MultiCheckBox
              wrapperClass="checkbox-list-side-by-side"
              descClass="settings-metabox-description"
              description={inputField.desc}
              selectDeselectClass="btn-purple select-deselect-trigger"
              inputWrapperClass="toggle-checkbox-header"
              inputInnerWrapperClass={inputField.look == 'toggle' ? "toggle-checkbox" : "default-checkbox"}// this props for change classes default/ Toggle
              inputClass={inputField.class}
              tour={inputField.tour}
              hintOuterClass="checkbox-description"
              hintInnerClass="hover-tooltip"
              idPrefix="toggle-switch"
              selectDeselect={inputField.select_deselect}
              selectDeselectValue="Select / Deselect All"
              rightContentClass="settings-checkbox-description"
              rightContent={inputField.right_content} // for place checkbox right
              options={inputField.options}
              value={value}
              proSetting={isProSetting(inputField.proSetting)}
              onChange={(e) => {
                if ( !proSettingChanged(inputField.proSetting) && !moduleEnabledChanged(inputField.moduleEnabled) ) {
                  handleChange(e, inputField.key, "multiple");
                }
              }}
              onMultiSelectDeselectChange={(e) =>
                handlMultiSelectDeselectChange( inputField.key, inputField.options )
              }
              proChanged={() => setModelOpen(true)}
            />
          );
          break;

        // For particular plugin required checkbox ( like if stock-alert plugin not active the checkbox not open)
        case "stock-alert-checkbox":
          input = (
            <CustomInput.MultiCheckBox
              wrapperClass="checkbox-list-side-by-side"
              descClass="settings-metabox-description"
              description={inputField.desc}
              selectDeselectClass="btn-purple select-deselect-trigger"
              inputWrapperClass="toggle-checkbox-header"
              inputInnerWrapperClass="toggle-checkbox"
              inputClass={inputField.class}
              hintOuterClass="dashicons dashicons-info"
              hintInnerClass="hover-tooltip"
              idPrefix="toggle-switch"
              selectDeselect={inputField.select_deselect}
              selectDeselectValue="Select / Deselect All"
              rightContentClass="settings-metabox-description"
              rightContent={inputField.right_content}
              options={inputField.options}
              value={value}
              proSetting={isProSetting(inputField.proSetting)}
              onChange={(e) => {
                const dependentPlugin = inputField.dependentPlugin ? false : true;
                if ( !proSettingChanged(inputField.proSetting) && !moduleEnabledChanged(inputField.moduleEnabled, inputField.dependentSetting, dependentPlugin) ) {
                  if (inputField.dependentPlugin) {
                    handleChange(e, inputField.key, "multiple");
                  }
                }
              }}
              onMultiSelectDeselectChange={(e) =>
                handlMultiSelectDeselectChange(inputField.key, inputField.options)
              }
            />
          );
          break;

        // Rectangle radio toggle button
        case "settingToggle":
          input =(
            <ToggleSetting 
              wrapperClass={`setting-form-input`}
              descClass="settings-metabox-description"
              description={inputField.desc}
              key={inputField.key}
              options={inputField.options}
              value={value || inputField.defaultValue}
              proSetting={isProSetting(inputField.proSetting)}
              onChange={(data) => {
                if ( !proSettingChanged(inputField.proSetting) && !moduleEnabledChanged(inputField.moduleEnabled) ) {
                  settingChanged.current = true;
                  updateSetting(inputField.key, data)
                }
              }}
            />
          );
          break;

        case "wpeditor":
          input = (
            <CustomInput.WpEditor
              apiKey={appLocalizer.mvx_tinymce_key}
              value={value}
              onEditorChange={(e) => {
                if ( !proSettingChanged(inputField.proSetting) && !moduleEnabledChanged(inputField.moduleEnabled) ) {
                  handleChange(e, inputField.key, "simple", "wpeditor");
                }
              }}
            />
          );
          break;

        case "label":
          input = (
            <CustomInput.Label
              wrapperClass="form-group-only-label"
              descClass="settings-metabox-description"
              value={inputField.valuename}
              description={inputField.desc}
            />
          );
          break;

        // For separation (if you want heading in line then put desc or add some description then add hint)
        case "section":
          input = (
            <CustomInput.Section 
            wrapperClass="setting-section-divider"
            value={inputField.desc}
            hint={inputField.hint} />
          );
          break;

        case "blocktext":
          input = (
            <CustomInput.BlockText
              wrapperClass="blocktext-class"
              blockTextClass="settings-metabox-description-code"
              value={inputField.blocktext}
            />
          );
          break;

        // Special input type project specific
        // customize button
        case "button-customizer":
          input = (
            <CustomInput.ButtonCustomizer
              text={(setting[inputField.key]?.button_text) || 'Button Text'}
              proSetting={isProSetting(inputField.proSetting)}
              setting={setting[inputField.key]}
              onChange={(key, value, isRestoreDefaults=false) => {
                if ( !proSettingChanged(inputField.proSetting) && !moduleEnabledChanged(inputField.moduleEnabled) ) {
                  settingChanged.current = true;
                  if (isRestoreDefaults) {
                      updateSetting(inputField.key, value);
                  } else {
                    updateSetting(inputField.key, { ...setting[inputField.key], [key]: value });
                  }
                }
              }}
            />
          );
          break;

        case "stock-alert-form-customizer":
          input = (
            <FormCustomizer
              value={value}
              buttonText={setting.customize_btn && setting.customize_btn.button_text || 'Submit'}
              proSetting={isProSetting(inputField.proSetting)}
              onChange={(e, key) => {
                if ( ! proSettingChanged( inputField.proSetting ) ) {
                  settingChanged.current = true;
                  updateSetting( e, key );
                }
              }}
            />
          );
          break;

        // custom from with free-pro tab
        case "form-customizer":
          input = (
            <FreeProFormCustomizer
              key={inputField.key}
              setting={setting}
              proSetting={isProSetting(inputField.proSetting)}
              proSettingChange={()=> proSettingChanged(inputField.proSetting)}
              moduleEnabledChange={()=> moduleEnabledChanged(inputField.moduleEnabled)}
              onChange={(key, value) => {
                  settingChanged.current = true;
                  updateSetting(key, value);
              }}
            />
          );
          break;

        // shop page builder( use in catalogx )
        case "catalog-customizer":
          input = (
            <CatalogCustomizer
              setting={setting}
              proSetting={appLocalizer.khali_dabba}
              onChange={(key, value) => {
                  settingChanged.current = true;
                  updateSetting(key, value);
              }}
            />
          );
          break;

        // for Grid-table input with multiple checkbox
        case "multi-checkbox-table":
          input = (
            <MultiCheckboxTable
              rows={inputField.rows} // row array
              columns={inputField.columns} // columns array
              description={inputField.desc}
              setting={setting}
              proSetting={isProSetting(inputField.proSetting)}
              modules={modules}
              onChange={(key, value) => {
                if ( !proSettingChanged(inputField.proSetting) && !moduleEnabledChanged(inputField.moduleEnabled) ) {
                  settingChanged.current = true;
                  updateSetting(key, value);
                }
              }}
              moduleChange={(moduleEnabled) => {
                setModelModuleOpen(true);
                setModulePopupData({
                  name: moduleEnabled,
                  settings: '',
                  plugin: '',
                });
                
              }}
            />
          );
          break;

        // Custom form builder
        case "from-builder":
          input = (
            <FromBuilder
              name={inputField.key}
              proSetting={isProSetting(inputField.proSetting)}
              proSettingChange={()=> proSettingChanged(inputField.proSetting)}
              onChange={(value) => {
                  settingChanged.current = true;
                  updateSetting(inputField.key, value);
              }}
            />
          );
          break;

        case "mergeComponent":
          input =(
            <MergeComponent 
              wrapperClass={`setting-form-input`}
              descClass="settings-metabox-description"
              description={inputField.desc}
              value={value}
              fields={inputField.fields} // field array include name, type, options, placeholder
              proSetting={isProSetting(inputField.proSetting)}
              onChange={(data) => {
                if ( !proSettingChanged(inputField.proSetting) && !moduleEnabledChanged(inputField.moduleEnabled) ) {
                  settingChanged.current = true;
                  updateSetting(inputField.key, data)
                }
              }}
            />
          );
          break;

        // for shortcode name and description
        case "shortCode-table":
          input =(
            <ShortCodeTable 
              wrapperClass={`setting-form-input`}
              descClass="settings-metabox-description"
              description={inputField.desc}
              key={inputField.key}
              options={inputField.option} // array includes label and description
              optionLabel={inputField.optionLabel}
            />
          );
          break;

        // Synchronize button (Changes later)
        case "syncbutton":
          input = <SyncNow
            buttonKey={inputField.key}
            apilink={inputField.apilink} // apilink 
            value={inputField.value}
            description={inputField.desc}
            proSetting={isProSetting(inputField.proSetting)}
            proSettingChanged={() => proSettingChanged(inputField.proSetting)}
            interval={inputField.interval}
            statusApiLink={inputField.statusApiLink} // api for each status of synchronization
          />
          break;

        // attribute mapping
        case "sync-map":
          input = <SyncMap
            description={inputField.desc}
            proSetting={isProSetting(inputField.proSetting)}
            proSettingChanged={() => proSettingChanged(inputField.proSetting)}
            value={value}
            syncFieldsMap={inputField.syncFieldsMap}// array includes heading, fields(in fields array all options include)
            onChange={(value) => {
              if (!proSettingChanged(inputField.proSetting) && true) {
                settingChanged.current = true;
                updateSetting(inputField.key, value)
              }
            }}
          />
          break;

        case "sso-key":
          input = <AutoGeneratedDefaultInput
            value={value}
            description={inputField.desc}
            proSetting={isProSetting(inputField.proSetting)}
            onChange={(value) => {
              if (!proSettingChanged(inputField.proSetting) && true) {
                settingChanged.current = true;
                updateSetting(inputField.key, value)
              }
            }}
          />
          break;

        // Test connection button
        case "testconnection":
          input = <ConnectButton 
            apiLink={inputField.apiLink} // apilink 
            tasks={inputField.tasks}/> // all tasks for test connection
          break;

        case "log":
          input = <Log 
            fetchApiLink={inputField.fetchApiLink} // api to fetch the log content
            downloadApiLink={inputField.downloadApiLink} // download the log file
            downloadFileName={inputField.fileName}/> // log file name
          break;

        // Checkbox with custom image
        case "checkbox-custom-img":
          input = <CheckboxCustomImg
            proSetting={isProSetting(inputField.proSetting)}
            description={inputField.desc}
            value={value}
            syncDirections={inputField.syncDirections} // array includes label, value, img1, img2
            onChange={(data) => {
              if ( !proSettingChanged(inputField.proSetting) && !moduleEnabledChanged(inputField.moduleEnabled) ) {
                settingChanged.current = true;
                updateSetting(inputField.key, data)
              }
            }}
          />
          break;

        // For mailchimp list
        case "api-connect":
          input = (
            <CustomInput.InputMailchimpList
              mailchimpKey={inputField.key}
              selectKey={inputField.selectKey}
              optionKey={inputField.optionKey}
              onChange={handleChange}
              proSettingChanged={
                () => proSettingChanged(inputField.proSetting)
              }
              settingChanged={settingChanged}
              apiLink={inputField.apiLink} // fetch api
            />
          );
          break;

        // this component do later
        case "nested-input":
          input = (
            <CustomInput.NestedInput
              // key={inputField.key}
              // name={inputField.name}
              // type={inputField.type}
              // wrapperClass={`setting-form-input`}
              // ParentWrapperClass="settings-basic-input-class"
              // parentOptions={inputField.parent_options}
              // innerParentWrapperClass="settings-basic-input-class"
              // parentLabelClass="setting-form-input-label"
              // parentInputClass="setting-form-input"
              // parentOnchage={handleChange}
              // proSettingChanged={
              //   () => proSettingChanged(inputField.proSetting)
              // }
            />
          );
          break;
        }

        return inputField.type === "section" || inputField.label === "no_label" ? (
          input
        ) : (
          <div key={"g" + inputField.key} className={`form-group ${inputField.classes ? inputField.classes : ''}`}>
            {inputField.type !== "catalog-customizer" && inputField.type !== "from-builder" && inputField.type !== "form-customizer" && (
              <label
                className="settings-form-label"
                key={"l" + inputField.key}
                htmlFor={inputField.key}
              >
                <p>{inputField.label}</p>
              </label>
            )}
            
            <div className="settings-input-content">{input}</div>
          </div>
        );
        
    });
  };

  const handleModelClose = () => {
    setModelOpen(false);
  };

  const handleModulePopupClose = () => {
    setModelModuleOpen(false);
  };

  return (
    <>
      <div className="dynamic-fields-wrapper">
        <Dialog
          className="admin-module-popup"
          open={modelOpen}
          onClose={handleModelClose}
          aria-labelledby="form-dialog-title"
        >
          <span
            className="admin-font adminLib-cross"
            onClick={handleModelClose}
          ></span>
          <Popoup />
        </Dialog>
        <Dialog
          className="admin-module-popup"
          open={modelModuleOpen}
          onClose={handleModulePopupClose}
          aria-labelledby="form-dialog-title"
        >
          <span
            className="admin-font adminLib-cross"
            onClick={handleModulePopupClose}
          ></span>
            <ModulePopoup 
              name={modulePopupData.name} 
              settings={modulePopupData.settings} 
              plugin={modulePopupData.plugin} 
            />
        </Dialog>
        {successMsg && (
          <div className="admin-notice-display-title">
            <i className="admin-font adminLib-icon-yes"></i>
            {successMsg}
          </div>
        )}
        <form
          className="dynamic-form"
          onSubmit={(e) => {
            handleSubmit(e);
          }}
        >
          {renderForm()}
        </form>
      </div>
    </>
  );
};

export default DynamicForm;
