import { useParams } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import {
  useRef, useCallback, useState, useEffect, forwardRef,
} from 'react';

import { L10n } from '@syncfusion/ej2-base';
import { Query } from '@syncfusion/ej2-data';
import { DropDownTreeComponent } from '@syncfusion/ej2-react-dropdowns';
import { ColumnsDirective, ColumnDirective } from '@syncfusion/ej2-react-grids';
import {
  TreeGridComponent, PdfExport, ExcelExport, Resize as TreeGridResize, Sort as TreeGridSort, Filter as TreeGridFilter,
} from '@syncfusion/ej2-react-treegrid';
import {
  Toolbar, Edit, Page, Inject, Filter, Selection, Resize, ColumnChooser, DetailRow, ExcelExport as GridExcelExport, PdfExport as GridPdfExport, RowDD, GridComponent
} from '@syncfusion/ej2-react-grids';

import { TextBoxComponent } from '@syncfusion/ej2-react-inputs';
import { DropDownListComponent } from '@syncfusion/ej2-react-dropdowns';

import DsrPopup from './DsrPopupInEstimate';
import {
  portalPurchaseUnitsService, getValidItemsService, estimateItemsUrl, getDataManagerObj, getDsrItemsUrl,
} from '../../services/dataManager';
import {
  getEstimateItemNumberingSystem, itemListSources, nestEstimateItem, numberingSystemOptions, saveEstimateItemNumberingSystem, updatedEstimateItemSerial,
} from '../../actions/estimation';

import css from './index.module.css';
import { getEstimateListData } from '../../actions/EstimateList';
import { numToChar, toRoman } from '../../services/utils/helpers';
import { getGridColumns, gridTools } from './BoqHelper';
import EstimateItemsGridToolbar from './EstimateItemsGridToolbar';
import NestItemWarningPopup from './NestItemWarningPopup';

import DropdownListComponentCustom from '../../cubeComponent/DropdownListComponentCustom';

const EstimateDsrItems = forwardRef((props, ref) => {
  const {
    source, getValidItemsQuery, itemSelectionCallback, fetchCostDatabase, fetchVersionsOfDsr, currencyData, costDatabaseCurrencySymbol, stateToUpdateBoqDatasource,
  } = props;
  const dispatch = useDispatch();
  const params = useParams();

  const dsrId = undefined
  const dsrVersionId = undefined

  const estimateId = '03433ee1-b360-4019-a242-d0cdbcafea15'
  const versionId = undefined

  const costDatabase = source === itemListSources.COST_DATABASE && useSelector((state) => state.costDatabase);
  const estimateData = source === itemListSources.ESTIMATE && useSelector((state) => state.getEstimateList[0]);

  const [previewMode, setPreviewMode] = useState(false);
  const [openDsrPopup, setOpenDsrPopup] = useState(false);
  const [allowTextWrap, setAllowTextWrap] = useState(false);
  const [savedGridValue, setSavedGridValue] = useState(null);
  const [dsrPopupParentId, setDsrPopupParentId] = useState('0');
  const [allowImportExcel, setAllowImportExcel] = useState(false);
  const [estimationFooterKey, setEstimationFooterKey] = useState(true);
  const [showFileUploadModal, setShowFileUploadModal] = useState(false);
  const [showNestItemWarning, setShowNestItemWarning] = useState(false);
  const [openItemPropertiesSidebar, setOpenItemPropertiesSidebar] = useState({ status: false, data: {} });

  const [selectedNumberingSystemType, setSelectedNumberingSystemType] = useState('');
  const [numberingSystemData, setNumberingSystemData] = useState({ status: false, data: {} });
  const [numberingSystem, setNumberingSystem] = useState({ show: false, parentId: '0', level: 0 });

  const treeGrid = useRef(null);
  const dataGrid = ref || useRef(null);
  const childGridRef = useRef(null);

  const rateRef = useRef(null);
  const quantityRef = useRef(null);
  const itemCodeRef = useRef(null);
  const descriptionRef = useRef(null);
  const purchaseUnitDropdownRef = useRef(null);
  const numberingSystemDataHelperRef = useRef(numberingSystemData);

  const filterOptions = { type: 'Menu' };
  const pageSettings = { pageSizes: true, pageSize: 10 };
  const editSettings = {
    allowAdding: true, allowEditing: true, allowDeleting: true, showDeleteConfirmDialog: true, newRowPosition: 'Bottom',
  };
  L10n.load({ 'en-US': { grid: { CancelButton: 'Discard', ConfirmDelete: 'Are you sure you want to delete this item ?' } } });

  const dsrItemsQuery = new Query().addParams('dsrId', dsrId).addParams('versionId', dsrVersionId);
  const estimateItemsQuery = new Query().addParams('estimateId', estimateId);

  const estimateItemsCustomService = getDataManagerObj(estimateItemsUrl, processGridResponse);
  const dsrItemsCustomService = getDataManagerObj(getDsrItemsUrl, processGridResponse);

  function handleCodeChange({ purchaseUnitsId, rate, description }) {
    purchaseUnitDropdownRef.current.value = purchaseUnitsId;
    purchaseUnitDropdownRef.current.enabled = false;

    descriptionRef.current.value = description;
    descriptionRef.current.enabled = false;

    rateRef.current.value = rate;
    rateRef.current.enabled = false;

    quantityRef.current.enabled = !(!purchaseUnitsId || !rate);
    quantityRef.current.value = null;
  }

  function handleDropdownTreeOnChange(e) {
    const itemSelected = itemCodeRef.current.treeObj.getTreeData(e.value[0]);
    const { purchaseUnitsId, rate, description } = itemSelected[0];

    handleCodeChange({ purchaseUnitsId, rate: rate || null, description });
  }

  function changePreviewStatus() {
    setPreviewMode((prev) => !prev);
  }

  function wrapTextInGrid() {
    if (previewMode || source === itemListSources.ADD_ITEM_POPUP) {
      treeGrid.current.allowTextWrap = !treeGrid.current.allowTextWrap;
      return;
    }

    setAllowTextWrap((prev) => !prev);
  }

  function handleExportPdf() {
    if (previewMode || source === itemListSources.ADD_ITEM_POPUP) {
      treeGrid.current.pdfExport({ pageOrientation: 'Landscape' });
      return;
    }

    dataGrid.current.pdfExport({ pageOrientation: 'Landscape' });
  }

  function handleExportExcel() {
    if (previewMode || source === itemListSources.ADD_ITEM_POPUP) {
      treeGrid.current.excelExport();
      return;
    }
    const exportProperties = { hierarchyExportMode: 'All' };
    dataGrid.current.excelExport(exportProperties);
  }

  function handleImportExcel() {
    if (allowImportExcel) {
      setShowFileUploadModal(true);
    }
  }

  function handleExpandAll(e) {
    if (previewMode || source === itemListSources.ADD_ITEM_POPUP) {
      treeGrid.current.expandAll();
      return;
    }

    dataGrid.current.detailExpandAll();
  }

  function handleCollapseAll() {
    if (previewMode || source === itemListSources.ADD_ITEM_POPUP) {
      treeGrid.current.collapseAll();
      return;
    }
    dataGrid.current.detailCollapseAll();
  }

  function handleDiscardItemAdditionFromPopup() {
    setOpenDsrPopup(false);
    setDsrPopupParentId('0');
  }

  function handleItemAdditionFromPopup(params) {
    const {
      purchaseUnitsId, rate, description, id, parentId,
    } = params;

    handleCodeChange({ purchaseUnitsId, rate, description });

    itemCodeRef.current.value = [id];
  }

  function numberSystemChange(args) {
    setSelectedNumberingSystemType(args.itemData.value);
  }

  async function submitNumberingSystem() {
    const newNumberingSystemData = {
      ...numberingSystemData.data,
      [numberingSystem.parentId]: selectedNumberingSystemType,
    };

    const payload = {
      estimateId,
      numberingSystem: selectedNumberingSystemType,
      parentId: numberingSystem.parentId.toString(),
    };

    setNumberingSystemData({ status: true, data: newNumberingSystemData });
    await saveEstimateItemNumberingSystem(payload);

    closeNumberingSystemPopup();
    refreshDataGrid();
  }

  function changeItemNumberingSystem(grid) {
    const parentId = grid.parentDetails?.parentRowData?.id || '0';
    const level = grid.parentDetails?.parentRowData?.level + 1 || 0;

    setNumberingSystem({ show: true, level, parentId });
  }

  async function fetchEstimateItemNumberingSystem() {
    const res = await getEstimateItemNumberingSystem({ estimateId, versionId });
    const { status, data } = res.data;

    if (status) {
      const dataAsObj = {};
      data.map((item) => dataAsObj[String(item.parentId)] = item.numberingSystem);

      setNumberingSystemData({ status: true, data: dataAsObj });
    }
  }

  function processGridResponse(originalValue) {
    const { errorMsg } = originalValue;

    if (errorMsg) {
      // show error toast
    }

    return originalValue;
  }

  function closeNumberingSystemPopup() {
    setNumberingSystem({ show: false, parentId: '0', level: 0 });
  }

  function openSidebar(record) {
    setOpenItemPropertiesSidebar({ status: true, data: { ...record, manualQuantity: record.quantity } });
  }

  function closeSidebar() {
    setOpenItemPropertiesSidebar({ status: false, data: null });
  }

  function closeFileUploadModal() {
    setShowFileUploadModal(false);
  }

  function enableExcelImport() {
    setAllowImportExcel(true);
  }

  function disableExcelImport() {
    setAllowImportExcel(false);
  }

  function refreshDataGrid() {
    dataGrid.current.refresh();
  }

  async function rowDrop(params) {
    const { fromIndex, dropIndex, data } = params;

    const payload = {
      fromIndex,
      dropIndex: dropIndex || 0,
      itemId: data[0].id,
      parentId: data[0].parentId || '0',
      estimateId,
    };

    if (payload.fromIndex == payload.dropIndex) {
      return;
    }

    const res = await updatedEstimateItemSerial(payload);

    if (res.data.status) {
      refreshDataGrid();
    }
  }

  function closeNestItemWarning() {
    setShowNestItemWarning(false);
  }

  function handleNestItemWarning() {
    nestItemInEstimate(savedGridValue);
    closeNestItemWarning();
  }

  async function nestItemInEstimate(grid) {
    const selectedRecord = grid.getSelectedRecords()[0];
    const {
      code, id, rate, description, purchaseUnitsId,
    } = selectedRecord;

    const data = { itemId: id, estimateId };

    if (!code) {
      data.description = description;
      data.rate = rate;
      data.purchaseUnit = purchaseUnitsId;
    }

    await nestEstimateItem(data);
    refreshDataGrid();
  }

  function nestItemInCostDatabase(grid) {
    const selectedRecord = grid.getSelectedRecords()[0];
    const selectedRow = grid.getSelectedRows()[0];

    const hasChild = selectedRecord.hasChild;

    if (hasChild) {
      return;
    }

    selectedRow.querySelector('td').style.visibility = 'visible';
  }

  function toolbarClickHandler(params) {
    const toolClicked = params.item.properties.id;
    const grid = params.originalEvent.currentTarget.closest('.e-grid').ej2_instances[0];

    if (toolClicked === 'add_item') {
      grid.addRecord();
      return;
    }

    if (toolClicked === 'edit_item') {
      grid.startEdit();
      return;
    }

    if (toolClicked === 'remove_item') {
      const selectedRow = grid.getSelectedRows()[0];
      grid.deleteRow(selectedRow);
      return;
    }

    if (toolClicked === 'nest_item' && source === itemListSources.ESTIMATE) {
      const selectedRecord = grid.getSelectedRecords()[0];

      if (selectedRecord.quantity || selectedRecord.quantityFromTakeoffs) {
        setShowNestItemWarning(true);
        setSavedGridValue(grid);
        return;
      }

      nestItemInEstimate(grid);
    }

    if (toolClicked === 'nest_item' && source === itemListSources.COST_DATABASE) {
      nestItemInCostDatabase(grid);
      return;
    }

    if (toolClicked === 'item_properties') {
      const selectedRecords = grid.getSelectedRecords();
      openSidebar(selectedRecords[0]);
      return;
    }

    if (toolClicked === 'expand_all') {
      grid.detailExpandAll();
      return;
    }

    if (toolClicked === 'collapse_all') {
      grid.detailCollapseAll();
      return;
    }

    if (toolClicked === 'select_numbering') {
      changeItemNumberingSystem(grid);
    }
  }

  function selectionEvent(params) {
    const grid = params.row.offsetParent.closest('.e-grid').ej2_instances[0];
    const numOfRecordsSelected = grid.getSelectedRowIndexes().length;
    const selectedRecords = grid.getSelectedRecords();

    if (!numOfRecordsSelected) {
      grid.toolbarModule.enableItems(['nest_item'], false);
      grid.toolbarModule.enableItems(['edit_item'], false);
      grid.toolbarModule.enableItems(['remove_item'], false);
      grid.toolbarModule.enableItems(['item_properties'], false);
      return;
    }

    if (numOfRecordsSelected === 1) {
      grid.toolbarModule.enableItems(['item_properties'], true);

      if (source === itemListSources.ESTIMATE && !versionId || source === itemListSources.COST_DATABASE && !dsrVersionId) {
        grid.toolbarModule.enableItems(['edit_item'], true);
        grid.toolbarModule.enableItems(['remove_item'], true);

        if (!selectedRecords[0].hasChild) {
          grid.toolbarModule.enableItems(['nest_item'], true);
        }
      }
      return;
    }

    if (numOfRecordsSelected > 1) {
      grid.toolbarModule.enableItems(['nest_item'], false);
      grid.toolbarModule.enableItems(['edit_item'], false);
      grid.toolbarModule.enableItems(['remove_item'], false);
      grid.toolbarModule.enableItems(['item_properties'], false);
    }
  }

  function popupTreeGridSelectionEvent(params) {
    const { name, data } = params;

    if (name === 'rowSelected' && source === itemListSources.ADD_ITEM_POPUP && itemSelectionCallback) {
      itemSelectionCallback(params.data);
      return;
    }

    if (name === 'rowDeselected' && source === itemListSources.ADD_ITEM_POPUP && itemSelectionCallback) {
      itemSelectionCallback(null);
    }
  }

  function validationForAddItemInEstimate({
    quantity, itemId, description, purchaseUnit, rate,
  }) {
    let content;

    if (quantity < 0) {
      content = 'Please enter a positive value for the quantity';
      return { status: false, content };
    }

    if (quantity && (!purchaseUnit || !rate)) {
      content = 'Please specify the unit and rate for the item';
      return { status: false, content };
    }

    if (!itemId && purchaseUnit && !rate) {
      content = 'Please enter the value of rate';
      return { status: false, content };
    }

    if (!itemId && !purchaseUnit && rate) {
      content = 'Please enter the value of unit';
      return { status: false, content };
    }

    if (!itemId && !description) {
      content = 'Please enter the description for the item';
      return { status: false, content };
    }

    return { status: true };
  }

  function addRecordInEstimate(params) {
    const { data, form } = params;
    const { purchaseUnit, description, code } = data;

    const quantity = parseFloat(data.quantity);
    const rate = parseFloat(data.rate);

    const itemId = code && code.length ? code[0] : undefined;

    const validationCheck = validationForAddItemInEstimate({
      quantity, itemId, description, purchaseUnit, rate,
    });

    if (!validationCheck.status) {
      params.cancel = true;

      const { content } = validationCheck;
      // show toast
      return;
    }

    const grid = form.closest('.e-grid').ej2_instances[0];
    const parentData = grid?.parentDetails?.parentRowData;

    const parentId = parentData?.id || '0';
    const level = parentData?.id ? parentData?.level + 1 : 0;

    const payload = {
      itemId, level, parentId, quantity, purchaseUnit, rate, description,
    };
    params.data = payload;
  }

  function validationForEditItemInEstimate({
    itemId, code, description, purchaseUnit, quantity, rate,
  }) {
    let content;

    if (rate <= 0) {
      content = 'Please enter a positive value for rate';
      return { status: false, content };
    }

    if (quantity < 0) {
      content = 'Please enter a non negative value for rate';
      return { status: false, content };
    }

    if (!code && !purchaseUnit && rate) {
      content = 'Please enter a purchase unit';
      return { status: false, content };
    }

    if (!code && purchaseUnit && !rate) {
      content = 'Please enter a positive value for rate';
      return { status: false, content };
    }

    if (!code && !purchaseUnit && !rate && quantity) {
      content = 'Please enter the unit and rate for the item';
      return { status: false, content };
    }

    return { status: true };
  }

  function editRecordInEstimate(params) {
    const { data } = params;
    const {
      id: itemId, description, purchaseUnit, code,
    } = data;

    const quantity = parseFloat(data.quantity);
    const rate = parseFloat(data.rate);

    const payload = {
      itemId, description, purchaseUnit, quantity, rate,
    };

    const validationCheck = validationForEditItemInEstimate({ ...payload, code });

    if (!validationCheck.status) {
      params.cancel = true;

      const { content } = validationCheck;
      // show toast
      return;
    }

    params.data = payload;
  }

  function validationForAddItemInCostDatabase({ code, description, rate }) {
    let content;

    if (!code || !description) {
      content = 'Please enter the code and description for the item';
      return { status: false, content };
    }

    if (rate && rate <= 0) {
      content = 'Please enter a positive value for rate';
      return { status: false, content };
    }

    return { status: true };
  }

  function addRecordInCostDatabase(params) {
    const { data, form } = params;
    const { code, description } = data;

    const rate = parseFloat(data.rate);

    const validationCheck = validationForAddItemInCostDatabase({ code, description, rate });

    if (!validationCheck.status) {
      params.cancel = true;

      const { content } = validationCheck;
      // show toast
      return;
    }

    const grid = form.closest('.e-grid').ej2_instances[0];
    const parentData = grid?.parentDetails?.parentRowData;

    const parentId = parentData?.id || '0';
    const level = parentData?.id ? parentData?.level + 1 : 0;

    params.data.level = level;
    params.data.parentId = parentId;
  }

  function editRecordInCostDatabase(params) {
    const { data } = params;
    const {
      id, code, description, purchaseUnit, rate,
    } = data;

    const validationCheck = validationForAddItemInCostDatabase({ code, description, rate });

    if (!validationCheck.status) {
      params.cancel = true;

      const { content } = validationCheck;
      // show toast
      return;
    }

    params.data = {
      id, code, description, purchaseUnit, rate,
    };
  }

  function actionBegin(params) {
    const { action, requestType } = params;

    if (action === 'add' && requestType === 'save' && source === itemListSources.ESTIMATE) {
      addRecordInEstimate(params);
      return;
    }

    if (action === 'add' && requestType === 'save' && source === itemListSources.COST_DATABASE) {
      addRecordInCostDatabase(params);
      return;
    }

    if (action === 'edit' && requestType === 'save' && source === itemListSources.ESTIMATE) {
      editRecordInEstimate(params);
      return;
    }

    if (action === 'edit' && requestType === 'save' && source === itemListSources.COST_DATABASE) {
      editRecordInCostDatabase(params);
    }
  }

  function actionComplete(params) {
    const { action, requestType } = params;

    if (((action === 'edit' || action === 'add') && requestType === 'save') || requestType === 'delete') {
      dataGrid.current.refresh();
    }

    if (source === itemListSources.COST_DATABASE) {
      if (((action === 'edit' || action === 'add') && requestType === 'save') || requestType === 'delete') {
        fetchCostDatabase();
        fetchVersionsOfDsr();
      }
    }

    if (source === itemListSources.ESTIMATE) {
      if (((action === 'edit' || action === 'add') && requestType === 'save') || requestType === 'delete') {
        dispatch(getEstimateListData({ estimateId, versionId }));
        setEstimationFooterKey((prev) => !prev);
      }
    }
  }

  function detailDataBound(params) {
    const childGrid = params.childGrid;
    childGrid.childGrid = getChildGrid;
  }

  function dataGridDataBound() {
    if (source === itemListSources.ESTIMATE) {
      const records = dataGrid.current.getCurrentViewRecords();

      if (!records.length) {
        enableExcelImport();
        return;
      }

      disableExcelImport();
    }
  }

  function rowDataBound(params) {
    const hasChild = params.data.hasChild;

    if (!hasChild) {
      params.row.querySelector('td').style.visibility = 'hidden';
    }
  }

  function treeRowDataBound(params) {
    if (source === itemListSources.ADD_ITEM_POPUP && !params.data.allowSelection) {
      params.row.classList.add('e-disabled');
      params.isSelectable = false;
    }
  }

  function openDsrPopupFn(params) {
    const { column } = params;
    const { parentDetails } = column?.parent;
    const parentId = parentDetails?.parentRowData?.id || '0';

    setOpenDsrPopup(true);
    setDsrPopupParentId(parentId);
  }

  function getNumberFromNumberSystem(value, fromNumberSystem) {
    if (fromNumberSystem == 0) {
      return value;
    }

    if ([1, 2].includes(fromNumberSystem)) {
      return charToNum(value);
    }

    if ([3, 4].includes(fromNumberSystem)) {
      return fromRoman(value);
    }
  }

  function getSymbolForNumber(number, toNumberSystem, fromNumberSystem) {
    let convertedNumber = number;

    if (fromNumberSystem) {
      convertedNumber = getNumberFromNumberSystem(number, fromNumberSystem);
    }

    if (toNumberSystem == 1) {
      return numToChar(convertedNumber).toLowerCase();
    }

    if (toNumberSystem == 2) {
      return numToChar(convertedNumber).toUpperCase();
    }

    if (toNumberSystem == 3) {
      return toRoman(convertedNumber).toLowerCase();
    }

    if (toNumberSystem == 4) {
      return toRoman(convertedNumber).toUpperCase();
    }

    return number;
  }

  function getSerialForParent(grid) {
    let result = '';
    let immediateParentSerial = '';

    if (grid.parentDetails) {
      immediateParentSerial = grid.parentDetails.parentRowData.serial;
      const immediateParentsParentId = grid.parentDetails.parentRowData.parentId;

      if (numberingSystemDataHelperRef.current.data.hasOwnProperty(immediateParentsParentId)) {
        const toNumberSystem = numberingSystemDataHelperRef.current.data[immediateParentsParentId];
        immediateParentSerial = getSymbolForNumber(immediateParentSerial, toNumberSystem, 0);
      }

      const immediateParentParentGridId = grid.parentDetails.parentID;
      const element = document.querySelector(`#${immediateParentParentGridId}`);
      const grandParentGrid = element.ej2_instances[0];

      const grandParentSerial = getSerialForParent(grandParentGrid);
      result = grandParentSerial ? `${grandParentSerial}.${immediateParentSerial}` : `${immediateParentSerial}`;
    }

    return result;
  }

  function getSerialForParentInPreviewMode(parentId, level) {
    if (level < 0) {
      return null;
    }

    const recordsAtCurrentLevel = treeGrid.current.getRecordDetails(level);
    const { records } = recordsAtCurrentLevel;
    const parentRecord = records.find((record) => record.id === parentId);

    if (!parentRecord) {
      return null;
    }

    const { parentId: grandParentId, serial } = parentRecord;

    let result = `${serial}`;

    if (numberingSystemDataHelperRef.current.data.hasOwnProperty(grandParentId)) {
      const toNumberSystem = numberingSystemDataHelperRef.current.data[grandParentId];
      result = getSymbolForNumber(serial, toNumberSystem, 0);
    }

    const grandParentSerial = getSerialForParentInPreviewMode(grandParentId, level - 1);

    if (grandParentSerial) {
      result = `${grandParentSerial}.${result}`;
    }

    return result;
  }

  function serialTemplate(params) {
    const {
      serial, parentId, column, level,
    } = params;
    let result = serial;

    if (numberingSystemDataHelperRef.current.data.hasOwnProperty(parentId)) {
      const toNumberSystem = numberingSystemDataHelperRef.current.data[parentId];
      result = getSymbolForNumber(serial, toNumberSystem, 0);
    }

    const parentSerial = column ? getSerialForParent(column.parent) : getSerialForParentInPreviewMode(parentId, level - 1);

    return parentSerial ? `${parentSerial}.${result}` : `${result}`;
  }

  function codeEditTemplate(params) {
    if (source === itemListSources.ESTIMATE) {
      const { id, column } = params;
      const enabled = !id;

      const value = id ? [id] : null;

      const { parentDetails } = column?.parent;
      const parentId = parentDetails?.parentRowData?.id || '0';

      const codeQuery = new Query().addParams('estimateId', estimateId).addParams('estimateParentId', parentId);

      const fields = {
        dataSource: getValidItemsService,
        query: codeQuery,
        value: 'id',
        text: 'code',
        hasChildren: 'hasChild',
        selectable: 'allowSelection',
        loadOnDemand: true,
        child: {
          dataSource: getValidItemsService, query: codeQuery, value: 'id', parentValue: 'parentId', text: 'code', hasChildren: 'hasChild', selectable: 'allowSelection', loadOnDemand: true,
        },
      };

      return (
        <div className={css.codeTemplateContainer}>
          <DropDownTreeComponent
            cssClass={css.dropdownTreeExpandIconShift}
            enabled={enabled}
            ref={itemCodeRef}
            value={value}
            id={params.column.field}
            name={params.column.field}
            change={handleDropdownTreeOnChange}
            fields={fields}
            changeOnBlur={false}
            showClearButton={false}
            treeSettings={{ loadOnDemand: true, expandOn: '' }}
            filterBarPlaceholder="Enter code"
            filterType="StartsWith"
          />
          <span className={css.openDsrIcon} onClick={() => openDsrPopupFn(params)}>&#9432;</span>
        </div>
      );
    }

    if (source === itemListSources.COST_DATABASE) {
      const { code } = params;

      return (
        <TextBoxComponent
          type="text"
          changeOnBlur={false}
          placeholder="Enter Code"
          value={code}
          id={params.column.field}
          name={params.column.field}
          ref={itemCodeRef}
        />
      );
    }
  }

  function unitTemplate(params) {
    const { hasChild, purchaseUnit } = params;
    const res = hasChild ? null : purchaseUnit;

    return res;
  }

  function unitEditTemplate(params) {
    const {
      id, code, hasChild, purchaseUnitsId, quantityFromTakeoffs,
    } = params;

    return (
      <DropdownListComponentCustom
        enabled={!(source === itemListSources.ESTIMATE && id && (code || hasChild || quantityFromTakeoffs))}
        value={purchaseUnitsId}
        id={params.column.field}
        name={params.column.field}
        ref={purchaseUnitDropdownRef}
        dataSource={portalPurchaseUnitsService}
        fields={{ text: 'name', value: 'id' }}
      />
    );
  }

  function descriptionEditTemplate(params) {
    const {
      id, code, description, quantityFromTakeoffs,
    } = params;

    return (
      <TextBoxComponent
        type="text"
        disabled={source === itemListSources.ESTIMATE && id && (code || quantityFromTakeoffs)}
        placeholder="Enter Description"
        changeOnBlur={false}
        value={description}
        id={params.column.field}
        name={params.column.field}
        ref={descriptionRef}
      />
    );
  }

  function quantityTemplate(params) {
    const { hasChild, quantity, quantityFromTakeoffs } = params;
    const res = hasChild ? null : parseFloat(parseFloat(quantity + quantityFromTakeoffs).toFixed(2));

    return res;
  }

  function quantityEditTemplate(params) {
    const {
      id, hasChild, quantity, quantityFromTakeoffs, purchaseUnitsId, rate, code,
    } = params;

    let disabled = false;

    const takeoffQuantityCheck = id && (hasChild || quantityFromTakeoffs);
    const purchaseUnitCheck = id && code && (!purchaseUnitsId || !rate);

    if (takeoffQuantityCheck || purchaseUnitCheck) {
      disabled = true;
    }

    return (
      <TextBoxComponent
        type="number"
        disabled={disabled}
        placeholder="Enter Quantity"
        changeOnBlur={false}
        value={parseFloat(parseFloat(quantity + quantityFromTakeoffs).toFixed(2))}
        id={params.column.field}
        name={params.column.field}
        ref={quantityRef}
      />
    );
  }

  function rateTemplate(params) {
    const { rate, hasChild } = params;
    const res = hasChild || rate === '0' ? null : rate;

    return res;
  }

  function rateEditTemplate(params) {
    const {
      id, code, hasChild, rate, quantityFromTakeoffs,
    } = params;

    return (
      <TextBoxComponent
        type="number"
        disabled={source === itemListSources.ESTIMATE && id && (code || hasChild || quantityFromTakeoffs)}
        placeholder="Enter Rate"
        changeOnBlur={false}
        value={rate}
        id={params.column.field}
        name={params.column.field}
        ref={rateRef}
      />
    );
  }

  function amountTemplate(params) {
    const { amount } = params;

    return parseFloat(parseFloat(amount).toFixed(2));
  }

  function amountEditTemplate(params) {
    const { amount } = params;

    const result = amount || amount === 0 ? parseFloat(parseFloat(amount).toFixed(2)) : null;
    return result;
  }

  const gridColumns = getGridColumns({
    source, currencyData, costDatabaseCurrencySymbol, serialTemplate, codeEditTemplate, descriptionEditTemplate, quantityTemplate, quantityEditTemplate, unitEditTemplate, unitTemplate, rateEditTemplate, rateTemplate, amountTemplate, amountEditTemplate,
  });

  const getChildGrid = {
    allowAdding: true,
    allowEditing: true,
    allowSorting: true,
    allowResizing: true,
    allowFiltering: true,
    columns: gridColumns,
    ref: childGridRef,
    filterSettings: { type: 'Menu' },
    pageSettings: { pageSize: 6, pageCount: 5 },
    editSettings,
    queryString: 'id',
    foreignKeyField: 'parentId',
    // allowRowDragAndDrop: source === itemListSources.ESTIMATE,
    toolbar: gridTools({ source, estimateVersionId: versionId, dsrVersionId }),
    actionBegin,
    actionComplete,
    toolbarClick: toolbarClickHandler,
    detailDataBound,
    rowSelected: selectionEvent,
    rowDeselected: selectionEvent,
    rowDataBound,
    // rowDrop,
    rowHeight: 35,
    dataSource: source === itemListSources.ESTIMATE ? estimateItemsCustomService : source === itemListSources.COST_DATABASE ? dsrItemsCustomService : getValidItemsService,
    query: source === itemListSources.ESTIMATE ? estimateItemsQuery : source === itemListSources.COST_DATABASE ? dsrItemsQuery : getValidItemsQuery,
  };

  function getColumnsDirective() {
    return (
      <ColumnsDirective>
        {gridColumns.map((column) => <ColumnDirective key={`columnDirective_${column.field}`} {...column} />)}
      </ColumnsDirective>
    );
  }

  const getDataGrid = useCallback(
    () => (
      <GridComponent
        ref={dataGrid}
        dataSource={source === itemListSources.ESTIMATE ? estimateItemsCustomService : dsrItemsCustomService}
        query={source === itemListSources.ESTIMATE ? estimateItemsQuery : dsrItemsQuery}
        toolbar={gridTools({ source, estimateVersionId: versionId, dsrVersionId })}
        toolbarClick={toolbarClickHandler}
        editSettings={editSettings}
        pageSettings={pageSettings}
        actionBegin={actionBegin}
        allowTextWrap={allowTextWrap}
        // allowRowDragAndDrop={source === itemListSources.ESTIMATE}
        actionComplete={actionComplete}
        childGrid={getChildGrid}
        allowEditing
        allowPaging
        allowResizing
        allowSelection
        allowExcelExport
        enableStickyHeader
        height="100%"
        allowPdfExport
        showColumnChooser
        rowSelected={selectionEvent}
        rowDeselected={selectionEvent}
        detailDataBound={detailDataBound}
        dataBound={dataGridDataBound}
        rowDataBound={rowDataBound}
        rowHeight={35}
        cssClass={css.gridTableWrapper}
      // rowDrop={rowDrop}
      >
        {getColumnsDirective()}
        <Inject services={[Toolbar, ColumnChooser, Edit, Page, Resize, Selection, DetailRow, GridExcelExport, GridPdfExport]} />
      </GridComponent>
    ),
    [allowTextWrap],
  );

  const getTreeGrid = useCallback(
    () => (
      <TreeGridComponent
        ref={treeGrid}
        query={source === itemListSources.ESTIMATE ? estimateItemsQuery : source === itemListSources.COST_DATABASE ? dsrItemsQuery : getValidItemsQuery}
        dataSource={source === itemListSources.ESTIMATE ? estimateItemsCustomService : source === itemListSources.COST_DATABASE ? dsrItemsCustomService : getValidItemsService}
        pageSettings={pageSettings}
        allowExcelExport
        allowPdfExport
        allowSorting
        allowResizing
        allowPaging
        enableCollapseAll
        allowSelection
        allowTextWrap={allowTextWrap}
        className={source === itemListSources.ADD_ITEM_POPUP ? css.treeGridContainer : undefined}
        idMapping="id"
        parentIdMapping="parentId"
        hasChildMapping="hasChild"
        rowSelected={popupTreeGridSelectionEvent}
        rowDeselected={popupTreeGridSelectionEvent}
        treeColumnIndex={1}
        enableHover="false"
        rowDataBound={treeRowDataBound}
        height="100%"
      >
        {getColumnsDirective()}
        <Inject services={[DetailRow, PdfExport, Toolbar, ExcelExport, TreeGridResize, TreeGridSort, Selection]} />
      </TreeGridComponent>
    ), [],
  );

  const itemsData = () => (
    <>
      {previewMode || source === itemListSources.ADD_ITEM_POPUP ? getTreeGrid() : getDataGrid()}
    </>
  );

  useEffect(() => {
    if (source === itemListSources.ESTIMATE && dataGrid && dataGrid.current) {
      refreshDataGrid();
    }
  }, [stateToUpdateBoqDatasource]);

  useEffect(() => {
    numberingSystemDataHelperRef.current = numberingSystemData;
  }, [numberingSystemData]);

  return (
    <>
      <div className={css.containerBOQ}>
        {openDsrPopup
          && (
            <DsrPopup
              parentId={dsrPopupParentId}
              estimateId={estimateId}
              handleDiscardItemAdditionFromPopup={handleDiscardItemAdditionFromPopup}
              handleItemAdditionFromPopup={handleItemAdditionFromPopup}
              currencyData={currencyData}
            />
          )}
        {showNestItemWarning
          && (
            <NestItemWarningPopup
              handleNestItemWarning={handleNestItemWarning}
              closeNestItemWarning={closeNestItemWarning}
            />
          )}

        <EstimateItemsGridToolbar
          source={source}
          previewMode={previewMode}
          changePreviewStatus={changePreviewStatus}
          wrapTextInGrid={wrapTextInGrid}
          handleExportPdf={handleExportPdf}
          handleExportExcel={handleExportExcel}
          allowImportExcel={allowImportExcel}
          handleImportExcel={handleImportExcel}
          handleExpandAll={handleExpandAll}
          handleCollapseAll={handleCollapseAll}
        />
        {itemsData()}
      </div>
    </>
  );
});

export default EstimateDsrItems;
