import Container from '@/components/shared/Container'
import { APP_NAME, DX_CLASSNAMES } from '@/constants/app.constant'
import { GridDto, SubFormTabTypeEnum } from '@/proxy/form/models'
import { useLocalization } from '@/utils/hooks/useLocalization'
import Gantt, {
  Column,
  ContextMenu,
  Editing,
  FilterRow,
  GanttRef,
  HeaderFilter,
  Item,
  Sorting,
  Tasks,
  Toolbar,
  Validation,
} from 'devextreme-react/gantt'
import { useCallback, useEffect, useRef, useState } from 'react'
import { Helmet } from 'react-helmet'
import { getList } from '@/services/form.service'
import { useListFormCustomDataSource } from './useListFormCustomDataSource'
import { addCss, addJs } from './Utils'
import { layoutTypes } from '../admin/listForm/edit/types'
import WidgetGroup from '@/components/ui/Widget/WidgetGroup'
import { ROUTES_ENUM } from '@/routes/route.constant'
import { usePWA } from '@/utils/hooks/usePWA'
import { GanttScaleType } from 'devextreme/ui/gantt'
import { useListFormColumns } from './useListFormColumns'
import CustomStore from 'devextreme/data/custom_store'
import { GridColumnData } from './GridColumnData'
import { Loading } from '@/components/shared'
import { usePermission } from '@/utils/hooks/usePermission'
import SubForms from '../form/SubForms'

interface GanttViewProps {
  listFormCode: string
  searchParams?: URLSearchParams
  isSubForm?: boolean
  level?: number
  refreshData?: () => Promise<void>
  gridDto?: GridDto
}

const GanttView = (props: GanttViewProps) => {
  const { listFormCode, searchParams, isSubForm, level, gridDto: extGridDto } = props
  const { translate } = useLocalization()
  const isPwaMode = usePWA()

  const gridRef = useRef<GanttRef>()
  const refListFormCode = useRef('')
  const widgetGroupRef = useRef<HTMLDivElement>(null)
  const { checkPermission } = usePermission()

  const [ganttDataSource, setGanttDataSource] = useState<CustomStore<any, any>>()
  const [columnData, setColumnData] = useState<GridColumnData[]>()
  const [gridDto, setGridDto] = useState<GridDto>()
  const [widgetGroupHeight, setWidgetGroupHeight] = useState(0)
  const [scaleType, setScaleType] = useState<GanttScaleType>('weeks')
  const layout = layoutTypes.gantt || 'gantt'

  useEffect(() => {
    const initializeGantt = async () => {
      const response = await getList({ listFormCode })
      setGridDto(response.data)
    }

    if (extGridDto === undefined) {
      initializeGantt()
    } else {
      setGridDto(extGridDto)
    }

    setScaleType(extGridDto?.gridOptions.ganttOptionDto?.scaleType || 'weeks')
  }, [listFormCode, extGridDto])

  useEffect(() => {
    if (gridRef?.current) {
      const instance = gridRef?.current?.instance()
      if (instance) {
        instance.option('dataSource', undefined)
      }
    }

    if (refListFormCode.current !== listFormCode) {
      // Reset state if needed
    }
  }, [listFormCode])

  const { createSelectDataSource } = useListFormCustomDataSource({ gridRef })
  const { getBandedColumns } = useListFormColumns({
    gridDto,
    listFormCode,
    isSubForm,
    gridRef,
  })

  useEffect(() => {
    if (!gridDto) {
      return
    }

    // Set js and css
    const grdOpt = gridDto.gridOptions
    if (grdOpt.customJsSources.length) {
      for (const js of grdOpt.customJsSources) {
        addJs(js)
      }
    }
    if (grdOpt.customStyleSources.length) {
      for (const css of grdOpt.customStyleSources) {
        addCss(css)
      }
    }
  }, [gridDto])

  useEffect(() => {
    if (!gridDto) return

    const cols = getBandedColumns()
    setColumnData(cols)

    const dataSource = createSelectDataSource(
      gridDto.gridOptions,
      listFormCode,
      searchParams,
      layout,
      undefined,
    )

    setGanttDataSource(dataSource)
  }, [gridDto, searchParams, createSelectDataSource])

  useEffect(() => {
    refListFormCode.current = listFormCode
  }, [listFormCode])

  // WidgetGroup yüksekliğini hesapla
  useEffect(() => {
    const calculateWidgetHeight = () => {
      if (widgetGroupRef.current) {
        const height = widgetGroupRef.current.offsetHeight
        setWidgetGroupHeight(height)
      }
    }

    calculateWidgetHeight()

    const resizeObserver = new ResizeObserver(calculateWidgetHeight)
    if (widgetGroupRef.current) {
      resizeObserver.observe(widgetGroupRef.current)
    }

    return () => {
      resizeObserver.disconnect()
    }
  }, [gridDto?.widgets])

  const settingButtonClick = useCallback(() => {
    window.open(
      ROUTES_ENUM.protected.saas.listFormManagement.edit.replace(':listFormCode', listFormCode),
      isPwaMode ? '_self' : '_blank',
    )
  }, [])

  const getSettingButtonOptions = useCallback(
    () => ({
      icon: 'preferences',
      stylingMode: 'icon',
      onClick: () => {
        settingButtonClick()
      },
    }),
    [settingButtonClick],
  )

  const getRefreshButtonOptions = useCallback(
    () => ({
      icon: 'refresh',
      text: translate('::ListForms.ListForm.Refresh'),
      stylingMode: 'icon',
      onClick: () => {
        gridRef.current?.instance()?.refresh()
      },
    }),
    [settingButtonClick],
  )

  return (
    <>
      <div ref={widgetGroupRef}>
        <WidgetGroup widgetGroups={gridDto?.widgets ?? []} />
      </div>

      <Container className={DX_CLASSNAMES}>
        {!isSubForm && (
          <Helmet
            titleTemplate={`%s | ${APP_NAME}`}
            title={translate('::' + gridDto?.gridOptions.title)}
            defaultTitle={APP_NAME}
          >
            <link rel="stylesheet" href="/css/gantt/dx-gantt.min.css" />
          </Helmet>
        )}
        {!gridDto && (
          <div className="p-4">
            <Loading loading>Loading gantt configuration...</Loading>
          </div>
        )}
        {gridDto && !ganttDataSource && (
          <div className="p-4">
            <Loading loading>Loading data source...</Loading>
          </div>
        )}
        {gridDto && columnData && ganttDataSource && (
          <>
            <div className="p-1">
              <Gantt
                ref={gridRef as any}
                key={`Gantt-${listFormCode}-${ganttDataSource ? 'loaded' : 'loading'}`}
                id={'Gantt-' + listFormCode}
                taskListWidth={500}
                scaleType={scaleType}
                rootValue={
                  gridDto.gridOptions.ganttOptionDto?.rootValue === '' ||
                  gridDto.gridOptions.ganttOptionDto?.rootValue === undefined
                    ? null
                    : gridDto.gridOptions.ganttOptionDto?.rootValue
                }
                height={
                  gridDto.gridOptions.height > 0
                    ? gridDto.gridOptions.height
                    : gridDto.gridOptions.fullHeight
                      ? `calc(100vh - ${170 + widgetGroupHeight}px)`
                      : undefined
                }
              >
                <Tasks
                  dataSource={ganttDataSource}
                  keyExpr={gridDto.gridOptions.ganttOptionDto?.keyExpr}
                  parentIdExpr={gridDto.gridOptions.ganttOptionDto?.parentIdExpr}
                  titleExpr={gridDto.gridOptions.ganttOptionDto?.titleExpr}
                  startExpr={gridDto.gridOptions.ganttOptionDto?.startExpr}
                  endExpr={gridDto.gridOptions.ganttOptionDto?.endExpr}
                  progressExpr={gridDto.gridOptions.ganttOptionDto?.progressExpr}
                />

                <Toolbar>
                  <Item name="undo" locateInMenu="auto" />
                  <Item name="redo" locateInMenu="auto" />
                  <Item name="separator" locateInMenu="auto" />
                  <Item name="collapseAll" locateInMenu="auto" />
                  <Item name="expandAll" locateInMenu="auto" />
                  {gridDto.gridOptions.ganttOptionDto?.allowTaskAdding && (
                    <Item name="addTask" locateInMenu="auto" />
                  )}
                  {gridDto.gridOptions.ganttOptionDto?.allowTaskDeleting && (
                    <Item name="deleteTask" locateInMenu="auto" />
                  )}
                  <Item name="separator" locateInMenu="auto" />
                  <Item name="zoomIn" locateInMenu="auto" />
                  <Item name="zoomOut" locateInMenu="auto" />
                  <Item name="separator" locateInMenu="auto" />
                  <Item
                    location="after"
                    widget="dxSelectBox"
                    locateInMenu="auto"
                    options={{
                      width: 150,
                      items: [
                        { value: 'auto', text: translate('::Auto') },
                        { value: 'minutes', text: translate('::Minutes') },
                        { value: 'hours', text: translate('::Hours') },
                        { value: 'days', text: translate('::Days') },
                        { value: 'weeks', text: translate('::Weeks') },
                        { value: 'months', text: translate('::Months') },
                        { value: 'quarters', text: translate('::Quarters') },
                        { value: 'years', text: translate('::Years') },
                      ],
                      displayExpr: 'text',
                      valueExpr: 'value',
                      value: scaleType,
                      onValueChanged: (e: any) => setScaleType(e.value),
                    }}
                  />
                  <Item
                    location="after"
                    widget="dxButton"
                    locateInMenu="auto"
                    showText="always"
                    options={getRefreshButtonOptions()}
                  />
                  {checkPermission(gridDto?.gridOptions.permissionDto.u) && (
                    <Item
                      location="after"
                      widget="dxButton"
                      locateInMenu="auto"
                      showText="always"
                      options={getSettingButtonOptions()}
                    />
                  )}
                </Toolbar>
                
                <Editing
                  enabled={gridDto.gridOptions.ganttOptionDto?.allowEditing}
                  allowTaskAdding={gridDto.gridOptions.ganttOptionDto?.allowTaskAdding}
                  allowTaskUpdating={gridDto.gridOptions.ganttOptionDto?.allowTaskUpdating}
                  allowTaskDeleting={gridDto.gridOptions.ganttOptionDto?.allowTaskDeleting}
                  allowDependencyAdding={gridDto.gridOptions.ganttOptionDto?.allowDependencyAdding}
                  allowDependencyDeleting={
                    gridDto.gridOptions.ganttOptionDto?.allowDependencyDeleting
                  }
                  allowResourceAdding={gridDto.gridOptions.ganttOptionDto?.allowResourceAdding}
                  allowResourceDeleting={gridDto.gridOptions.ganttOptionDto?.allowResourceDeleting}
                />

                <FilterRow visible={gridDto.gridOptions.filterRowDto?.visible}></FilterRow>
                <HeaderFilter visible={gridDto.gridOptions.headerFilterDto.visible}></HeaderFilter>
                <Sorting mode={gridDto.gridOptions?.sortMode}></Sorting>
                <Validation autoUpdateParentTasks={true} />
                <ContextMenu enabled={false} />

                {columnData
                  .filter((col) => col.type != 'buttons')
                  .map((col: any) => (
                    <Column key={col.dataField} {...col} />
                  ))}
              </Gantt>
            </div>
          </>
        )}
      </Container>
    </>
  )
}

export default GanttView
