import {
    useCallback, useContext, useEffect, useRef, useState,
  } from 'react';
  import { useNavigate, useParams } from 'react-router-dom';
  import { useDispatch, useSelector } from 'react-redux';
  import {
    GanttComponent,
    EditDialogFieldsDirective,
    DayMarkers,
    EditDialogFieldDirective,
    Inject,
    Edit,
    Selection,
    Toolbar,
    ColumnsDirective,
    ColumnDirective,
    RowDD,
    Filter,
    AddDialogFieldsDirective,
    AddDialogFieldDirective,
    Sort,
    CriticalPath,
    VirtualScroll,
    Resize,
  } from '@syncfusion/ej2-react-gantt';
  // import GanttComponent from '../../../cubeComponent/html/GanttComponent';
  import { Predicate, Query } from '@syncfusion/ej2-data';
  import css from '../index.module.css';
  import {
    getScheduleDetails, getSelectionSetElements, setTaskData, updateTaskTypeOfScheduleTask,
  } from '../../../actions/task';
  import ExistingTasks from './ExistingTasks';
  import ExcelImport from './ExcelImport';
  import {
    getDataManagerObj, performGanttOperationsUrl, resourceService, taskTypeService,
  } from '../../../services/dataManager';
  import { DropDownList } from '@syncfusion/ej2-react-dropdowns';
  import DropDownListComponent from '../../../cubeComponent/form/DropdownListComponent';
  import { showToastNotification } from '../../../actions/toast';
  import { TOAST_TYPE_ERROR, TOAST_TYPE_SUCCESS } from '../../../services/constants';
  import { hexToRgb } from '../../../actions/estimation';
  import { DateTimePicker } from '@syncfusion/ej2-react-calendars';
  import { HoopsViewerContext } from '../../HoopsViewer/HoopsViewerContext';
  import { getNodeIdsFromCubeUniqueId } from '../../../services/cubeViewHelper';
  import InspectionCreation from '../../CreateInspectionAndProgress/InspectionCreation';
  import { formCategories } from '@Components/PortalSetings/Configuration/FormsAndFields/constants';
  import LinkBoqToTaskAndForm from '@Components/CreateInspectionAndProgress/linkBoqItemsToTaskAndForms';
  import { forwardRef } from 'react';
  import ModalStateDialogComponent from '@CubeComponents/html/modal/ModalWithState';
  import IconComponent from '@CubeComponents/icons';
  import GridComponent from '../../../cubeComponent/html/grid';
  import { getContractItemDetails, linkEntitiesToContract } from '../../../actions/Contracts';
  import ButtonComponent from '../../../cubeComponent/form/ButtonComponent';
  import { BUTTON_TYPES } from '../../../cubeComponent/constants/globalVariable';
  import { getBoqItems, linkBoqItems } from '../../../actions/schedules';
  import { NumericTextBoxComponent } from '@syncfusion/ej2-react-inputs';
  
  const GanttChart = forwardRef((props, ref) => {
    const dataGrid = ref || useRef();
    const attachedItemRef = useRef();
    let actualEndDateField;
    let actualStartDateField;
    const projectData = useSelector((state) => state.projectData);
    const contractDetails = useSelector((state) => state.contractDetails);
    const layout = useSelector((state) => state.layout);
    const [showWarning, setShowWarning] = useState({ status: false });
    const performGanttOperationsService = getDataManagerObj(performGanttOperationsUrl, processResponseFun);
  
    const url = useParams();
    const navigate = useNavigate();
    const { viewerImpl } = useContext(HoopsViewerContext);
    const ganttQuery = new Query().addParams('fileVersionId', url.fileId).addParams('scheduleId', props.scheduleId).addParams('projectId', props.projectId)
      .addParams('spaceId', props.spaceId)
      .addParams('contractId', url.contractId);
  
    const taskTypeQuery = new Query().addParams('scheduleId', props.scheduleId);
    const { TaskData, sliderTimer, selectionSetTaskElements } = useSelector((state) => state);
    let taskTypeDiv; let actualEndDateDiv; let actualStartDateDiv;
  
    const predicate = new Predicate('projectId', 'equal', props.projectId).and('scheduleId', 'equal', props.scheduleId);
    const dispatch = useDispatch();
    const scheduleId = props.scheduleId;
    const spaceId = props.spaceId;
    const projectId = props.projectId;
    const [taskTypeDataSource, setTaskTypeDataSource] = useState([]);
    const [showBoqModal, setShowBoqModal] = useState(false);
    const [showImportModal, setShowImportModal] = useState(false);
    const [resourcesDataSource, setResourcesDataSource] = useState([]);
    const [aiCounter, setAiCounter] = useState(0);
    const [isGanttRendered, setIsGanttRendered] = useState(false);
    const [showFormFlowCreationModal, setShowFormFlowCreationModal] = useState({ status: false, category: '' });
    const [showTaskModal, setTaskModal] = useState(false);
    const [attachedItems, setAttachedItems] = useState(null);
    const [taskItemQuantity, setTaskItemQuantity] = useState({});
  
    const taskFields = {
      id: 'TaskID',
      name: 'TaskName',
      startDate: 'StartDate',
      endDate: 'EndDate',
      duration: 'Duration',
      progress: 'Progress',
      taskType: 'taskTypeId',
      actualStartDate: 'actualStartDate',
      actualEndDate: 'actualEndDate',
      dependency: 'Predecessor',
      child: 'SubTasks',
      notes: 'info',
      resourceInfo: 'resources',
      // hasChildMapping: 'isParent',
      // parentID: 'parentId'
    };
  
    const resourceFields = {
      id: '_id',
      name: 'name',
    };
  
    const editSettings = {
      allowAdding: !url.contractId,
      allowEditing: !url.contractId,
      allowDeleting: true,
      allowTaskbarEditing: !url.contractId,
      showDeleteConfirmDialog: !url.contractId,
    };
  
    const splitterSettings = {
      columnIndex: 2,
      position: '40%',
    };
    const gridLines = 'Both';
  
    const toolbar = [
      ...(!url.contractId) ? ['Add',
      {
        text: 'Import',
        tooltipText: 'Import Excel',
        prefixIcon: 'e-add',
        id: 'excel_import',
      }] : [{
        text: 'Attach Tasks',
        prefixIcon: 'e-link',
        id: 'attach_tasks_contract',
      }],
      ...!url.contractId ? [{
        text: 'Remove',
        prefixIcon: 'e-delete',
        id: 'Editing_delete',
      }, 'Edit', 'Update', 'Cancel', 'Indent', 'Outdent']
        : [{
          text: 'Un-link',
          prefixIcon: 'e-break',
          id: 'un-link-from-contract',
          disabled: true,
        }],
      'ExpandAll', 'CollapseAll', 'ZoomIn', 'ZoomOut', 'ZoomToFit',
  
      ...(url.contractId) ? [] : [{
        text: 'Add Existing Tasks',
        tooltipText: 'Task Creation',
        prefixIcon: 'e-add',
        id: 'custom_createUnAsTsk',
      }],
      ...(url.contractId) ? [{
        text: 'Link BOQ Items',
        tooltipText: 'Link BOQ Items',
        prefixIcon: 'e-link',
        id: 'link_boq_items',
        disabled: true,
      }] : [],
      // ...(layout.INSPECTION?.ENABLE && url.contractId) ? [{
      //   text: 'Create Inspection',
      //   prefixIcon: 'e-description',
      //   id: 'create_inspection',
      // }] : [],
      // ...(layout.PROGRESS_UPDATES?.ENABLE && url.contractId) ? [{
      //   text: 'Update Site Progress',
      //   prefixIcon: 'e-description',
      //   id: 'create_progressUpdates',
      // }] : [],
      // ...(layout.PROGRESS_UPDATES?.ENABLE && url.contractId) ? [{
      //   text: 'Change Order',
      //   prefixIcon: 'e-description',
      //   id: 'change_order',
      // }] : [],
    ];
  
    const modifyData = (data) => {
      const tempSet = new Set([...data.resources]);
      const resources = Array.from(tempSet);
      if (data.SubTasks.length) {
        const arrangedData = arrangeData(data.SubTasks);
        data.SubTasks = arrangedData;
      }
      return {
        ...data,
        resources,
        StartDate: data.StartDate ? new Date(data.StartDate) : null,
        EndDate: data.EndDate ? new Date(data.EndDate) : null,
        actualStartDate: data.actualStartDate ? new Date(data.actualStartDate) : null,
        actualEndDate: data.actualEndDate ? new Date(data.actualEndDate) : null,
      };
    };
  
    const arrangeData = (data) => {
      const newData = data.map((data) => {
        const modifiedData = modifyData(data);
        return modifiedData;
      });
      return newData;
    };
  
    function processResponseFun(args) {
      if (args.count && args.result) {
        const finalData = arrangeData(args.result);
        args.result = finalData;
        return args;
      }
      return args;
    }
  
    const showWarningModal = (source) => {
      setShowWarning({ status: true, source });
    };
    const hideWarningModal = () => {
      setShowWarning({ status: false });
    };
    const toolbarClickHandler = async (args) => {
      if (args.item.properties.id === 'custom_createUnAsTsk') {
        setTaskModal(true);
      }
      if (args.item.properties.id === 'attach_tasks_contract') {
        props.attachTaskModalState();
      }
      else if (args.item.properties.id === 'link_boq_items') {
        setShowBoqModal(true);
      }
      else if (args.item.properties.id === 'un-link-from-contract') {
        showWarningModal('unLinkTask');
      }
      else if (args.item.properties.id === 'excel_import') {
        setShowImportModal(true);
      }
      // else if (args.item.properties.id === 'create_inspection') {
      //   setShowFormFlowCreationModal({ status: true, category: formCategories.inspection });
      // }
      // else if (args.item.properties.id === 'create_progressUpdates') {
      //   setShowFormFlowCreationModal({ status: true, category: formCategories.progressUpdates });
      // }
      // else if (args.item.properties.id === 'change_order') {
      //   setShowFormFlowCreationModal({ status: true, category: formCategories.changeOrder });
      // }
    };
  
    useEffect(() => {
      if (props.refreshGrid) {
        refreshGrid();
        if (props.setRefreshGrid) {
          props.setRefreshGrid(false);
        }
      }
    }, [props.refreshGrid]);
  
    const refreshGrid = () => {
      setTaskModal(false);
      dataGrid.current.refresh();
    };
  
    const timelineSettings = {
      topTier: {
        unit: 'Week',
        format: 'MMM dd, y',
      },
      bottomTier: {
        unit: 'Day',
      },
    };
  
    const FilterOption = {
      type: 'Menu',
    };
  
    const labelSettings = {
      leftLabel: 'TaskName',
      rightLabel: '${Progress}%  ${resources}',
    };
  
    const init = async () => {
      if (props.activeTab == 'simulation') {
        const ganttData = await performGanttOperationsService.executeQuery(ganttQuery);
        if (ganttData.result.length || ganttData.result.count) {
          dispatch(setTaskData(ganttData.result.result ?? ganttData.result));
        }
      }
      if (url.fileId) {
        dispatch(getSelectionSetElements({ scheduleId, fileVersionId: url.fileId }));
      }
    };
  
    useEffect(() => {
      init();
    }, [props.activeTab]);
  
    const created = async (args) => {
      const taskTypeData = await taskTypeService.executeQuery(taskTypeQuery);
      setTaskTypeDataSource(taskTypeData.result);
      const resourcesData = await resourceService.executeQuery(new Query().addParams('fileVersionId', url.fileId).addParams('scheduleId', props.scheduleId)
        .requiresCount(true));
      // FOR NOW KEEPING THE UNITS TO HARDCODED 1, ADVANCE FEATURE TO BE IMPLEMENTED LATER
      const modifiedResources = resourcesData?.result?.map((resource) => {
        const data = { _id: resource._id, name: resource.name, totalUnit: 1 };
        return data;
      });
      setResourcesDataSource(modifiedResources);
      if (dataGrid.current?.toolbarModule) {
        if (contractDetails.linkedSchedule?.isLocked || contractDetails.isLocked) {
          dataGrid.current.toolbarModule.enableItems(['attach_tasks_contract'], false);
        }
        // dataGrid.current.toolbarModule.enableItems(['create_inspection'], false);
        // dataGrid.current.toolbarModule.enableItems(['create_progressUpdates'], false);
        // dataGrid.current.toolbarModule.enableItems(['change_order'], false);
      }
    };
  
    const showErrorToast = (message) => {
      dispatch(
        showToastNotification({
          content: message,
          type: TOAST_TYPE_ERROR,
        }),
      );
    };
  
    useEffect(() => {
      if (dataGrid.current.element?.getElementsByClassName('e-treegrid').length > 0) {
        dataGrid.current.resources = resourcesDataSource;
      }
    }, [resourcesDataSource]);
  
    const modelNodesColourSetter = ({ nodeIds, appearanceName, appearanceColour }) => {
      if (nodeIds && appearanceName == 'Hide') {
        viewerImpl.hwv.model.setNodesVisibility(nodeIds, false, null);
      }
      else if (nodeIds && appearanceName == 'None') {
        viewerImpl.hwv.model.setNodesVisibility(nodeIds, true, null);
        viewerImpl.hwv.model.unsetNodesFaceColor(nodeIds);
      }
      else if (nodeIds && appearanceName == 'Model Appearance') {
        viewerImpl.hwv.model.setNodesVisibility(nodeIds, true, null);
        viewerImpl.hwv.model.unsetNodesFaceColor(nodeIds);
      }
      else if (nodeIds && appearanceColour) {
        viewerImpl.hwv.model.setNodesVisibility(nodeIds, true, null);
        const colour = hexToRgb(appearanceColour);
        viewerImpl.hwv.model.setNodesFaceColor(nodeIds, new Communicator.Color(colour.red, colour.green, colour.blue));
      }
    };
  
    useEffect(() => {
      // document.title = `${projectData.description} - ${props.GanttDetails.title} | Gantt`;
      if (aiCounter == 0) {
        setAiCounter(aiCounter + 1);
      }
    }, [props.isAi]);
  
    useEffect(() => {
      if (props.viewType == 'Planned') {
        dataGrid.current.taskFields.startDate = 'StartDate';
        dataGrid.current.taskFields.endDate = 'EndDate';
      }
      if (props.viewType == 'Actual') {
        dataGrid.current.taskFields.duration = null;
        dataGrid.current.taskFields.startDate = 'actualStartDate';
        dataGrid.current.taskFields.endDate = 'actualEndDate';
      }
      if (props.viewType == 'Planned Against Actual') {
        // TO BE IMPLEMENTED LATER
      }
    }, [props.viewType]);
  
    useEffect(() => {
      if (props.activeTab === 'simulation' && TaskData?.length && isGanttRendered) {
        const currentDateTime = sliderTimer?.scheduleTime ? sliderTimer.scheduleTime : 1;
        let allTasksYetToComplete = [];
        let completedTasks = [];
        let runningTasks = [];
        if (props.viewType == 'Planned') {
          allTasksYetToComplete = TaskData.filter((obj) => currentDateTime < new Date(obj.EndDate).getTime());
          completedTasks = TaskData.filter((obj) => currentDateTime >= new Date(obj.EndDate).getTime());
          runningTasks = TaskData.filter((obj) => (currentDateTime >= new Date(obj.StartDate).getTime() && currentDateTime <= new Date(obj.EndDate).getTime()));
        }
        if (props.viewType == 'Actual') {
          allTasksYetToComplete = TaskData.filter((obj) => currentDateTime < new Date(obj.actualEndDate).getTime());
          completedTasks = TaskData.filter((obj) => currentDateTime >= new Date(obj.actualEndDate).getTime());
          runningTasks = TaskData.filter((obj) => (currentDateTime >= new Date(obj.actualStartDate).getTime() && currentDateTime <= new Date(obj.actualEndDate).getTime()));
        }
        if (props.viewType == 'Planned Against Actual') {
          allTasksYetToComplete = TaskData.filter((obj) => currentDateTime < new Date(obj.actualEndDate).getTime());
          completedTasks = TaskData.filter((obj) => currentDateTime >= new Date(obj.actualEndDate).getTime());
          runningTasks = TaskData.filter((obj) => (currentDateTime >= Math.min(new Date(obj.actualStartDate).getTime(), new Date(obj.StartDate).getTime()) && currentDateTime <= Math.max(new Date(obj.actualEndDate).getTime(), new Date(obj.EndDate).getTime())));
        }
        dataGrid.current.dataSource = runningTasks;
  
        const completedElements = [];
        if (completedTasks.length) {
          completedTasks.map((eachTask) => {
            const elementIdList = selectionSetTaskElements[eachTask.TaskIDUUID] ?? [];
            completedElements.push(elementIdList);
            let highestEndDate;
            if (eachTask.taskTypeData?.name) {
              if (props.viewType == 'Planned') {
                highestEndDate = new Date(eachTask.EndDate).getTime();
              }
              if (props.viewType == 'Actual') {
                highestEndDate = new Date(eachTask.actualEndDate).getTime();
              }
              if (props.viewType == 'Planned Against Actual') {
                highestEndDate = new Date(eachTask.actualEndDate).getTime();
              }
              if (currentDateTime >= highestEndDate) {
                let nodeIds = elementIdList?.map((id) => getNodeIdsFromCubeUniqueId(id));
                nodeIds = nodeIds?.flat();
                if (nodeIds?.length) {
                  modelNodesColourSetter({ nodeIds, appearanceName: eachTask.taskTypeData.endAppearanceData.name, appearanceColour: eachTask.taskTypeData.endAppearanceData.colour });
                }
              }
            }
          });
        }
        if (allTasksYetToComplete.length) {
          allTasksYetToComplete.map((eachTask) => {
            const elementIdList = selectionSetTaskElements[eachTask.TaskIDUUID] ?? [];
            const selectedSelectionItem = viewerImpl.hwv.selectionManager.getResults();
  
            let nodeIds = elementIdList?.map((id) => getNodeIdsFromCubeUniqueId(id));
            nodeIds = nodeIds?.flat();
            if (eachTask.taskTypeData?.name && nodeIds?.length) {
              let lowestStartDate;
              let highestEndDate;
              if (props.viewType == 'Planned') {
                lowestStartDate = new Date(eachTask.StartDate).getTime();
                highestEndDate = new Date(eachTask.EndDate).getTime();
              }
              if (props.viewType == 'Actual') {
                lowestStartDate = new Date(eachTask.actualStartDate).getTime();
                highestEndDate = new Date(eachTask.actualEndDate).getTime();
              }
              if (props.viewType == 'Planned Against Actual') {
                lowestStartDate = Math.min(new Date(eachTask.actualStartDate).getTime(), new Date(eachTask.StartDate).getTime());
                highestEndDate = Math.max(new Date(eachTask.actualEndDate).getTime(), new Date(eachTask.EndDate).getTime());
              }
              if (currentDateTime >= lowestStartDate && currentDateTime != 1) {
                if (props.viewType == 'Planned' || props.viewType == 'Actual') {
                  modelNodesColourSetter({ nodeIds, appearanceName: eachTask.taskTypeData.startAppearanceData.name, appearanceColour: eachTask.taskTypeData.startAppearanceData.colour });
                }
                if (props.viewType == 'Planned Against Actual') {
                  const startDate = new Date(eachTask.StartDate).getTime();
                  const endDate = new Date(eachTask.EndDate).getTime();
                  const actualStartDate = new Date(eachTask.actualStartDate).getTime();
                  const actualEndDate = new Date(eachTask.actualEndDate).getTime();
  
                  if (startDate < actualStartDate) {
                    if (currentDateTime < actualStartDate) {
                      modelNodesColourSetter({ nodeIds, appearanceName: eachTask.taskTypeData.startAppearanceData.name, appearanceColour: eachTask.taskTypeData.startAppearanceData.colour });
                    }
                    if (currentDateTime >= actualStartDate) {
                      modelNodesColourSetter({ nodeIds, appearanceName: eachTask.taskTypeData.lateAppearanceData.name, appearanceColour: eachTask.taskTypeData.lateAppearanceData.colour });
                    }
                  }
                  if (actualStartDate < startDate) {
                    if (currentDateTime >= actualStartDate) {
                      modelNodesColourSetter({ nodeIds, appearanceName: eachTask.taskTypeData.earlyAppearanceData.name, appearanceColour: eachTask.taskTypeData.earlyAppearanceData.colour });
                    }
                  }
                  if (actualStartDate == startDate) {
                    if (currentDateTime >= endDate) {
                      modelNodesColourSetter({ nodeIds, appearanceName: eachTask.taskTypeData.lateAppearanceData.name, appearanceColour: eachTask.taskTypeData.lateAppearanceData.colour });
                    }
                    if (currentDateTime < endDate) {
                      modelNodesColourSetter({ nodeIds, appearanceName: eachTask.taskTypeData.startAppearanceData.name, appearanceColour: eachTask.taskTypeData.startAppearanceData.colour });
                    }
                  }
                }
              }
              else if (currentDateTime <= lowestStartDate && currentDateTime != 1) {
                modelNodesColourSetter({ nodeIds, appearanceName: eachTask.taskTypeData.simulationStartAppearanceData.name, appearanceColour: eachTask.taskTypeData.simulationStartAppearanceData.colour });
              }
            }
  
            elementIdList?.forEach((elementId) => {
              if (viewerImpl.hwv.selectionManager.isNodeSelected(getNodeIdsFromCubeUniqueId(elementId)) && !completedElements.includes(elementId)) {
                const selectionItem = selectedSelectionItem.find((item) => item.getNodeId() == getNodeIdsFromCubeUniqueId(elementId));
                if (selectionItem) {
                  viewerImpl.hwv.selectionManager.remove(selectionItem);
                }
              }
            });
          });
        }
      }
      if (props.activeTab === 'gantt' && TaskData?.length) {
        viewerImpl.hwv.model.resetNodesColor();
        viewerImpl.hwv.model.resetNodesVisibility();
      }
    }, [sliderTimer, props.activeTab, TaskData, props.viewType, isGanttRendered]);
  
    useEffect(() => {
      if (props.activeTab === 'simulation') {
        dataGrid.current.toolbar = [];
        // dispatch(getSelectionSetElements({ scheduleId,fileVersionId:url.fileId }));
      }
      else {
        dataGrid.current.toolbar = toolbar;
        dataGrid.current.dataSource = performGanttOperationsService;
        if (props?.viewerImpl) {
          viewerImpl.hwv.selectionManager.clear();
        }
      }
    }, [props.activeTab]);
  
    useEffect(() => () => {
      dispatch(setTaskData([]));
      viewerImpl?.hwv?.model?.resetNodesColor();
      viewerImpl?.hwv?.model?.resetNodesVisibility();
    }, []);
  
    const closeActualStartCal = (args) => {
      if (actualStartDateField.changedArgs.value) {
        actualEndDateField.properties.min = actualStartDateField.changedArgs.value;
      }
    };
    const closeActualEndCal = (args) => {
      if (actualEndDateField.changedArgs.value) {
        actualStartDateField.properties.max = actualEndDateField.changedArgs.value;
      }
    };
    const actualEndDateClear = (args) => {
      if (actualStartDateField?.properties?.max) {
        actualStartDateField.properties.max = null;
      }
    };
    const actualStartDateClear = (args) => {
      if (actualEndDateField?.properties?.min) {
        actualEndDateField.properties.min = null;
      }
    };
  
    const actionBegin = (args) => {
      if (args.requestType == 'beforeDrop' && (isNaN(args.dropIndex) || args.dropPosition == 'Invalid')) {
        args.cancel = true;
        return;
      }
      if (args.requestType == 'beforeDrop' && (args.dropPosition == 'bottomSegment' || args.dropPosition == 'topSegment')) {
        args.data[0].taskData.parentId = args.dropRecord.taskData.parentId;
      }
      if (args.requestType == 'beforeDrop' && args.dropPosition == 'middleSegment') {
        args.data[0].taskData.parentId = args.dropRecord.taskData.TaskIDUUID;
      }
      if (args.requestType == 'beforeDelete') {
        args.data[0].taskData.TaskID = args.data[0].taskData.TaskIDUUID;
      }
      if (args.requestType === 'beforeOpenAddDialog' || args.requestType == 'beforeOpenEditDialog') {
        if (args.requestType === 'beforeOpenAddDialog') {
          args.rowData.ganttProperties.startDate = new Date(Date.now());
          args.rowData.ganttProperties.endDate = new Date(Date.now());
          args.rowData.StartDate = new Date(Date.now());
          args.rowData.EndDate = new Date(Date.now());
        }
        args.Resources.columns[1].visible = false;
        args.Resources.columns[3].allowEditing = false;
        args.Resources.columns[3].field = 'totalUnit';
        args.dialogModel.allowDragging = false;
        const column = dataGrid.current.columnByField.taskTypeId;
        const startDateColumn = dataGrid.current.columnByField.actualStartDate;
        const endDateColumn = dataGrid.current.columnByField.actualEndDate;
  
        taskTypeDiv = dataGrid.current.createElement('div', {
          className: `${css.cutomFieldClass}`,
          id: 'taskTypeDiv',
        });
        actualStartDateDiv = dataGrid.current.createElement('div', {
          className: `${css.cutomFieldClassForAS}`,
          id: 'actualStartDateDiv',
        });
        actualEndDateDiv = dataGrid.current.createElement('div', {
          className: `${css.cutomFieldClass}`,
          id: 'actualEndDateDiv',
        });
  
        const taskTypeDropDown = new DropDownList({
          value: args.rowData.taskTypeId,
          dataSource: taskTypeService,
          fields: { value: '_id', text: 'name' },
          placeholder: 'Select Task Type',
          query: taskTypeQuery,
        });
  
        actualStartDateField = new DateTimePicker({
          close: closeActualStartCal,
          cleared: actualStartDateClear,
          value: args.rowData.actualStartDate ? args.rowData.actualStartDate : null,
          placeholder: 'Select Actual Start Date',
          format: 'MMM dd yyyy hh:mm a',
          max: args.rowData.actualEndDate ? new Date(args.rowData.actualEndDate) : null,
          max: args.rowData.actualEndDate ? new Date(args.rowData.actualEndDate) : null,
        });
  
        actualEndDateField = new DateTimePicker({
          close: closeActualEndCal,
          cleared: actualEndDateClear,
          value: args.rowData.actualEndDate ? args.rowData.actualEndDate : null,
          placeholder: 'Select Actual End date',
          format: 'MMM dd yyyy hh:mm a',
          min: args.rowData.actualStartDate ? new Date(args.rowData.actualStartDate) : null,
          min: args.rowData.actualStartDate ? new Date(args.rowData.actualStartDate) : null,
        });
  
        const inputElement = dataGrid.current.createElement('input', {
          attrs: {
            type: 'text',
            id: `${dataGrid.current.controlId}${column.field}`,
            name: 'input',
            title: 'title',
          },
        });
  
        const actualStartDateElement = dataGrid.current.createElement('input', {
          attrs: {
            type: 'text',
            id: `${dataGrid.current.controlId}${startDateColumn.field}`,
            name: 'input',
            title: 'title',
          },
        });
  
        const actualEndDateElement = dataGrid.current.createElement('input', {
          attrs: {
            type: 'text',
            id: `${dataGrid.current.controlId}${endDateColumn.field}`,
            name: 'input',
            title: 'title',
          },
        });
  
        taskTypeDiv.innerHTML = 'Task Type';
        actualStartDateDiv.innerHTML = 'Actual Start Date';
        actualEndDateDiv.innerHTML = 'Actual End Date';
  
        taskTypeDiv.appendChild(inputElement);
        actualStartDateDiv.appendChild(actualStartDateElement);
        actualEndDateDiv.appendChild(actualEndDateElement);
  
        taskTypeDropDown.appendTo(inputElement);
        actualStartDateField.appendTo(actualStartDateElement);
        actualEndDateField.appendTo(actualEndDateElement);
      }
      if (args.requestType == 'beforeSave' || args.requestType == 'beforeAdd') {
        const resourceId = [];
        const resourceName = [];
        args.data.taskData.resources?.map((resource) => {
          if (resource) {
            resourceId.push(resource._id);
            resourceName.push(resource.name);
          }
        });
        args.data.taskData.resources = resourceName;
        args.data.taskData.resourceIds = resourceId;
      }
    };
  
    const actionComplete = async (args) => {
      if (args.requestType === 'openAddDialog' || args.requestType === 'openEditDialog') {
        const generalTab = document.getElementById(`${dataGrid.current.controlId}GeneralTabContainer`);
        if (args.requestType === 'openAddDialog') {
          generalTab.appendChild(actualStartDateDiv);
          generalTab.appendChild(actualEndDateDiv);
          generalTab.appendChild(taskTypeDiv);
        }
        if (args.requestType === 'openEditDialog') {
          generalTab.appendChild(actualStartDateDiv);
          generalTab.appendChild(actualEndDateDiv);
        }
        const tabObj = document.getElementById('Editing_Tab');
        tabObj.selected = function (args) {
          const id = args.selectedContent.childNodes[0].id;
          if (args.selectedIndex == 2) {
            const gridObj = document.getElementById('EditingResourcesTabContainer_gridcontrol').ej2_instances[0];
            gridObj.hideColumns('ID');
          }
        };
      }
      if (args.requestType == 'add' || args.requestType == 'delete' || args.requestType == 'save') {
        dispatch(getScheduleDetails({ ganttId: scheduleId }));
        if (url.fileId) {
          dispatch(getSelectionSetElements({ scheduleId, fileVersionId: url.fileId }));
        }
        // if (args.requestType != 'add') {
        dataGrid.current.refresh();
        // }
      }
    };
  
    const showTaskItems = async (args, taskData) => {
      const itemData = await getBoqItems({ taskId: [taskData.TaskIDUUID], source: 'CONTRACT', contractId: url.contractId });
      const itemQuantityMapper = {};
      taskData.linkedBoqItems.map((item) => {
        itemQuantityMapper[item.itemId] = item.quantityLinkedManualy;
      });
      const tempArray = itemData.data.data?.map((item) => ({
        ...item,
        amount: item.rate * itemQuantityMapper[item.itemId] ?? 0,
      }));
      setAttachedItems(tempArray);
    };
  
    const formatTaskID = (data) => {
      let taskId;
  
      if (data?.taskData?.TaskDisp) {
        taskId = `${data?.taskData?.TaskDisp}`;
      }
      else {
        const counter = data?.taskData?.TaskID ?? '0';
        taskId = `TSK-${String(counter).padStart(4, '0')}`;
      }
  
      const itemsLinked = data.taskData?.linkedBoqItems;
  
      return (
        <div className="flex justify-between items-center">
          <span>{taskId}</span>
          {Array.isArray(itemsLinked) && itemsLinked.length > 0 && <IconComponent cssClass="cursor-pointer" name="details" onClick={(args) => showTaskItems(args, data.taskData)} />}
        </div>
      );
    };
  
    const handleTaskTypeChange = async (e, args) => {
      const data = {
        taskTypeId: e.target.value,
        taskId: args.taskData.TaskIDUUID,
        scheduleId,
        contractId: url.contractId,
      };
      const res = await updateTaskTypeOfScheduleTask(data);
      if (res.data.status) {
        dispatch(showToastNotification({
          content: 'Task Type updated Successfully',
          type: TOAST_TYPE_SUCCESS,
        }));
      }
      else {
        dispatch(showToastNotification({
          content: 'Error',
          type: TOAST_TYPE_ERROR,
        }));
      }
    };
  
    const taskTypeTemplate = (args) => (
      <DropDownListComponent
        dataSource={taskTypeService}
        fields={{ value: '_id', text: 'name' }}
        value={args.taskTypeId}
        onChange={(event) => handleTaskTypeChange(event, args)}
        query={taskTypeQuery}
        showClearButton
      />
    );
  
    // This is used for AI. Donot remove for the time being. TODO: Need to discuss with dev
    const sortingOptions = { columns: [{ field: 'TaskID', direction: 'Ascending' }] };
  
    const dataBound = (args) => {
      // Patch for AI
      setIsGanttRendered(true);
      if (props.isAi && aiCounter > 0 && args.isGanttCreated == true) {
        // dataGrid.current.sortColumn('TaskID', 'Ascending');
        dataGrid.current.fitToProject();
        const length = document.getElementsByClassName('e-row').length;
  
        for (let i = 0; i < length; i++) {
          document.getElementsByClassName('e-row')[i].style.visibility = 'hidden';
          document.getElementsByClassName('e-row')[i].style.opacity = 0;
  
          document.getElementsByClassName('e-chart-row')[i].style.visibility = 'hidden';
          document.getElementsByClassName('e-chart-row')[i].style.opacity = 0;
        }
  
        for (let i = 0; i < length; i++) {
          setTimeout(() => {
            document.getElementsByClassName('e-row')[i].style.visibility = 'visible';
            document.getElementsByClassName('e-row')[i].style.opacity = 1;
            document.getElementsByClassName('e-row')[i].style.transition = 'visibility 0.5s, opacity 0.5s linear';
  
            document.getElementsByClassName('e-chart-row')[i].style.visibility = 'visible';
            document.getElementsByClassName('e-chart-row')[i].style.opacity = 1;
            document.getElementsByClassName('e-chart-row')[i].style.transition = 'visibility 0.5s, opacity 0.5s linear';
          }, 500 * i);
        }
      }
    };
  
    const rowSelected = (args) => {
      if (!dataGrid || !dataGrid.current) return;
      if (args.name == 'rowSelected') {
        if (!contractDetails.linkedSchedule?.isLocked) {
          dataGrid.current.toolbarModule.enableItems(['un-link-from-contract', 'link_boq_items'], true);
        }
        // if (contractDetails.linkedSchedule?.isLocked) {
        //   dataGrid.current.toolbarModule.enableItems(['create_inspection', 'create_progressUpdates'], true);
        // }
      }
      if (args.name == 'rowDeselected') {
        dataGrid.current.toolbarModule.enableItems(['link_boq_items', 'un-link-from-contract'], false);
      }
    };
  
    const taskList = useCallback(
      () => (
        <GanttComponent
          id="Editing"
          allowSorting
          ref={dataGrid}
          allowRowDragAndDrop
          allowResizing
          dataSource={performGanttOperationsService}
          dateFormat="MMM dd y, hh:mm a"
          treeColumnIndex={1}
          allowSelection
          allowFiltering
          filterSettings={FilterOption}
          showColumnMenu={false}
          highlightWeekends
          allowUnscheduledTasks
          dayWorkingTime={[{ from: 0, to: 24 }]}
          taskFields={taskFields}
          timelineSettings={timelineSettings}
          labelSettings={labelSettings}
          splitterSettings={splitterSettings}
          height="100%"
          width="100%"
          editSettings={editSettings}
          gridLines={gridLines}
          selectionSettings={{ enableToggle: true }}
          includeWeekend
          toolbar={toolbar}
          toolbarClick={toolbarClickHandler}
          resourceFields={resourceFields}
          resources={resourcesDataSource}
          actionComplete={actionComplete}
          actionBegin={actionBegin}
          created={created}
          dataBound={dataBound}
          query={ganttQuery}
          rowSelected={rowSelected}
          rowDeselected={rowSelected}
          // sortSettings={sortingOptions}
          enableVirtualization
          // loadChildOnDemand={false}
        >
          <ColumnsDirective>
            <ColumnDirective field="TaskID" width="110" isPrimaryKey filter={FilterOption} template={formatTaskID} allowEditing={false} />
            <ColumnDirective field="TaskName" headerText="Title" width="200" clipMode="EllipsisWithTooltip" />
            <ColumnDirective field="StartDate" type="date" filter={FilterOption} />
            <ColumnDirective field="EndDate" type="date" filter={FilterOption} />
            <ColumnDirective field="Duration" filter={FilterOption} />
            <ColumnDirective field="actualStartDate" editType="datetimepickeredit" headerText="Actual Start Date" />
            <ColumnDirective field="actualEndDate" editType="datetimepickeredit" headerText="Actual End Date" />
            <ColumnDirective field="taskTypeId" template={taskTypeTemplate} allowEditing={false} headerText="Task Type" />
            <ColumnDirective field="Progress" filter={FilterOption} />
          </ColumnsDirective>
          <AddDialogFieldsDirective>
            <AddDialogFieldDirective type="General" headerText="General" />
            <AddDialogFieldDirective type="Dependency" />
            <AddDialogFieldDirective type="Resources" />
            {/* <AddDialogFieldDirective type="Notes" /> */}
          </AddDialogFieldsDirective>
          <EditDialogFieldsDirective>
            <EditDialogFieldDirective type="General" headerText="General" />
            <EditDialogFieldDirective type="Dependency" />
            <EditDialogFieldDirective type="Resources" />
            {/* <EditDialogFieldDirective type="Notes" /> */}
          </EditDialogFieldsDirective>
          <Inject services={[Edit, RowDD, Selection, Toolbar, DayMarkers, Filter, Sort, Resize, VirtualScroll, CriticalPath]} />
        </GanttComponent>
      ),
      [props.isAi],
    );
  
    const getInspectionFormFLow = () => (
      <InspectionCreation
        selectedTask={dataGrid.current.selectionModule.getSelectedRecords()[0].taskData}
        GanttDetails={props.GanttDetails}
        projectId={projectId}
        scheduleId={scheduleId}
        contractId={url.contractId}
        spaceId={spaceId}
        showFormFlowCreationModal={showFormFlowCreationModal}
        setShowFormFlowCreationModal={setShowFormFlowCreationModal}
        source="contract"
      />
    );
  
    const successCallback = () => {
      dataGrid.current.refresh();
    };
  
    const linkBoqItemsModal = () => (
      <LinkBoqToTaskAndForm
        selectedTask={dataGrid.current.selectionModule.getSelectedRecords()[0].taskData}
        showBoqModal={showBoqModal}
        setShowBoqModal={setShowBoqModal}
        source="gantt"
        successCallback={successCallback}
      />
    );
    const handleUnLinkTaskClick = async () => {
      const data = {
        action: 'un-link',
        entity: 'task',
        contractId: url.contractId,
        data: [
          dataGrid.current.selectionModule.getSelectedRecords()[0]?.taskData?.TaskIDUUID,
        ],
      };
      const res = await linkEntitiesToContract(data);
      if (res.data.status) {
        dispatch(
          showToastNotification({
            content: 'Task Un-liniked successfully',
            type: TOAST_TYPE_SUCCESS,
          }),
        );
        hideWarningModal();
        dataGrid.current.refresh();
      }
    };
    const warningModal = () => {
      const source = showWarning.source;
      let btnText; let contentTxt; let headerText; let
        callBackFun;
      switch (source) {
        case 'unLinkTask':
          btnText = 'Un-Link';
          contentTxt = 'Un-linking this tasks will also remove all its childs from this and all child contracts. Are you sure you want to continue.?';
          headerText = 'Un-Link ?';
          callBackFun = handleUnLinkTaskClick;
          break;
      }
      return (
        <ModalStateDialogComponent
          footerContent={(
            <div><ButtonComponent onClick={callBackFun} buttonType={BUTTON_TYPES.GRADIENT_BUTTON}>{btnText}</ButtonComponent></div>
          )}
          width="30%"
          headerContent={(
            <div className="flex w-full justify-between items-center">
              {headerText}
              <IconComponent onClick={hideWarningModal} cssClass="cursor-pointer" name="close" />
            </div>
          )}
          onCancel={hideWarningModal}
          isVisible={showWarning.status}
          modelContent={(
            <div className="mt-6 mb-6">
              {contentTxt}
              {' '}
            </div>
          )}
        />
      );
    };
    const handleUnLinkItemClick = async () => {
      if (attachedItemRef.current.getSelectedRecords().length > 0) {
        const selectedItems = attachedItemRef.current.getSelectedRecords();
        const itemIds = selectedItems.map((item) => item.itemId);
        const data = {
          contractHasTaskId: dataGrid.current.selectionModule.getSelectedRecords()[0]?.taskData?.TaskIDUUID,
          originalTaskId: dataGrid.current.selectionModule.getSelectedRecords()[0]?.taskData?.originalTaskId,
          boqItems: itemIds,
          scheduleId,
          parentContractId: contractDetails.parentId,
          contractId: url.contractId,
          action: 'un-link',
          entity: 'task',
        };
        const res = await linkBoqItems(data);
        if (res.data.status) {
          dispatch(
            showToastNotification({
              content: 'Item removed successfully',
            }),
          );
          setAttachedItems(null);
          dataGrid.current.refresh();
        }
        else {
          showErrorToast(res.data.message);
        }
      }
      else {
        showErrorToast('first select items to un-link');
      }
    };
    const handleQuantityChange = async (event, args) => {
      const value = Number(event.target.value.replace(/,/g, ''));
      const data = {
        customQuantity: value,
        taskId: dataGrid.current.selectionModule.getSelectedRecords()[0]?.taskData?.TaskIDUUID,
        itemId: args.itemId,
      };
      setTaskItemQuantity((prev) => ({
          ...prev,
          [args.itemId]: {
            customQuantity: value,
            taskId: dataGrid.current.selectionModule.getSelectedRecords()[0]?.taskData?.TaskIDUUID,
            itemId: args.itemId,
          },
        }));
    };
  
    const handleSaveItemClick = async () => {
      const data = [];
      Object.keys(taskItemQuantity).map((itemId) => {
        data.push(taskItemQuantity[itemId]);
      });
      const res = await getContractItemDetails({
        contractId: url.contractId,
        entity: 'tasks',
        action: 'modify',
        data,
      });
      if (res.data.status) {
        dispatch(
          showToastNotification({
            content: 'Quantity modified successfully',
            type: TOAST_TYPE_SUCCESS,
          }),
        );
      }
    };
  
    const linkedQuantityTemplate = (args) => {
      const max = (args.quantityLinkedManualy + args.availableQuantity);
      const min = 0;
      return (
        <div onClick={(e) => e.stopPropagation()} className="flex justify-around items-center">
          {contractDetails.linkedSchedule?.isLocked ? (args.quantityLinkedManualy) : (
            <NumericTextBoxComponent placeholder="quantity" value={args.quantityLinkedManualy} min={min} max={max} onBlur={(event) => handleQuantityChange(event, args)} />
          )}
        </div>
      );
    };
  
    const getTaskItemsGrid = useCallback(() => (
      <div className="m-6 h-96 flex overflow-auto max-h-96">
        <GridComponent
          ref={attachedItemRef}
          dataSource={attachedItems}
          toolbarClick={toolbarClickHandler}
          rowHeight={60}
          height="100%"
          allowResizing={false}
          cssClass="overflow-auto"
        >
          <ColumnsDirective>
            <ColumnDirective
              type="checkbox"
              width="50"
            />
            <ColumnDirective
              headerText="S.No"
              textAlign="center"
              field="serial"
              width="100"
            />
            <ColumnDirective
              headerText="Code"
              textAlign="center"
              field="code"
              width="100"
            />
            <ColumnDirective
              headerText="Description"
              textAlign="center"
              field="description"
              width="150"
            />
            <ColumnDirective
              headerText="Total Quantity"
              textAlign="center"
              field="originalQuantity"
              width="150"
            />
            <ColumnDirective
              headerText="Linked Quantity"
              textAlign="center"
              field="quantityLinkedManualy"
              width="150"
              template={linkedQuantityTemplate}
            />
            <ColumnDirective
              headerText="Unit"
              textAlign="center"
              field="purchaseUnit.name"
              width="120"
            />
            <ColumnDirective
              headerText="Rate"
              textAlign="center"
              field="rate"
              width="100"
            />
            <ColumnDirective
              headerText="Amount"
              textAlign="center"
              field="amount"
              width="100"
            />
  
          </ColumnsDirective>
        </GridComponent>
      </div>
    ), [attachedItems]);
  
    return (
      <div className={css.controlPane} style={{ position: 'relative' }}>
        <div className={css.controlSection} style={{ position: 'relative' }}>
          {showTaskModal && <ExistingTasks refreshGrid={refreshGrid} setTaskModal={setTaskModal} spaceId={spaceId} scheduleId={scheduleId} projectId={projectId} />}
          {taskList()}
  
          {Array.isArray(attachedItems) && (
            <ModalStateDialogComponent
              allowModalPadding={false}
              footerContent={!contractDetails.linkedSchedule?.isLocked && (
                <div className="m-6 w-full flex justify-between">
                  <div className="flex gap-2">
                    <ButtonComponent buttonType={BUTTON_TYPES.BACKGROUND_BUTTON} onClick={handleSaveItemClick}>
                      Save
                    </ButtonComponent>
                    <ButtonComponent buttonType={BUTTON_TYPES.BACKGROUND_BUTTON} onClick={() => setAttachedItems(null)}>
                      Cancel
                    </ButtonComponent>
                  </div>
                  <div>
                    <ButtonComponent buttonType={BUTTON_TYPES.BACKGROUND_BUTTON} onClick={handleUnLinkItemClick}>
                      Un-Link
                    </ButtonComponent>
                  </div>
                </div>
              )}
              width="80%"
              headerContent={(
                <div className="bg-button_light  w-full flex justify-between rounded-md">
                  <div className="flex m-6 flex-col gap-1">
                    <div>Linked Items</div>
                  </div>
                  <div className="flex pr-7 cursor-pointer">
                    <IconComponent name="close" onClick={() => setAttachedItems(null)} />
                  </div>
                </div>
              )}
              onCancel={() => setAttachedItems(null)}
              isVisible
              modelContent={getTaskItemsGrid()}
            />
          )}
          {showWarning.status && (
            warningModal()
          )}
        </div>
        {showFormFlowCreationModal.status && getInspectionFormFLow()}
        {showBoqModal && linkBoqItemsModal()}
        {
          showImportModal && <ExcelImport showImportModal={showImportModal} setShowImportModal={setShowImportModal} type="Schedule" refreshDataGrid={successCallback} />
        }
      </div>
    );
  });
  
  export default GanttChart;
  