import Container from '@/components/shared/Container'
import { Dialog, Notification, toast } from '@/components/ui'
import { APP_NAME, DX_CLASSNAMES } from '@/constants/app.constant'
import { executeEditorScript } from '@/utils/editorScriptRuntime'
import {
  DbTypeEnum,
  EditingFormItemDto,
  GridDto,
  ListFormCustomizationTypeEnum,
  PlatformEditorTypes,
  SubFormTabTypeEnum,
} from '@/proxy/form/models'
import {
  getListFormCustomization,
  postListFormCustomization,
} from '@/services/list-form-customization.service'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { captionize } from 'devextreme/core/utils/inflector'
import { Template } from 'devextreme-react/core/template'
import TreeListDx, {
  ColumnChooser,
  ColumnFixing,
  Editing,
  FilterPanel,
  FilterRow,
  HeaderFilter,
  LoadPanel,
  Pager,
  Paging,
  RemoteOperations,
  Scrolling,
  SearchPanel,
  Selection,
  Sorting,
  Toolbar,
  TreeListRef,
  TreeListTypes,
} from 'devextreme-react/tree-list'
import { Item } from 'devextreme-react/toolbar'
import CustomStore from 'devextreme/data/custom_store'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { Helmet } from 'react-helmet'
import { RowMode, SimpleItemWithColData } from '../form/types'
import { GridColumnData } from './GridColumnData'
import GridFilterDialogs from './GridFilterDialogs'
import {
  addCss,
  addJs,
  autoNumber,
  controlStyleCondition,
  GridExtraFilterState,
  setFormEditingExtraItemValues,
  setGridPanelColor,
} from './Utils'
import { GridBoxEditorComponent } from './editors/GridBoxEditorComponent'
import { TagBoxEditorComponent } from './editors/TagBoxEditorComponent'
import { useFilters } from './useFilters'
import { updateWorkflowApprovalToolbarItems, useToolbar } from './useToolbar'
import WidgetGroup from '@/components/ui/Widget/WidgetGroup'
import { GridExtraFilterToolbar } from './GridExtraFilterToolbar'
import { getList } from '@/services/form.service'
import { layoutTypes } from '../admin/listForm/edit/types'
import { useListFormCustomDataSource } from './useListFormCustomDataSource'
import { useListFormColumns } from './useListFormColumns'
import { DataType } from 'devextreme/common'
import { useStoreState } from '@/store/store'
import SubForms from '../form/SubForms'
import { ImportDashboard } from '@/components/importManager/ImportDashboard'
import { workflowService } from '@/services/workflow.service'
import { NotePanel } from '../form/notes/NotePanel'

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

const statedGridPanelColor = 'rgba(50, 200, 200, 0.5)'

const isTemporaryDxKey = (key: unknown) => typeof key === 'string' && key.startsWith('_DX_KEY_')

const getPersistedInsertedKey = (e: any, keyFieldName?: string) => {
  const dataKey = keyFieldName ? e.data?.[keyFieldName] : undefined
  if (dataKey !== undefined && dataKey !== null && !isTemporaryDxKey(dataKey)) {
    return dataKey
  }

  if (e.key !== undefined && e.key !== null && !isTemporaryDxKey(e.key)) {
    return e.key
  }

  return undefined
}

const updateReadOnlyInFormItems = (items: any[] = [], field: string, readOnly: boolean) => {
  let changed = false
  const expected = String(field || '').toLowerCase()

  const nextItems = items.map((item) => {
    const key = item?.dataField || item?.name
    let nextItem = item

    if (key && String(key).toLowerCase() === expected) {
      const editorOptions = nextItem.editorOptions || {}
      if (editorOptions.readOnly !== readOnly) {
        changed = true
        nextItem = {
          ...nextItem,
          editorOptions: {
            ...editorOptions,
            readOnly,
          },
        }
      }
    }

    if (nextItem?.items?.length) {
      const childResult = updateReadOnlyInFormItems(nextItem.items, field, readOnly)
      if (childResult.changed) {
        changed = true
        nextItem = { ...nextItem, items: childResult.items }
      }
    }

    if (nextItem?.tabs?.length) {
      const tabs = nextItem.tabs.map((tab: any) => {
        const tabResult = updateReadOnlyInFormItems(tab.items, field, readOnly)
        if (tabResult.changed) {
          changed = true
          return { ...tab, items: tabResult.items }
        }
        return tab
      })
      nextItem = tabs === nextItem.tabs ? nextItem : { ...nextItem, tabs }
    }

    return nextItem
  })

  return { items: nextItems, changed }
}

const findFormFieldKey = (items: any[] = [], field: string): string => {
  const expected = String(field || '').toLowerCase()

  for (const item of items || []) {
    const key = item?.dataField || item?.name
    if (key && String(key).toLowerCase() === expected) {
      return key
    }

    const childKey = findFormFieldKey(item?.items || [], field)
    if (childKey) {
      return childKey
    }

    for (const tab of item?.tabs || []) {
      const tabKey = findFormFieldKey(tab?.items || [], field)
      if (tabKey) {
        return tabKey
      }
    }
  }

  return field
}

const setFormEditorReadOnly = (form: any, field: string, readOnly: boolean) => {
  if (!form?.option) return false

  const apply = () => {
    const formItems = form.option('items') || []
    const resolvedField = findFormFieldKey(formItems, field)
    const editor = form.getEditor?.(resolvedField) ?? form.getEditor?.(field)
    const result = updateReadOnlyInFormItems(formItems, resolvedField, readOnly)

    if (result.changed) {
      try {
        const item = form.itemOption?.(resolvedField) ?? form.itemOption?.(field)
        if (item) {
          form.itemOption?.(resolvedField, 'editorOptions', {
            ...(item.editorOptions || {}),
            readOnly,
          })
        } else {
          form.option('items', result.items)
        }
      } catch {
        form.option('items', result.items)
      }
    }

    const activeEditor = editor ?? form.getEditor?.(resolvedField) ?? form.getEditor?.(field)
    if (activeEditor?.option?.('readOnly') !== readOnly) {
      activeEditor?.option?.('readOnly', readOnly)
    }
  }

  apply()
  setTimeout(apply, 0)
  return true
}

const getActiveEditingForm = (component: any) => {
  const editForm = component?.getView?.('editingView')?._editForm
  return editForm?.getEditor || editForm?.itemOption ? editForm : undefined
}

const flattenEditingFormItems = (items: any[] = []): EditingFormItemDto[] =>
  items.flatMap((item) => [
    ...(item?.dataField ? [item] : []),
    ...flattenEditingFormItems(item?.items || []),
    ...(item?.tabs || []).flatMap((tab: any) => flattenEditingFormItems(tab?.items || [])),
  ])

const getValueByField = (data: Record<string, any> = {}, field?: string) => {
  if (!field) return undefined
  if (Object.prototype.hasOwnProperty.call(data, field)) return data[field]
  const key = Object.keys(data).find(
    (itemKey) => itemKey.toLowerCase() === String(field).toLowerCase(),
  )
  return key ? data[key] : undefined
}

const shouldRunEditorScriptOnContentReady = (script?: string) =>
  Boolean(
    script && (script.includes('setEditorReadOnly') || script.includes('runtimeSetEditorReadOnly')),
  )

const isTouchLikeDevice = () =>
  typeof window !== 'undefined' &&
  (window.matchMedia?.('(pointer: coarse)').matches || window.matchMedia?.('(hover: none)').matches)

const isMobileViewport = () =>
  typeof window !== 'undefined' && window.matchMedia?.('(max-width: 767px)').matches

const Tree = (props: TreeProps) => {
  const { listFormCode, searchParams, isSubForm, level, gridDto: extGridDto } = props
  const { translate } = useLocalization()
  const currentUser = useStoreState((state) => state.auth.user)
  const useMobileEditPopup = useRef(isMobileViewport() || isTouchLikeDevice()).current

  const gridRef = useRef<TreeListRef>()
  const refListFormCode = useRef('')
  const widgetGroupRef = useRef<HTMLDivElement>(null)
  const editingFormDataRef = useRef<Record<string, any>>({})
  const editingFormInstanceRef = useRef<any>()
  // Edit popup state kaydetmeyi engellemek için flag
  const isEditingRef = useRef(false)

  const [treeListDataSource, setTreeListDataSource] = useState<CustomStore<any, any>>()
  const [columnData, setColumnData] = useState<GridColumnData[]>()
  const [formData, setFormData] = useState<any>()
  const [mode, setMode] = useState<RowMode>('view')
  const [extraFilters, setExtraFilters] = useState<GridExtraFilterState[]>([])
  const [gridDto, setGridDto] = useState<GridDto>()
  const [isPopupFullScreen, setIsPopupFullScreen] = useState(false)
  const [widgetGroupHeight, setWidgetGroupHeight] = useState(0)
  const [notePanelTarget, setNotePanelTarget] = useState<{
    entityName: string
    entityId: string
  } | null>(null)

  const [expandedRowKeys, setExpandedRowKeys] = useState<any[]>([])

  type EditorOptionsWithButtons = {
    buttons?: any[]
  } & Record<string, any>

  const defaultSearchParams = useRef<string | null>(null)

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

    if (extGridDto === undefined) {
      initializeTreeList()
    } else {
      setGridDto(extGridDto)
    }
  }, [listFormCode, extGridDto])

  useEffect(() => {
    if (!defaultSearchParams.current) {
      defaultSearchParams.current = searchParams?.get('filter') ?? null
    }
  }, [searchParams])

  // StateStoring için storageKey'i memoize et
  const storageKey = useMemo(() => {
    return gridDto?.gridOptions.stateStoringDto?.storageKey ?? ''
  }, [gridDto?.gridOptions.stateStoringDto?.storageKey])

  const customSaveState = useCallback(
    (state: any) => {
      if (isEditingRef.current) {
        return Promise.resolve()
      }
      return postListFormCustomization({
        listFormCode: listFormCode,
        customizationType: ListFormCustomizationTypeEnum.GridState,
        filterName: `tree-${storageKey}`,
        customizationData: JSON.stringify(state),
      })
        .then(() => {
          setGridPanelColor(statedGridPanelColor)
          toast.push(
            <Notification type="success" duration={2000}>
              {translate('::ListForms.ListForm.GridStateSaved')}
            </Notification>,
            {
              placement: 'top-end',
            },
          )
        })
        .catch((err) => {
          toast.push(
            <Notification type="danger" duration={2500}>
              {translate('::ListForms.ListForm.GridStateSaveError')}
            </Notification>,
            {
              placement: 'top-end',
            },
          )
          throw err
        })
    },
    [listFormCode, storageKey, translate],
  )

  const customLoadState = useCallback(() => {
    return getListFormCustomization(
      listFormCode,
      ListFormCustomizationTypeEnum.GridState,
      `tree-${storageKey}`,
    ).then((response: any) => {
      if (response.data?.length > 0) {
        setGridPanelColor(statedGridPanelColor)
        return JSON.parse(response.data[0].customizationData)
      }
      // Veri yoksa null dön (DevExtreme bunu default state olarak algılar)
      return null
    })
  }, [listFormCode, storageKey])

  const { filterToolbarData, ...filterData } = useFilters({
    gridDto,
    gridRef,
    listFormCode,
    saveGridState: customSaveState,
  })

  const { createSelectDataSource } = useListFormCustomDataSource({ gridRef })

  const openNotePanel = useCallback(
    (rowData: Record<string, any>) => {
      const keyFieldName = gridDto?.gridOptions.keyFieldName
      const entityId = getValueByField(rowData, keyFieldName)
      if (entityId === undefined || entityId === null || entityId === '') {
        return
      }

      setNotePanelTarget({
        entityName: gridDto?.gridOptions.listFormCode ?? listFormCode,
        entityId: String(entityId),
      })
    },
    [gridDto, listFormCode],
  )

  const { getBandedColumns } = useListFormColumns({
    gridDto,
    listFormCode,
    isSubForm,
    gridRef,
    onShowNote: openNotePanel,
  })

  const extractSearchParamsFields = useCallback((filter: any): [string, string, any][] => {
    if (!Array.isArray(filter)) return []

    if (filter.length === 3 && typeof filter[0] === 'string') {
      return [filter as [string, string, any]]
    }

    return filter.flatMap((f) => extractSearchParamsFields(f))
  }, [])

  const getSelectedRowKeys = useCallback(async () => {
    const tree = gridRef.current?.instance()
    if (!tree) {
      return []
    }

    return await tree.getSelectedRowKeys()
  }, [])

  const getSelectedRowsData = useCallback(() => {
    const tree = gridRef.current?.instance()
    if (!tree) {
      return []
    }

    return tree.getSelectedRowsData()
  }, [])

  const expandAll = useCallback(() => {
    const tree = gridRef.current?.instance()
    if (!tree) return
    tree.forEachNode((node: any) => {
      if (node.hasChildren) {
        tree.expandRow(node.key)
      }
    })
  }, [])

  const collapseAll = useCallback(() => {
    const tree = gridRef.current?.instance()
    if (!tree) return
    tree.forEachNode((node: any) => {
      if (node.hasChildren) {
        tree.collapseRow(node.key)
      }
    })
  }, [])

  const updateWorkflowApprovalButtons = useCallback(
    (component?: any, selectedRowsData?: Record<string, unknown>[]) => {
      const tree = component ?? gridRef.current?.instance()
      if (!tree) {
        return
      }

      updateWorkflowApprovalToolbarItems(
        tree,
        gridDto?.gridOptions.workflowDto,
        selectedRowsData ?? tree.getSelectedRowsData(),
        currentUser,
      )
    },
    [currentUser, gridDto],
  )

  const refreshData = useCallback(() => {
    const tree = gridRef.current?.instance()
    const refreshResult = tree?.refresh()
    Promise.resolve(refreshResult).finally(() => updateWorkflowApprovalButtons(tree))
  }, [updateWorkflowApprovalButtons])

  const getFilter = useCallback(() => {
    const tree = gridRef.current?.instance()
    if (!tree) {
      return
    }

    return tree.getCombinedFilter()
  }, [])

  const layout = layoutTypes.tree
  const { toolbarData, toolbarModalData, setToolbarModalData } = useToolbar({
    gridDto,
    listFormCode,
    getSelectedRowKeys,
    getSelectedRowsData,
    refreshData,
    expandAll,
    collapseAll,
    getFilter,
    layout,
  })

  const onSelectionChanged = useCallback(
    (data: any) => {
      const treeOpt = gridDto?.gridOptions
      const tree = gridRef.current?.instance()
      if (!treeOpt || !tree) {
        return
      }

      if (treeOpt.editingOptionDto?.allowDeleting) {
        try {
          const opt = tree.option('toolbar')
          if (opt && opt.items && Array.isArray(opt.items)) {
            const deleteSelectedRecordsIndex = opt.items
              .map((e: any) => e.name)
              .indexOf('deleteSelectedRecords')

            if (deleteSelectedRecordsIndex >= 0) {
              tree.option(
                `toolbar.items[${deleteSelectedRecordsIndex}].options.visible`,
                data.selectedRowsData.length > 1,
              )
            }
          }
        } catch (error) {
          console.error('Error updating toolbar items:', error)
        }
      }

      updateWorkflowApprovalButtons(tree, data.selectedRowsData)

      if (data.selectedRowsData.length) {
        setFormData(data.selectedRowsData[0])
      }
    },
    [gridDto],
  )

  const onCellPrepared = useCallback(
    (e: any) => {
      const columnFormats = gridDto?.columnFormats
      if (!columnFormats) {
        return
      }

      for (let indxCol = 0; indxCol < columnFormats.length; indxCol++) {
        const colFormat = columnFormats[indxCol]
        for (let indxStyl = 0; indxStyl < colFormat.columnStylingDto.length; indxStyl++) {
          const colStyle = colFormat.columnStylingDto[indxStyl]
          if (e.rowType == colStyle.rowType) {
            if (colStyle.useRow || e.column.dataField == colFormat.fieldName) {
              if (
                !colStyle.conditionValue ||
                controlStyleCondition(e.data, colFormat.fieldName, colStyle)
              ) {
                if (colStyle.cssClassName) {
                  e.cellElement.addClass(colStyle.cssClassName)
                }
                if (colStyle.cssStyles) {
                  e.cellElement.attr(
                    'style',
                    e.cellElement.attr('style') + ';' + colStyle.cssStyles,
                  )
                }
              }
            }
          }
        }
      }
    },
    [gridDto],
  )

  function onInitNewRow(e: any) {
    if (!gridDto?.columnFormats) {
      editingFormDataRef.current = { ...(e.data || {}) }
      return
    }

    setMode('new')
    setIsPopupFullScreen(gridDto?.gridOptions.editingOptionDto?.popup?.fullScreen ?? false)

    for (const colFormat of gridDto?.columnFormats) {
      if (!colFormat.fieldName) {
        continue
      }

      // Grid'den gelen columnFormat'ları kullanarak default değerleri set et
      if (colFormat.defaultValue != null) {
        if (
          typeof colFormat.defaultValue === 'string' &&
          colFormat.defaultValue === '@AUTONUMBER'
        ) {
          e.data[colFormat.fieldName] = autoNumber
        } else {
          e.data[colFormat.fieldName] = colFormat.defaultValue
        }
      }

      if (extraFilters.some((f) => f.fieldName === colFormat.fieldName)) {
        continue
      }

      if (!searchParams) {
        continue
      }

      const rawFilter = searchParams?.get('filter')
      if (rawFilter) {
        const parsed = JSON.parse(rawFilter)
        const filters = extractSearchParamsFields(parsed)
        const fieldMatch = filters.find(([field]) => field === colFormat.fieldName)

        if (fieldMatch) {
          const val = fieldMatch[2] //value
          const dType = colFormat.dataType as DataType

          switch (dType) {
            case 'date':
            case 'datetime':
              e.data[colFormat.fieldName] = new Date(val)
              break
            case 'number':
              e.data[colFormat.fieldName] = Number(val)
              break
            case 'boolean':
              e.data[colFormat.fieldName] = val === true || val === 'true'
              break
            case 'object':
              try {
                e.data[colFormat.fieldName] = JSON.parse(val)
              } catch {}
              break
            default:
              e.data[colFormat.fieldName] = val
              break
          }
        }
      }

      editingFormDataRef.current = { ...(e.data || {}) }
    }
  }

  const onRowInserting = useCallback((e: TreeListTypes.RowInsertingEvent) => {
    e.data = setFormEditingExtraItemValues(e.data)
  }, [])

  const onRowUpdating = useCallback(
    (e: TreeListTypes.RowUpdatingEvent) => {
      if (gridDto?.gridOptions.editingOptionDto?.sendOnlyChangedFormValuesUpdate) {
        if (Object.keys(e.newData).some((a) => a.includes(':'))) {
          Object.keys(e.oldData).forEach((col) => {
            if (col.includes(':')) {
              e.newData[col] = e.newData[col] ?? e.oldData[col]
            }
          })
        }
        e.newData = setFormEditingExtraItemValues(e.newData)
      } else {
        let newData = { ...e.oldData, ...e.newData }
        newData = setFormEditingExtraItemValues(newData)
        Object.keys(newData).forEach((key) => {
          if (key.includes(':')) {
            delete newData[key]
          }
        })
        e.newData = newData
      }

      if (gridDto?.gridOptions.keyFieldName) {
        delete e.newData[gridDto?.gridOptions.keyFieldName]
      }
    },
    [gridDto],
  )

  const onEditingStart = useCallback(
    (e: TreeListTypes.EditingStartEvent) => {
      isEditingRef.current = true
      editingFormDataRef.current = { ...(e.data || {}) }
      setMode('edit')
      setIsPopupFullScreen(gridDto?.gridOptions.editingOptionDto?.popup?.fullScreen ?? false)
      const columns = e.component.option('columns') as GridColumnData[]
      columns?.forEach((col) => {
        if (!col.dataField?.includes(':')) {
          return
        }
        const field = col.dataField.split(':')
        if (!e.data[field[0]]) {
          return
        }
        const json = JSON.parse(e.data[field[0]])
        e.data[col.dataField] = json[field[1]]
      })
    },
    [gridDto],
  )

  const onDataErrorOccurred = useCallback((e: TreeListTypes.DataErrorOccurredEvent) => {
    toast.push(
      <Notification type="danger" duration={2000}>
        {e.error?.message}
      </Notification>,
      {
        placement: 'top-end',
      },
    )
  }, [])

  function onEditorPreparing(editor: TreeListTypes.EditorPreparingEvent) {
    if (editor.parentType === 'dataRow' && editor.dataField && gridDto) {
      const formItem = gridDto.gridOptions.editingFormDto
        .flatMap((group) => flattenEditingFormItems([group]))
        .find((i) => i.dataField === editor.dataField)
      const fieldName = editor.dataField.split(':')[0]
      const columnFormat = gridDto.columnFormats.find((column) => column.fieldName === fieldName)
      const isNewRow = Boolean((editor as any).row?.isNewRow) || mode === 'new'

      const hasReadOnlyEditorOption = editor.editorOptions?.readOnly === true
      const hasDisabledEditorOption = editor.editorOptions?.disabled === true

      if (
        (isNewRow && columnFormat?.allowAdding === false) ||
        (!isNewRow && columnFormat?.allowEditing === false)
      ) {
        editor.editorOptions.readOnly = true
      } else if (isNewRow && columnFormat?.allowAdding === true) {
        if (!hasReadOnlyEditorOption) {
          editor.editorOptions.readOnly = false
        }
        if (!hasDisabledEditorOption) {
          editor.editorOptions.disabled = false
        }
      }

      // Cascade disabled mantığı
      const colFormat = gridDto.columnFormats.find((c) => c.fieldName === editor.dataField)
      if (colFormat?.lookupDto?.cascadeParentFields) {
        const parentFields = colFormat.lookupDto.cascadeParentFields
          .split(',')
          .map((f: string) => f.trim())

        const prevHandler = editor.editorOptions.onValueChanged

        editor.editorOptions.onValueChanged = (e: any) => {
          if (prevHandler) prevHandler(e)

          // Parent field değiştiğinde tüm cascade childları kontrol et
          const grid = editor.component
          const rowKey = grid.option('editing.editRowKey')
          const rowIndex = grid.getRowIndexByKey(rowKey)
          const rowData = grid.getVisibleRows().find((r) => r.key === rowKey)?.data || {}

          // Bu field bir parent ise, child fieldleri temizle
          if (colFormat.lookupDto?.cascadeEmptyFields) {
            const childFields = colFormat.lookupDto.cascadeEmptyFields
              .split(',')
              .map((f: string) => f.trim())
            childFields.forEach((childField: string) => {
              if (rowIndex >= 0) {
                grid.cellValue(rowIndex, childField, null)
              }
            })
          }

          // Tüm cascade fieldlerin disabled durumlarını güncelle
          const popup = grid.option('editing.popup')
          if (popup) {
            const formInstance = grid.option('editing.form') as any
            if (formInstance && formInstance.getEditor) {
              gridDto.columnFormats.forEach((col) => {
                if (col.lookupDto?.cascadeParentFields) {
                  const colParentFields = col.lookupDto.cascadeParentFields
                    .split(',')
                    .map((f: string) => f.trim())
                  const shouldDisable = colParentFields.some((pf: string) => !rowData[pf])

                  try {
                    const editorInstance = formInstance.getEditor(col.fieldName!)
                    if (editorInstance) {
                      const formItem = gridDto.gridOptions.editingFormDto
                        .flatMap((group) => flattenEditingFormItems([group]))
                        .find((i) => i.dataField === col.fieldName)
                      const editorOptions = formItem?.editorOptions
                        ? JSON.parse(formItem.editorOptions)
                        : {}

                      editorInstance.option(
                        'disabled',
                        editorOptions?.disabled === true ? true : shouldDisable,
                      )
                    }
                  } catch (err) {
                    console.debug('Cascade disabled update skipped for', col.fieldName, err)
                  }
                }
              })
            }
          }
        }

        // İlk açılışta disabled durumunu kontrol et
        const grid = editor.component
        const rowKey = grid.option('editing.editRowKey')
        const rowData = grid.getVisibleRows().find((r) => r.key === rowKey)?.data || {}
        const shouldDisable = parentFields.some((pf: string) => !rowData[pf])

        if (shouldDisable) {
          editor.editorOptions.disabled = true
        }
      }

      if (formItem?.editorScript) {
        const prevHandler = editor.editorOptions.onValueChanged
        const editorDataField = editor.dataField

        editor.editorOptions.onValueChanged = (e: any) => {
          if (prevHandler) prevHandler(e)

          try {
            const grid = editor.component
            const rowKey = grid.option('editing.editRowKey')
            const rowIndex = grid.getRowIndexByKey(rowKey)

            const formData = {
              ...(grid.getVisibleRows().find((r) => r.key === rowKey)?.data || {}),
              [editorDataField]: e.value,
            }
            const runtimeSetEditorReadOnly = (field: string, readOnly: boolean) =>
              setFormEditorReadOnly(
                editingFormInstanceRef.current ?? getActiveEditingForm(grid),
                field,
                readOnly,
              )

            const setFormData = (newData: any) => {
              if (rowIndex >= 0) {
                Object.keys(newData).forEach((field) => {
                  grid.cellValue(rowIndex, field, newData[field])
                })
              }
            }

            executeEditorScript(formItem.editorScript!, {
              formData,
              e,
              editor,
              runtimeSetEditorReadOnly,
              setFormData,
            })
          } catch (err) {
            console.error('Script exec error', formItem.dataField, err)
          }
        }
      }

      if (editor.editorOptions?.buttons) {
        editor.editorOptions.buttons = editor.editorOptions.buttons.map((btn: any) => {
          if (btn?.options?.onClick && typeof btn.options.onClick === 'function') {
            const origClick = btn.options.onClick
            btn.options.onClick = (e: any) => {
              const grid = editor.component
              const rowKey = grid.option('editing.editRowKey')
              const rowIndex = grid.getRowIndexByKey(rowKey)
              const formData = grid.getVisibleRows().find((r) => r.key === rowKey)?.data || {}

              origClick({
                ...e,
                formData,
                fieldName: editor.dataField,
                rowKey,
                rowIndex,
              })
            }
          }
          return btn
        })
      }
    }
  }

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

    if (refListFormCode.current !== listFormCode) {
      setExtraFilters([])
    }
  }, [listFormCode])

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

    // İlk render'da hesapla
    calculateWidgetHeight()

    // Resize durumunda tekrar hesapla
    const resizeObserver = new ResizeObserver(calculateWidgetHeight)
    if (widgetGroupRef.current) {
      resizeObserver.observe(widgetGroupRef.current)
    }

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

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

    const treeOpt = gridDto.gridOptions
    if (treeOpt.customJsSources.length) {
      for (const js of treeOpt.customJsSources) {
        addJs(js)
      }
    }
    if (treeOpt.customStyleSources.length) {
      for (const css of treeOpt.customStyleSources) {
        addCss(css)
      }
    }

    if (gridDto?.gridOptions.extraFilterDto) {
      setExtraFilters(
        gridDto.gridOptions.extraFilterDto.map((f) => ({
          fieldName: f.fieldName,
          operator: f.operator,
          controlType: f.controlType,
          value: f.defaultValue ?? '',
        })),
      )
    }

    if (gridDto.gridOptions.editingOptionDto?.popup) {
      setIsPopupFullScreen(gridDto.gridOptions.editingOptionDto?.popup?.fullScreen ?? false)
    }

    // Set initial expanded row keys
    if (gridDto.gridOptions.treeOptionDto?.expandedRowKeys) {
      setExpandedRowKeys(gridDto.gridOptions.treeOptionDto.expandedRowKeys)
    } else if (gridDto.gridOptions.treeOptionDto?.autoExpandAll) {
      setExpandedRowKeys([])
    }
  }, [gridDto])

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

    const cols = getBandedColumns()
    setColumnData(cols)

    const dataSource = createSelectDataSource(
      gridDto.gridOptions,
      listFormCode,
      searchParams,
      layoutTypes.tree,
      cols,
    )
    setTreeListDataSource(dataSource)
  }, [gridDto, searchParams])

  useEffect(() => {
    const activeFilters = extraFilters.filter((f) => f.value)

    let base: any = null
    if (defaultSearchParams.current) {
      base = JSON.parse(defaultSearchParams.current)
    }

    const baseTriplets = extractSearchParamsFields(base)

    const extraTriplets = activeFilters.map(
      (f) => [f.fieldName, f.operator, f.value] as [string, string, any],
    )

    const merged = [...baseTriplets, ...extraTriplets].reduce(
      (acc, cur) => {
        const [field, op] = cur
        const idx = acc.findIndex((a) => a[0] === field && a[1] === op)
        if (idx >= 0) {
          acc[idx] = cur
        } else {
          acc.push(cur)
        }
        return acc
      },
      [] as [string, string, any][],
    )

    let filter: any = null
    if (merged.length === 1) {
      filter = merged[0]
    } else if (merged.length > 1) {
      filter = merged.reduce((acc, f, idx) => {
        if (idx === 0) return f
        return [acc, 'and', f]
      }, null as any)
    }

    if (filter) {
      searchParams?.set('filter', JSON.stringify(filter))
    } else {
      searchParams?.delete('filter')
    }

    gridRef.current?.instance().refresh()
  }, [extraFilters])

  useEffect(() => {
    if (!columnData || !gridRef?.current) return

    const instance = gridRef?.current?.instance()
    if (instance) {
      instance.option('columns', columnData as any)
    }
  }, [columnData])

  useEffect(() => {
    if (!treeListDataSource || !gridRef?.current) return

    const instance = gridRef?.current?.instance()
    if (instance) {
      instance.option('dataSource', treeListDataSource)
    }
  }, [treeListDataSource])

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

  // Component mount olduğunda state'i bir kez yükle
  useEffect(() => {
    if (!gridDto || !gridRef?.current || !treeListDataSource || !columnData) return

    const instance = gridRef?.current?.instance()
    if (instance) {
      customLoadState()
        .then((state) => {
          if (state) {
            instance.state(state)
          }
        })
        .catch((err) => {
          console.error('State load error:', err)
        })
    }
  }, [gridDto, treeListDataSource, columnData])

  // StateStoring'i devre dışı bırak - manuel kaydetme kullanılacak
  useEffect(() => {
    if (!gridDto || !gridRef?.current) return

    const instance = gridRef?.current?.instance()
    if (instance) {
      // Otomatik state kaydetme/yükleme kapalı
      instance.option('stateStoring', {
        enabled: false,
      })
    }
  }, [gridDto])

  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}
          ></Helmet>
        )}
        {gridDto && columnData && (
          <div className="p-1 bg-white dark:bg-neutral-800 dark:border-neutral-700 ">
            <TreeListDx
              ref={gridRef as any}
              id={'TreeList-' + listFormCode}
              height={
                gridDto.gridOptions.height > 0
                  ? gridDto.gridOptions.height
                  : gridDto.gridOptions.fullHeight
                    ? `calc(100vh - ${170 + widgetGroupHeight}px)`
                    : undefined
              }
              width={gridDto.gridOptions.width || '100%'}
              dataStructure="plain"
              keyExpr={gridDto.gridOptions.treeOptionDto?.keyExpr}
              parentIdExpr={gridDto.gridOptions.treeOptionDto?.parentIdExpr}
              hasItemsExpr={gridDto.gridOptions.treeOptionDto?.hasItemsExpr}
              rootValue={
                gridDto.gridOptions.treeOptionDto?.rootValue === '' ||
                gridDto.gridOptions.treeOptionDto?.rootValue === undefined
                  ? null
                  : gridDto.gridOptions.treeOptionDto?.rootValue
              }
              {...(!gridDto.gridOptions.treeOptionDto?.autoExpandAll && {
                expandedRowKeys: expandedRowKeys,
                onRowExpanding: (e: any) => {
                  setExpandedRowKeys((prev) => [...prev, e.key])
                },
                onRowCollapsing: (e: any) => {
                  setExpandedRowKeys((prev) => prev.filter((k) => k !== e.key))
                },
              })}
              autoExpandAll={gridDto.gridOptions.treeOptionDto?.autoExpandAll || false}
              allowColumnResizing={gridDto.gridOptions.columnOptionDto?.allowColumnResizing}
              allowColumnReordering={gridDto.gridOptions.columnOptionDto?.allowColumnReordering}
              showBorders={gridDto.gridOptions.columnOptionDto?.showBorders}
              showRowLines={gridDto.gridOptions.columnOptionDto?.showRowLines}
              showColumnLines={gridDto.gridOptions.columnOptionDto?.showColumnLines}
              columnResizingMode={gridDto.gridOptions.columnOptionDto?.columnResizingMode}
              columnAutoWidth={gridDto.gridOptions.columnOptionDto?.columnAutoWidth}
              rtlEnabled={gridDto.gridOptions.columnOptionDto?.rtlEnabled}
              rowAlternationEnabled={gridDto.gridOptions.columnOptionDto?.rowAlternationEnabled}
              onRowPrepared={(e) => {
                //header, filter, data, group, summaries
                if (e.rowType === 'data') {
                  e.rowElement.style.height = gridDto.gridOptions?.rowDto.rowHeight
                  e.rowElement.style.whiteSpace = gridDto.gridOptions?.rowDto.whiteSpace
                  e.rowElement.style.overflowWrap = gridDto.gridOptions?.rowDto.overflowWrap
                }
              }}
              hoverStateEnabled={gridDto.gridOptions.columnOptionDto?.hoverStateEnabled}
              columnHidingEnabled={gridDto.gridOptions.columnOptionDto?.columnHidingEnabled}
              focusedRowEnabled={gridDto.gridOptions.columnOptionDto?.focusedRowEnabled}
              showColumnHeaders={gridDto.gridOptions.columnOptionDto?.showColumnHeaders}
              filterSyncEnabled={true}
              onSelectionChanged={onSelectionChanged}
              onInitNewRow={onInitNewRow}
              onCellPrepared={onCellPrepared}
              onRowInserting={onRowInserting}
              onRowUpdating={onRowUpdating}
              onEditingStart={onEditingStart}
              onDataErrorOccurred={onDataErrorOccurred}
              onEditCanceled={() => {
                isEditingRef.current = false
                setMode('view')
                setIsPopupFullScreen(false)
              }}
              onSaved={() => {
                isEditingRef.current = false
                setMode('view')
                setIsPopupFullScreen(false)
              }}
              onRowInserted={(e) => {
                const insertedKey = getPersistedInsertedKey(e, gridDto.gridOptions.keyFieldName)

                if (
                  gridDto.gridOptions.workflowDto?.approvalStatusFieldName &&
                  insertedKey !== undefined
                ) {
                  workflowService
                    .startWorkflow(listFormCode, [insertedKey])
                    .then((result) => {
                      const messages = result.toastMessages ?? []
                      if (messages.length > 0) {
                        toast.push(
                          <Notification type="info" duration={7000}>
                            {messages.map((message, messageIndex) => (
                              <div
                                key={messageIndex}
                                className={messageIndex > 0 ? 'mt-2 border-t pt-2' : undefined}
                              >
                                {message.split('\n').map((line, lineIndex) => (
                                  <div key={lineIndex}>{line}</div>
                                ))}
                              </div>
                            ))}
                          </Notification>,
                          { placement: 'top-end' },
                        )
                      }
                      gridRef.current?.instance()?.refresh()
                    })
                    .catch(console.error)
                }
                props.refreshData?.()
              }}
              onRowUpdated={() => {
                props.refreshData?.()
              }}
              onRowRemoved={() => {
                props.refreshData?.()
              }}
              onEditorPreparing={onEditorPreparing}
              onContentReady={(e) => {
                updateWorkflowApprovalButtons(e.component)

                // Restore expanded keys after data refresh (only if autoExpandAll is false)
                if (
                  !gridDto.gridOptions.treeOptionDto?.autoExpandAll &&
                  expandedRowKeys.length > 0
                ) {
                  e.component.option('expandedRowKeys', expandedRowKeys)
                }
              }}
            >
              <RemoteOperations filtering={true} sorting={true} grouping={false} />
              <Editing
                refreshMode={gridDto.gridOptions.editingOptionDto?.refreshMode}
                mode={gridDto.gridOptions.editingOptionDto?.mode}
                allowDeleting={gridDto.gridOptions.editingOptionDto?.allowDeleting}
                allowUpdating={gridDto.gridOptions.editingOptionDto?.allowUpdating}
                allowAdding={gridDto.gridOptions.editingOptionDto?.allowAdding}
                useIcons={gridDto.gridOptions.editingOptionDto?.useIcons}
                confirmDelete={gridDto.gridOptions.editingOptionDto?.confirmDelete}
                selectTextOnEditStart={gridDto.gridOptions.editingOptionDto?.selectTextOnEditStart}
                startEditAction={gridDto.gridOptions.editingOptionDto?.startEditAction}
                popup={{
                  animation: {},
                  wrapperAttr: useMobileEditPopup ? { class: 'mobile-edit-popup' } : undefined,
                  title:
                    (mode === 'new' ? '✚ ' : '🖊️ ') +
                    translate('::' + gridDto.gridOptions.editingOptionDto?.popup?.title),
                  showTitle: gridDto.gridOptions.editingOptionDto?.popup?.showTitle,
                  hideOnOutsideClick:
                    gridDto.gridOptions.editingOptionDto?.popup?.hideOnOutsideClick,
                  width: useMobileEditPopup
                    ? '100%'
                    : gridDto.gridOptions.editingOptionDto?.popup?.width,
                  height: useMobileEditPopup
                    ? '100dvh'
                    : gridDto.gridOptions.editingOptionDto?.popup?.height,
                  position: useMobileEditPopup
                    ? {
                        my: 'top center',
                        at: 'top center',
                        of: typeof window !== 'undefined' ? window : undefined,
                      }
                    : gridDto.gridOptions.editingOptionDto?.popup?.position,
                  resizeEnabled: gridDto.gridOptions.editingOptionDto?.popup?.resizeEnabled,
                  fullScreen: isPopupFullScreen,
                  dragEnabled: gridDto.gridOptions.editingOptionDto?.popup?.dragEnabled,
                  restorePosition: gridDto.gridOptions.editingOptionDto?.popup?.restorePosition,
                  toolbarItems: [
                    {
                      widget: 'dxButton',
                      toolbar: 'bottom',
                      location: 'after',
                      options: {
                        text: translate('::Save'),
                        type: 'default',
                        onClick: () => {
                          const tree = gridRef.current?.instance()
                          tree?.saveEditData()
                        },
                      },
                    },
                    {
                      widget: 'dxButton',
                      toolbar: 'bottom',
                      location: 'after',
                      options: {
                        text: translate('::Cancel'),
                        onClick: () => {
                          const tree = gridRef.current?.instance()
                          tree?.cancelEditData()
                        },
                      },
                    },
                    {
                      widget: 'dxButton',
                      toolbar: 'top',
                      location: 'after',
                      options: {
                        icon: isPopupFullScreen ? 'collapse' : 'fullscreen',
                        hint: isPopupFullScreen
                          ? translate('::Normal Boyut')
                          : translate('::Tam Ekran'),
                        stylingMode: 'text',
                        onClick: () => setIsPopupFullScreen(!isPopupFullScreen),
                      },
                    },
                  ],
                }}
                form={{
                  colCount: 1,
                  onContentReady: (e) => {
                    editingFormInstanceRef.current = e.component

                    const form = e.component
                    const grid = gridRef.current?.instance()
                    const rowKey = grid?.option('editing.editRowKey')
                    const rowIndex = rowKey !== undefined ? grid?.getRowIndexByKey(rowKey) : -1
                    const runtimeSetEditorReadOnly = (field: string, readOnly: boolean) =>
                      setFormEditorReadOnly(form, field, readOnly)
                    const setFormData = (newData: any) => {
                      form?.option?.('formData', newData)
                      editingFormDataRef.current = { ...newData }
                      if (grid && rowIndex !== undefined && rowIndex >= 0) {
                        Object.keys(newData).forEach((field) => {
                          grid.cellValue(rowIndex, field, newData[field])
                        })
                      }
                    }

                    const runReadOnlyScripts = () => {
                      const formItems = gridDto.gridOptions.editingFormDto.flatMap((group) =>
                        flattenEditingFormItems([group]),
                      )
                      const scriptItems = formItems.filter((formItem) =>
                        shouldRunEditorScriptOnContentReady(formItem.editorScript),
                      )

                      if (!scriptItems.length) {
                        return
                      }

                      const editorValues = formItems.reduce<Record<string, any>>(
                        (values, formItem) => {
                          const editorInstance = form?.getEditor?.(formItem.dataField)
                          if (editorInstance?.option) {
                            values[formItem.dataField] = editorInstance.option('value')
                          }
                          return values
                        },
                        {},
                      )
                      const formData = {
                        ...editingFormDataRef.current,
                        ...(form?.option?.('formData') || {}),
                        ...editorValues,
                      }
                      editingFormDataRef.current = { ...formData }

                      scriptItems.forEach((formItem) => {
                        try {
                          const editorInstance = form?.getEditor?.(formItem.dataField)
                          const editorValue =
                            editorInstance?.option?.('value') ??
                            getValueByField(formData, formItem.dataField)
                          const editor = {
                            dataField: formItem.dataField,
                            component: grid,
                          }
                          const e = {
                            component: form,
                            dataField: formItem.dataField,
                            value: editorValue,
                          }

                          executeEditorScript(formItem.editorScript!, {
                            formData,
                            e,
                            editor,
                            runtimeSetEditorReadOnly,
                            setFormData,
                          })
                        } catch (err) {
                          console.error(
                            'Script exec error on contentReady',
                            formItem.dataField,
                            err,
                          )
                        }
                      })
                    }

                    runReadOnlyScripts()
                  },
                  onFieldDataChanged: (e) => {
                    if (e.dataField) {
                      const previousValue = editingFormDataRef.current?.[e.dataField]
                      editingFormDataRef.current = {
                        ...(e.component?.option?.('formData') || {}),
                      }

                      const formItem = gridDto.gridOptions.editingFormDto
                        .flatMap((group) => flattenEditingFormItems([group]))
                        .find(
                          (i) =>
                            String(i.dataField || '').toLowerCase() ===
                            String(e.dataField || '').toLowerCase(),
                        )
                      if (formItem?.editorScript) {
                        try {
                          const grid = gridRef.current?.instance()
                          const rowKey = grid?.option('editing.editRowKey')
                          const rowIndex =
                            rowKey !== undefined ? grid?.getRowIndexByKey(rowKey) : -1
                          const formData = {
                            ...(e.component?.option?.('formData') || {}),
                            [e.dataField]: e.value,
                          }
                          editingFormDataRef.current = { ...formData }
                          const runtimeSetEditorReadOnly = (field: string, readOnly: boolean) =>
                            setFormEditorReadOnly(e.component, field, readOnly)
                          const setFormData = (newData: any) => {
                            e.component?.option?.('formData', newData)
                            editingFormDataRef.current = { ...newData }
                            if (grid && rowIndex !== undefined && rowIndex >= 0) {
                              Object.keys(newData).forEach((field) => {
                                grid.cellValue(rowIndex, field, newData[field])
                              })
                            }
                          }

                          executeEditorScript(formItem.editorScript, {
                            formData,
                            e,
                            editor: {
                              dataField: e.dataField,
                              component: grid,
                            },
                            runtimeSetEditorReadOnly,
                            setFormData,
                          })
                        } catch (err) {
                          console.error('Script exec error', err)
                        }
                      }
                    }
                  },
                  items:
                    gridDto.gridOptions.editingFormDto?.length > 0
                      ? (() => {
                          const sortedFormDto = gridDto.gridOptions.editingFormDto
                            .slice()
                            .sort((a: any, b: any) => (a.order >= b.order ? 1 : -1))

                          // Tabbed item'ları grupla
                          const tabbedItems = sortedFormDto.filter(
                            (e: any) => e.itemType === 'tabbed',
                          )
                          const result: any[] = []

                          // Helper function: item mapper
                          const mapFormItem = (i: EditingFormItemDto) => {
                            let editorOptions: EditorOptionsWithButtons = {}
                            let parsedEditorOptions: EditorOptionsWithButtons = {}
                            const forcedEditorOptions: EditorOptionsWithButtons = {}
                            try {
                              parsedEditorOptions = i.editorOptions
                                ? JSON.parse(i.editorOptions)
                                : {}

                              const rawFilter = searchParams?.get('filter')
                              if (rawFilter) {
                                const parsed = JSON.parse(rawFilter)
                                const filters = extractSearchParamsFields(parsed)

                                const hasFilter = filters.some(
                                  ([field, op, val]) => field === i.dataField,
                                )

                                if (hasFilter) {
                                  const existsInExtra = extraFilters.some(
                                    (f) => f.fieldName === i.dataField && !!f.value,
                                  )

                                  if (!existsInExtra) {
                                    forcedEditorOptions.readOnly = true
                                  }
                                }
                              }
                            } catch {}

                            const fieldName = i.dataField.split(':')[0]
                            const listFormField = gridDto.columnFormats.find(
                              (x: any) => x.fieldName === fieldName,
                            )

                            const defaultEditorOptions: EditorOptionsWithButtons = {}

                            if (listFormField?.sourceDbType === DbTypeEnum.Date) {
                              Object.assign(defaultEditorOptions, {
                                type: 'date',
                                dateSerializationFormat: 'yyyy-MM-dd',
                                displayFormat: 'shortDate',
                              })
                            } else if (
                              listFormField?.sourceDbType === DbTypeEnum.DateTime ||
                              listFormField?.sourceDbType === DbTypeEnum.DateTime2 ||
                              listFormField?.sourceDbType === DbTypeEnum.DateTimeOffset
                            ) {
                              Object.assign(defaultEditorOptions, {
                                type: 'datetime',
                                dateSerializationFormat: 'yyyy-MM-ddTHH:mm:ss',
                                displayFormat: 'shortDateShortTime',
                              })
                            }

                            editorOptions = {
                              ...defaultEditorOptions,
                              ...parsedEditorOptions,
                              ...forcedEditorOptions,
                            }

                            if (editorOptions?.buttons) {
                              editorOptions.buttons = (editorOptions?.buttons || []).map(
                                (btn: any) => {
                                  if (
                                    btn?.options?.onClick &&
                                    typeof btn.options.onClick === 'string'
                                  ) {
                                    btn.options.onClick = eval(`(${btn.options.onClick})`)
                                  }
                                  return btn
                                },
                              )
                            }

                            const item: SimpleItemWithColData = {
                              canRead: listFormField?.canRead ?? false,
                              canUpdate: listFormField?.canUpdate ?? false,
                              canCreate: listFormField?.canCreate ?? false,
                              canExport: listFormField?.canExport ?? false,
                              allowEditing: listFormField?.allowEditing ?? true,
                              allowAdding: listFormField?.allowAdding ?? true,
                              dataField: i.dataField,
                              name: i.dataField,
                              editorType2: i.editorType2,
                              editorType:
                                i.editorType2 == PlatformEditorTypes.dxGridBox
                                  ? 'dxDropDownBox'
                                  : i.editorType2 == PlatformEditorTypes.dxImageUpload
                                    ? undefined
                                    : i.editorType2,
                              colSpan: i.colSpan,
                              editorOptions,
                              editorScript: i.editorScript,
                            }

                            if (i.dataField.indexOf(':') >= 0) {
                              item.label = { text: captionize(i.dataField.split(':')[1]) }
                            }

                            if (
                              (mode == 'edit' && !item.canUpdate) ||
                              (mode == 'new' && !item.canCreate)
                            ) {
                              item.editorOptions = {
                                ...item.editorOptions,
                                readOnly: true,
                              }
                            }

                            return item
                          }

                          sortedFormDto.forEach((e: any) => {
                            if (e.itemType !== 'tabbed') {
                              result.push({
                                itemType: e.itemType,
                                colCount: e.colCount,
                                colSpan: e.colSpan,
                                caption: e.caption, // Group'larda caption olmalı
                                items: e.items
                                  ?.sort((a: any, b: any) => (a.order >= b.order ? 1 : -1))
                                  .map(mapFormItem)
                                  .filter((a: any) => {
                                    if (mode === 'view') {
                                      return a.canRead
                                    } else if (mode === 'new') {
                                      return a.canCreate && a.allowAdding
                                    } else if (mode === 'edit') {
                                      return a.canUpdate && a.allowEditing
                                    } else {
                                      return false
                                    }
                                  }),
                              })
                            } else if (tabbedItems.length > 0 && e === tabbedItems[0]) {
                              // Tabbed için caption OLMAMALI - sadece tabs array içinde title kullan
                              result.push({
                                itemType: 'tabbed',
                                colCount: 1,
                                colSpan: 1,
                                // caption kullanma! Tabs içindeki title'lar yeterli
                                tabs: tabbedItems.map((tabbedItem: any) => {
                                  // Backend'den gelen colCount ve colSpan değerlerini kullan
                                  const effectiveColCount = tabbedItem.colCount || 1

                                  return {
                                    title: tabbedItem.caption, // Her tab'ın title'ı
                                    colCount: effectiveColCount,
                                    items: tabbedItem.items
                                      ?.sort((a: any, b: any) => (a.order >= b.order ? 1 : -1))
                                      .map(mapFormItem)
                                      .filter((a: any) => {
                                        if (mode === 'view') {
                                          return a.canRead
                                        } else if (mode === 'new') {
                                          return a.canCreate && a.allowAdding
                                        } else if (mode === 'edit') {
                                          return a.canUpdate && a.allowEditing
                                        } else {
                                          return false
                                        }
                                      }),
                                  }
                                }),
                              })
                            }
                          })

                          return result
                        })()
                      : undefined,
                }}
              ></Editing>
              <Template name={'cellEditTagBox'} render={TagBoxEditorComponent} />
              <Template name={'cellEditGridBox'} render={GridBoxEditorComponent} />
              <Template name="extraFilters">
                <GridExtraFilterToolbar
                  filters={gridDto?.gridOptions.extraFilterDto ?? []}
                  extraFilters={extraFilters}
                  setExtraFilters={setExtraFilters}
                />
              </Template>
              <Toolbar
                visible={(toolbarData?.length ?? 0) > 0 || (filterToolbarData?.length ?? 0) > 0}
              >
                {toolbarData?.map((item) => (
                  <Item key={item.name} {...item}></Item>
                ))}
                {filterToolbarData?.map((item) => (
                  <Item key={item.name} {...item}></Item>
                ))}
                {/* burada özel filtre alanını Template ile bağla */}
                {gridDto?.gridOptions.extraFilterDto?.length ? (
                  <Item location="before" template="extraFilters" cssClass="no-default" />
                ) : null}
              </Toolbar>
              <Sorting mode={gridDto.gridOptions?.sortMode}></Sorting>
              <FilterRow
                visible={gridDto.gridOptions.filterRowDto?.visible}
                applyFilter={gridDto.gridOptions.filterRowDto?.applyFilter}
              ></FilterRow>
              <FilterPanel visible={gridDto.gridOptions.filterPanelDto.visible}></FilterPanel>
              <HeaderFilter visible={gridDto.gridOptions.headerFilterDto.visible}></HeaderFilter>
              <SearchPanel
                visible={gridDto.gridOptions.searchPanelDto.visible}
                width={gridDto.gridOptions.searchPanelDto.width}
                placeholder={translate('::App.Search')}
              ></SearchPanel>
              <Selection
                mode={gridDto.gridOptions.selectionDto?.mode}
                recursive={gridDto.gridOptions.treeOptionDto?.recursiveSelection || false}
              ></Selection>
              <Paging enabled={true} defaultPageSize={gridDto.gridOptions.pageSize ?? 10} />
              <Pager
                visible={gridDto.gridOptions.pagerOptionDto?.visible ?? true}
                allowedPageSizes={
                  gridDto.gridOptions.pagerOptionDto?.allowedPageSizes
                    ?.split(',')
                    .map((a: any) => +a) ?? [10, 20, 50, 100]
                }
                showPageSizeSelector={
                  gridDto.gridOptions.pagerOptionDto?.showPageSizeSelector ?? true
                }
                showInfo={gridDto.gridOptions.pagerOptionDto?.showInfo ?? true}
                showNavigationButtons={
                  gridDto.gridOptions.pagerOptionDto?.showNavigationButtons ?? true
                }
                infoText={gridDto.gridOptions.pagerOptionDto?.infoText}
                displayMode={gridDto.gridOptions.pagerOptionDto?.displayMode ?? 'full'}
              ></Pager>
              <ColumnChooser
                enabled={gridDto.gridOptions.columnOptionDto?.columnChooserEnabled}
                mode={gridDto.gridOptions.columnOptionDto?.columnChooserMode}
              ></ColumnChooser>
              <ColumnFixing
                enabled={gridDto.gridOptions.columnOptionDto?.columnFixingEnabled}
              ></ColumnFixing>
              <Scrolling mode={gridDto.gridOptions.pagerOptionDto?.scrollingMode}></Scrolling>
              <LoadPanel
                enabled={gridDto.gridOptions.pagerOptionDto?.loadPanelEnabled}
                text={gridDto.gridOptions.pagerOptionDto?.loadPanelText}
              ></LoadPanel>
            </TreeListDx>

            {gridDto?.gridOptions?.subFormsDto?.length > 0 &&
              gridDto?.gridOptions?.subFormsListFormType === SubFormTabTypeEnum.List && (
                <>
                  <hr className="my-2" />
                  <SubForms gridDto={gridDto!} formData={formData} level={level ?? 0} />
                </>
              )}

            <Dialog
              width={useMobileEditPopup ? '100%' : 1000}
              isOpen={filterData.isImportModalOpen || false}
              onClose={() => filterData.setIsImportModalOpen(false)}
              onRequestClose={() => filterData.setIsImportModalOpen(false)}
            >
              <Dialog.Header className="-mx-6 -mt-6 flex h-11 items-center px-6 pr-20 border-b border-gray-200 dark:border-gray-700">
                <h2 className="text-lg font-semibold text-gray-800 dark:text-gray-100">
                  {translate('::ListForms.ListForm.ImportManager')}
                </h2>
              </Dialog.Header>
              <Dialog.Body className="flex flex-col">
                <ImportDashboard gridDto={gridDto} />
              </Dialog.Body>
            </Dialog>
          </div>
        )}

        <Dialog
          isOpen={toolbarModalData?.open || false}
          onClose={() => setToolbarModalData(undefined)}
          onRequestClose={() => setToolbarModalData(undefined)}
        >
          {toolbarModalData?.content}
        </Dialog>
        <GridFilterDialogs gridRef={gridRef as any} listFormCode={listFormCode} {...filterData} />
        {notePanelTarget && (
          <NotePanel
            entityName={notePanelTarget.entityName}
            entityId={notePanelTarget.entityId}
            isVisible
            onToggle={() => setNotePanelTarget(null)}
          />
        )}
      </Container>
    </>
  )
}

export default Tree
