import Container from '@/components/shared/Container'
import { Dialog, Notification, toast } from '@/components/ui'
import { DX_CLASSNAMES } from '@/constants/app.constant'
import {
  DbTypeEnum,
  EditingFormItemDto,
  GridDto,
  ListFormCustomizationTypeEnum,
  PlatformEditorTypes,
} from '@/proxy/form/models'
import {
  getListFormCustomization,
  postListFormCustomization,
} from '@/services/list-form-customization.service'
import { useLocalization } from '@/utils/hooks/useLocalization'
import useResponsive from '@/utils/hooks/useResponsive'
import { Template } from 'devextreme-react/core/template'
import DataGrid, {
  ColumnChooser,
  ColumnFixing,
  DataGridRef,
  DataGridTypes,
  Editing,
  Export,
  FilterPanel,
  FilterRow,
  Grouping,
  GroupItem as GroupItemDx,
  GroupPanel,
  HeaderFilter,
  IStateStoringProps,
  LoadPanel,
  Pager,
  Paging,
  Scrolling,
  SearchPanel,
  Selection,
  Sorting,
  Summary,
  Toolbar,
  TotalItem,
} from 'devextreme-react/data-grid'
import { Item } from 'devextreme-react/toolbar'
import { DataType } from 'devextreme/common'
import { captionize } from 'devextreme/core/utils/inflector'
import CustomStore from 'devextreme/data/custom_store'
import { useCallback, useEffect, useRef, useState } from 'react'
import { Helmet } from 'react-helmet'
import SubForms from '../form/SubForms'
import { RowMode, SimpleItemWithColData } from '../form/types'
import { GridColumnData } from './GridColumnData'
import GridFilterDialogs from './GridFilterDialogs'
import {
  addCss,
  addJs,
  autoNumber,
  controlStyleCondition,
  extractSearchParamsFields,
  GridExtraFilterState,
  setFormEditingExtraItemValues,
  setGridPanelColor,
} from './Utils'
import { GridBoxEditorComponent } from './editors/GridBoxEditorComponent'
import { TagBoxEditorComponent } from './editors/TagBoxEditorComponent'
import { useFilters } from './useFilters'
import { useToolbar } from './useToolbar'
import { ImportDashboard } from '@/components/importManager/ImportDashboard'
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 { Loading } from '@/components/shared'
import { useStoreState } from '@/store'
import { locale, loadMessages } from 'devextreme/localization'

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

const statedGridPanelColor = 'rgba(50, 200, 200, 0.5)' // kullanici tanimli gridState ile islem gormus gridin paneline ait renk

const Grid = (props: GridProps) => {
  const { listFormCode, searchParams, isSubForm, level, gridDto: extGridDto } = props
  const { translate } = useLocalization()
  const { smaller } = useResponsive()
  const config = useStoreState((state) => state.abpConfig.config)

  const gridRef = useRef<DataGridRef>()
  const refListFormCode = useRef('')
  const widgetGroupRef = useRef<HTMLDivElement>(null)
  // Edit popup state kaydetmeyi engellemek için flag
  const isEditingRef = useRef(false)

  const [gridDataSource, setGridDataSource] = 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 preloadExportLibs = () => {
    import('exceljs')
    import('file-saver')
    import('devextreme/excel_exporter')
    import('jspdf')
    import('devextreme/pdf_exporter')
  }

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

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

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

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

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

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

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

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

  async function getSelectedRowKeys() {
    const grd = gridRef.current?.instance()
    if (!grd) {
      return []
    }

    return await grd.getSelectedRowKeys()
  }

  function getSelectedRowsData() {
    const grd = gridRef.current?.instance()
    if (!grd) {
      return []
    }

    return grd.getSelectedRowsData()
  }

  function refreshData() {
    gridRef.current?.instance()?.refresh()
  }

  function getFilter() {
    const grd = gridRef.current?.instance()
    if (!grd) {
      return
    }

    return grd.getCombinedFilter()
  }

  function onSelectionChanged(data: any) {
    const grdOpt = gridDto?.gridOptions
    const grd = gridRef.current?.instance()
    if (!grdOpt || !grd) {
      return
    }

    // kullanicinin yetkisi varsa ve birden fazla kayit secili ise coklu silme gorunsun
    if (grdOpt.editingOptionDto?.allowDeleting) {
      // && abp.auth.isGranted(grdOpt.permissionDto?.d)
      // kullanicinin silme yetkisi var ise
      const opt = grd.option('toolbar')
      const deleteSelectedRecordsIndex = opt?.items
        ?.map((e: any) => e.name)
        .indexOf('deleteSelectedRecords')
      // deleteSelectedRecords ismindeki custom butonun index degerini bul

      grd.option(
        `toolbar.items[${deleteSelectedRecordsIndex}].options.visible`,
        data.selectedRowsData.length > 1,
      ) // birden fazla kayit secilmis ise gorunsun
    }

    // SubForm'ları gösterebilmek için secili satiri formData'ya at
    if (data.selectedRowsData.length) {
      setFormData(data.selectedRowsData[0])
    }
  }

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

    // satir, hucre yada header vb. kisimlara conditional style uygulamak icin
    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] // uygulanacak style
        if (e.rowType == colStyle.rowType) {
          // header, filter, data, group, summaries ..her birisine style uygulanabilir
          // style bütün satıra uygulansın olarak seçili ise yada sadece ilgili field üzerinde ise
          if (colStyle.useRow || e.column.dataField == colFormat.fieldName) {
            if (
              !colStyle.conditionValue ||
              controlStyleCondition(e.data, colFormat.fieldName, colStyle)
            ) {
              // css sınıf ismi var ise uygula
              if (colStyle.cssClassName) {
                e.cellElement.addClass(colStyle.cssClassName)
              }
              // css inline style var ise uygula
              if (colStyle.cssStyles) {
                e.cellElement.attr('style', e.cellElement.attr('style') + ';' + colStyle.cssStyles)
              }
            }
          }
        }
      }
    }
  }

  function onInitNewRow(e: any) {
    if (!gridDto?.columnFormats) {
      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
        }
      }

      // ExtraFilters içerisinde ilgili Field varsa, default değerleri set etme
      if (extraFilters.some((f) => f.fieldName === colFormat.fieldName)) {
        continue
      }

      // URL'den veya Component Prop'dan gelen parametreleri set et
      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
          }
        }
      }
    }
  }

  function onRowInserting(e: DataGridTypes.RowInsertingEvent<any, any>) {
    e.data = setFormEditingExtraItemValues(e.data)
  }

  function onRowUpdating(e: DataGridTypes.RowUpdatingEvent<any, any>) {
    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]
    }
  }

  function onEditingStart(e: DataGridTypes.EditingStartEvent<any, any>) {
    isEditingRef.current = true
    setMode('edit')
    setIsPopupFullScreen(gridDto?.gridOptions.editingOptionDto?.popup?.fullScreen ?? false)
    const columns = e.component.option('columns') as GridColumnData[]
    // FormEditingExtraItem field ise datayı doldur
    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]]
    })
  }

  function onDataErrorOccurred(e: DataGridTypes.DataErrorOccurredEvent<any, any>) {
    toast.push(
      <Notification type="danger" duration={2000}>
        {e.error?.message}
      </Notification>,
      {
        placement: 'top-end',
      },
    )
  }

  function onEditorPreparing(editor: DataGridTypes.EditorPreparingEvent<any, any>) {
    if (editor.parentType === 'dataRow' && editor.dataField && gridDto) {
      const formItem = gridDto.gridOptions.editingFormDto
        .flatMap((group) => group.items || [])
        .find((i) => i.dataField === editor.dataField)

      // 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) {
                      editorInstance.option('disabled', 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

        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 || {}

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

            eval(formItem.editorScript!)
          } 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
        })
      }
    }
  }

  const customSaveState = useCallback(
    (state: any) => {
      if (isEditingRef.current) {
        return Promise.resolve()
      }
      return postListFormCustomization({
        listFormCode: listFormCode,
        customizationType: ListFormCustomizationTypeEnum.GridState,
        filterName: `list-${gridRef.current?.instance()?.option('stateStoring')?.storageKey ?? ''}`,
        customizationData: JSON.stringify(state),
      }).then(() => {
        setGridPanelColor(statedGridPanelColor)
      })
    },
    [listFormCode],
  )

  const customLoadState = useCallback(() => {
    return getListFormCustomization(
      listFormCode,
      ListFormCustomizationTypeEnum.GridState,
      `list-${gridRef.current?.instance()?.option('stateStoring')?.storageKey ?? ''}`,
    ).then((response: any) => {
      setGridPanelColor(statedGridPanelColor)
      if (response.data?.length > 0) {
        return JSON.parse(response.data[0].customizationData)
      }
    })
  }, [listFormCode])

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

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

  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)
      }
    }

    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)
    }
  }, [gridDto])

  // Kolonları oluştur - dil değiştiğinde güncelle
  useEffect(() => {
    if (!gridDto || !config) return

    const cols = getBandedColumns()

    cols?.forEach((col) => {
      const eo = col.editorOptions

      // Sadece phoneGlobal formatlı kolonlarda çalış
      if (eo?.format === 'phoneGlobal') {
        // DevExtreme bazen string tipinde formatter'ı çağırmaz
        // Bu yüzden her durumda çalışması için customizeText ekleyeceğiz
        col.dataType = 'string'

        const formatter = (value: any) => {
          if (!value) return ''

          // string'e dönüştür ve sadece rakamları al
          let digits = String(value).replace(/\D/g, '')

          // +90, 0090, 0 gibi ülke kodu veya ön ekleri atla
          if (digits.startsWith('90') && digits.length > 10) digits = digits.slice(-10)
          if (digits.startsWith('0') && digits.length > 10) digits = digits.slice(-10)
          if (digits.length > 10) digits = digits.slice(-10)

          // 🔒 Eğer 10 haneli değilse geçersiz → boş göster
          if (digits.length !== 10) return ''

          // (XXX) XXX-XXXX formatında göster
          const match = digits.match(/^(\d{3})(\d{3})(\d{4})$/)
          return match ? `(${match[1]}) ${match[2]}-${match[3]}` : digits
        }

        // 1️⃣ Normal format nesnesi
        col.format = { formatter }

        // 2️⃣ CustomizeText fallback — bazı durumlarda zorunlu
        col.customizeText = (cellInfo: any) => formatter(cellInfo?.value)
      }
    })

    setColumnData(cols)
  }, [gridDto, config])

  // DataSource oluştur
  useEffect(() => {
    if (!gridDto) return

    const dataSource = createSelectDataSource(
      gridDto.gridOptions,
      listFormCode,
      searchParams,
      layoutTypes.grid,
      columnData,
    )

    setGridDataSource(dataSource)
  }, [gridDto, searchParams])

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

    refListFormCode.current = listFormCode
    if (!gridRef?.current) {
      return
    }

    const instance = gridRef?.current?.instance()
    if (instance) {
      instance.option('columns', columnData)
      instance.option('remoteOperations', {
        groupPaging: true,
        filtering: true,
        sorting: true,
        paging: true,
        grouping: true,
        summary: true,
      })
      instance.option('dataSource', gridDataSource)
      instance.state(null)

      const stateStoring: IStateStoringProps = {
        enabled: gridDto?.gridOptions.stateStoringDto?.enabled,
        type: gridDto?.gridOptions.stateStoringDto?.type,
        savingTimeout: gridDto?.gridOptions.stateStoringDto?.savingTimeout,
        storageKey: gridDto?.gridOptions.stateStoringDto?.storageKey,
      }
      if (
        gridDto?.gridOptions.stateStoringDto?.enabled &&
        gridDto?.gridOptions.stateStoringDto?.type === 'custom'
      ) {
        stateStoring.customSave = customSaveState
        stateStoring.customLoad = customLoadState
      }
      instance.option('stateStoring', stateStoring)
    }
  }, [columnData])

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

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

    // Default filter tripletlerini çıkar
    const baseTriplets = extractSearchParamsFields(base)

    // Extra filter tripletleri hazırla
    const extraTriplets = activeFilters.map(
      (f) => [f.fieldName, f.operator, f.value] as [string, string, any],
    )

    // Tripletleri birleştir, aynı field+op varsa sonuncuyu al
    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 // varsa üzerine yaz
        } else {
          acc.push(cur)
        }
        return acc
      },
      [] as [string, string, any][],
    )

    // Tek filtre varsa direkt yaz
    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(() => {
    refListFormCode.current = listFormCode
  }, [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])

  const onExporting = async (e: DataGridTypes.ExportingEvent) => {
    // DevExtreme’in varsayılan export davranışını iptal ediyoruz; kendi akışımızı çalıştıracağız
    e.cancel = true

    const grid = gridRef?.current?.instance()
    if (!grid) return

    try {
      if (e.format === 'xlsx' || e.format === 'csv') {
        // exceljs + file-saver + devextreme excel exporter => ihtiyaç anında yükle
        const [{ Workbook }, { saveAs }, { exportDataGrid: exportDataExcel }] = await Promise.all([
          import('exceljs'),
          import('file-saver'),
          import('devextreme/excel_exporter'),
        ])

        const workbook = new Workbook()
        const worksheet = workbook.addWorksheet(`${listFormCode}_sheet`)

        await exportDataExcel({
          component: grid as any,
          worksheet,
          autoFilterEnabled: true,
        })

        if (e.format === 'xlsx') {
          const buffer = await workbook.xlsx.writeBuffer()
          saveAs(
            new Blob([buffer], { type: 'application/octet-stream' }),
            `${listFormCode}_export.xlsx`,
          )
        } else {
          const buffer = await workbook.csv.writeBuffer()
          saveAs(
            new Blob([buffer], { type: 'application/octet-stream' }),
            `${listFormCode}_export.csv`,
          )
        }
      } else if (e.format === 'pdf') {
        // jspdf + devextreme pdf exporter => ihtiyaç anında yükle
        const [jspdfMod, { exportDataGrid: exportDataPdf }] = await Promise.all([
          import('jspdf'),
          import('devextreme/pdf_exporter'),
        ])

        // jsPDF bazı paketlemelerde default, bazılarında named export olarak gelir
        const JsPDFCtor = (jspdfMod as any).default ?? (jspdfMod as any).jsPDF
        const doc = new JsPDFCtor({})

        await exportDataPdf({
          jsPDFDocument: doc,
          component: grid as any,
          indent: 5,
        })

        doc.save(`${listFormCode}_export.pdf`)
      }
    } catch (err) {
      console.error('Export error:', err)
      toast.push(
        <Notification type="danger" duration={2500}>
          {translate('::App.Common.ExportError') ?? 'Dışa aktarma sırasında hata oluştu.'}
        </Notification>,
        { placement: 'top-end' },
      )
    }
  }

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

      <Container className={DX_CLASSNAMES}>
        {!isSubForm && (
          <Helmet
            titleTemplate="%s | Erp Platform"
            title={translate('::' + gridDto?.gridOptions.title)}
            defaultTitle="Erp Platform"
          ></Helmet>
        )}
        {!gridDto && (
          <div className="p-4">
            <Loading loading>Loading grid configuration...</Loading>
          </div>
        )}
        {gridDto && !columnData && (
          <div className="p-4">
            <Loading loading>Loading columns...</Loading>
          </div>
        )}
        {gridDto && columnData && !gridDataSource && (
          <div className="p-4">
            <Loading loading>Loading data source...</Loading>
          </div>
        )}
        {gridDto &&
          columnData &&
          gridDataSource &&
          (() => {
            return true
          })() && (
            <>
              <div className="p-1">
                <DataGrid
                  ref={gridRef as any}
                  key={`Grid-${listFormCode}-${gridDataSource ? 'loaded' : 'loading'}`}
                  id={'Grid-' + listFormCode}
                  // dataSource={gridDataSource}
                  // columns={columnData}
                  // remoteOperations={{
                  //   groupPaging: true,
                  //   filtering: true,
                  //   sorting: true,
                  //   paging: true,
                  //   grouping: true,
                  //   summary: true,
                  // }}
                  height={
                    gridDto.gridOptions.height > 0
                      ? gridDto.gridOptions.height
                      : gridDto.gridOptions.fullHeight
                        ? `calc(100vh - ${170 + widgetGroupHeight}px)`
                        : undefined
                  }
                  width={gridDto.gridOptions.width || '100%'}
                  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}
                  onExporting={onExporting}
                  onEditCanceling={() => {
                    setMode('view')
                  }}
                  onEditCanceled={() => {
                    isEditingRef.current = false
                    setMode('view')
                    setIsPopupFullScreen(false)
                  }}
                  onSaved={() => {
                    isEditingRef.current = false
                    setMode('view')
                    setIsPopupFullScreen(false)
                  }}
                  onRowInserted={() => {
                    props.refreshData?.()
                  }}
                  onRowUpdated={() => {
                    props.refreshData?.()
                  }}
                  onRowRemoved={() => {
                    props.refreshData?.()
                  }}
                  onEditorPreparing={onEditorPreparing}
                >
                  <Export
                    enabled={gridDto.gridOptions.exportDto?.enabled}
                    allowExportSelectedData={gridDto.gridOptions.exportDto?.allowExportSelectedData}
                    formats={['pdf', 'xlsx', 'csv']}
                  />
                  <Editing
                    refreshMode={gridDto.gridOptions.editingOptionDto?.refreshMode}
                    mode={smaller.md ? 'form' : 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}
                    newRowPosition={gridDto.gridOptions.editingOptionDto?.newRowPosition}
                    selectTextOnEditStart={
                      gridDto.gridOptions.editingOptionDto?.selectTextOnEditStart
                    }
                    startEditAction={gridDto.gridOptions.editingOptionDto?.startEditAction}
                    popup={{
                      animation: {},
                      title:
                        (mode === 'new' ? '✚ ' : '🖊️ ') +
                        translate('::' + gridDto.gridOptions.editingOptionDto?.popup?.title),
                      showTitle: gridDto.gridOptions.editingOptionDto?.popup?.showTitle,
                      hideOnOutsideClick:
                        gridDto.gridOptions.editingOptionDto?.popup?.hideOnOutsideClick,
                      width: gridDto.gridOptions.editingOptionDto?.popup?.width,
                      height: gridDto.gridOptions.editingOptionDto?.popup?.height,
                      resizeEnabled: gridDto.gridOptions.editingOptionDto?.popup?.resizeEnabled,
                      fullScreen: isPopupFullScreen,
                      toolbarItems: [
                        {
                          widget: 'dxButton',
                          toolbar: 'bottom',
                          location: 'after',
                          options: {
                            text: translate('::Save'),
                            type: 'default',
                            onClick: () => {
                              const grid = gridRef.current?.instance()
                              grid?.saveEditData()
                            },
                          },
                        },
                        {
                          widget: 'dxButton',
                          toolbar: 'bottom',
                          location: 'after',
                          options: {
                            text: translate('::Cancel'),
                            onClick: () => {
                              const grid = gridRef.current?.instance()
                              grid?.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,
                      onFieldDataChanged: (e) => {
                        if (e.dataField) {
                          const formItem = gridDto.gridOptions.editingFormDto
                            .flatMap((group) => group.items || [])
                            .find((i) => i.dataField === e.dataField)
                          if (formItem?.editorScript) {
                            try {
                              eval(formItem.editorScript)
                            } 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 = {}
                                try {
                                  editorOptions = i.editorOptions && JSON.parse(i.editorOptions)

                                  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 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) {
                                        editorOptions = {
                                          ...editorOptions,
                                          readOnly: true,
                                        }
                                      }
                                    }
                                  }
                                } catch {}

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

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

                                // Set defaultValue for @AUTONUMBER fields
                                if (
                                  typeof listFormField?.defaultValue === 'string' &&
                                  listFormField?.defaultValue === '@AUTONUMBER' &&
                                  mode === 'new'
                                ) {
                                  editorOptions = {
                                    ...editorOptions,
                                    value: autoNumber(),
                                  }
                                }

                                const item: SimpleItemWithColData = {
                                  canRead: listFormField?.canRead ?? false,
                                  canUpdate: listFormField?.canUpdate ?? false,
                                  canCreate: listFormField?.canCreate ?? false,
                                  canExport: listFormField?.canExport ?? false,
                                  dataField: i.dataField,
                                  name: i.dataField,
                                  editorType2: i.editorType2,
                                  editorType:
                                    i.editorType2 == PlatformEditorTypes.dxGridBox
                                      ? 'dxDropDownBox'
                                      : i.editorType2,
                                  colSpan: i.colSpan,
                                  isRequired: i.isRequired,
                                  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') {
                                  // Backend'den gelen colCount ve colSpan değerlerini kullan
                                  const effectiveColCount = e.colCount || 1
                                  const effectiveColSpan = e.colSpan || 1

                                  result.push({
                                    itemType: e.itemType,
                                    colCount: effectiveColCount,
                                    colSpan: effectiveColSpan,
                                    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.canRead
                                        } else if (mode === 'edit') {
                                          return a.canUpdate || a.canRead
                                        } 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.canRead
                                            } else if (mode === 'edit') {
                                              return a.canUpdate || a.canRead
                                            } 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 || filterToolbarData.length > 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>
                  <GroupPanel
                    visible={gridDto.gridOptions.groupPanelDto?.visible}
                    emptyPanelText={translate('::App.GroupPanel.EmptyPanelText')}
                  ></GroupPanel>
                  <Grouping
                    autoExpandAll={gridDto.gridOptions.groupPanelDto?.autoExpandAll}
                  ></Grouping>
                  <Selection
                    mode={gridDto.gridOptions.selectionDto?.mode}
                    allowSelectAll={gridDto.gridOptions.selectionDto?.allowSelectAll}
                    selectAllMode={gridDto.gridOptions.selectionDto?.selectAllMode}
                    showCheckBoxesMode={gridDto.gridOptions.selectionDto?.showCheckBoxesMode}
                  ></Selection>
                  <Paging defaultPageSize={gridDto.gridOptions.pageSize ?? 20} />
                  <Pager
                    visible={gridDto.gridOptions.pagerOptionDto?.visible}
                    allowedPageSizes={gridDto.gridOptions.pagerOptionDto?.allowedPageSizes
                      ?.split(',')
                      .map((a: any) => +a)}
                    showPageSizeSelector={gridDto.gridOptions.pagerOptionDto?.showPageSizeSelector}
                    showInfo={false}
                    showNavigationButtons={
                      gridDto.gridOptions.pagerOptionDto?.showNavigationButtons
                    }
                    displayMode={gridDto.gridOptions.pagerOptionDto?.displayMode}
                  ></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>
                  <Summary>
                    {gridDto.columnFormats
                      .filter((x: any) => !!x.columnTotalSummaryDto?.summaryType)
                      .map((x: any) => (
                        <TotalItem
                          key={`Total_${x.fieldName}`}
                          column={x.fieldName}
                          summaryType={x.columnTotalSummaryDto.summaryType as any}
                          showInColumn={x.columnTotalSummaryDto.showInColumn}
                          valueFormat={x.columnTotalSummaryDto.valueFormat}
                          displayFormat={x.columnTotalSummaryDto.displayFormat}
                        />
                      ))}
                    {gridDto.columnFormats
                      .filter((x: any) => !!x.columnGroupSummaryDto?.summaryType)
                      .map((x: any) => (
                        <GroupItemDx
                          key={`Group_${x.fieldName}`}
                          column={x.fieldName}
                          summaryType={x.columnGroupSummaryDto.summaryType as any}
                          showInColumn={x.columnGroupSummaryDto.showInColumn}
                          valueFormat={x.columnGroupSummaryDto.valueFormat}
                          displayFormat={x.columnGroupSummaryDto.displayFormat}
                        />
                      ))}
                  </Summary>
                </DataGrid>

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

                <Dialog
                  width={smaller.md ? '100%' : 1000}
                  isOpen={filterData.isImportModalOpen || false}
                  onClose={() => filterData.setIsImportModalOpen(false)}
                  onRequestClose={() => filterData.setIsImportModalOpen(false)}
                >
                  <ImportDashboard gridDto={gridDto} />
                </Dialog>
              </div>
            </>
          )}

        <Dialog
          isOpen={toolbarModalData?.open || false}
          onClose={() => setToolbarModalData(undefined)}
          onRequestClose={() => setToolbarModalData(undefined)}
        >
          {toolbarModalData?.content}
        </Dialog>
        <GridFilterDialogs gridRef={gridRef} listFormCode={listFormCode} {...filterData} />
      </Container>
    </>
  )
}

export default Grid
