import Container from '@/components/shared/Container'
import { APP_NAME, DX_CLASSNAMES } from '@/constants/app.constant'
import { GridDto, ListFormCustomizationTypeEnum } from '@/proxy/form/models'
import {
  getListFormCustomization,
  postListFormCustomization,
} from '@/services/list-form-customization.service'
import { useLocalization } from '@/utils/hooks/useLocalization'
import Chart, { ChartRef, CommonSeriesSettings, Size, Tooltip } from 'devextreme-react/chart'
import PivotGrid, {
  Export,
  FieldChooser,
  FieldPanel,
  HeaderFilter,
  LoadPanel,
  PivotGridRef,
  PivotGridTypes,
  Scrolling,
  Search,
} from 'devextreme-react/pivot-grid'
import CustomStore from 'devextreme/data/custom_store'
import { Field } from 'devextreme/ui/pivot_grid/data_source'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { Helmet } from 'react-helmet'
import { GridColumnData } from './GridColumnData'
import {
  addCss,
  addJs,
  controlStyleCondition,
  pivotFieldConvertDataType,
  setGridPanelColor,
} from './Utils'
import { useFilters } from './useFilters'
import WidgetGroup from '@/components/common/WidgetGroup'
import { Button, Dropdown, Notification, toast } from '@/components/ui'
import { FaCaretDown, FaCog, FaSave, FaTimes, FaUndo } from 'react-icons/fa'
import { usePermission } from '@/utils/hooks/usePermission'
import { ROUTES_ENUM } from '@/routes/route.constant'
import { usePWA } from '@/utils/hooks/usePWA'
import { layoutTypes } from '../admin/listForm/edit/types'
import { useListFormCustomDataSource } from './useListFormCustomDataSource'
import { useListFormColumns } from './useListFormColumns'
import { useStoreState } from '@/store'
import Checkbox from '@/components/ui/Checkbox'

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

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

const Pivot = (props: PivotProps) => {
  const { listFormCode, searchParams, isSubForm, level, gridDto } = props
  const { translate } = useLocalization()
  const { checkPermission } = usePermission()
  const isPwaMode = usePWA()

  const gridRef = useRef<PivotGridRef>()
  const chartRef = useRef<ChartRef>(null)
  const refListFormCode = useRef('')
  const config = useStoreState((state) => state.abpConfig.config)

  const [gridDataSource, setGridDataSource] = useState<CustomStore<any, any>>()
  const [columnData, setColumnData] = useState<GridColumnData[]>()
  const [showChart, setShowChart] = useState(false)

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

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

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

  const onCellPrepared = useCallback(
    (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,
                  )
                }
              }
            }
          }
        }
      }
    },
    [gridDto],
  )

  const clearPivotFilters = useCallback(() => {
    const grid = gridRef.current?.instance()
    if (!grid) return

    const ds = grid.getDataSource()
    if (ds) {
      const fields = ds.fields()
      fields.forEach((f: any) => {
        f.filterValues = undefined
        f.filterType = undefined
      })
      ds.reload()
    }
  }, [])

  const moveAllFieldsToFilterArea = useCallback(() => {
    const grid = gridRef.current?.instance()
    if (!grid) return

    const ds = grid.getDataSource()
    if (!ds) return

    const fields = ds.fields()

    fields.forEach((field: any) => {
      field.area = 'filter' // tüm alanları filtre alanına taşı
      field.areaIndex = undefined
    })

    ds.fields(fields)
    ds.reload() // PivotGrid’i yeniden yükle
    grid.repaint() // UI güncelle
  }, [])

  const resetPivotGridState = useCallback(async () => {
    const grid = gridRef.current?.instance()
    if (grid) {
      // State'i veritabanından sil
      await postListFormCustomization({
        listFormCode: listFormCode,
        customizationType: ListFormCustomizationTypeEnum.GridState,
        filterName: `pivot-${storageKey}`,
        customizationData: '',
      })

      // DataSource'u resetle
      const ds = grid.getDataSource()
      if (ds && typeof ds.state === 'function') {
        ds.state(null) // State'i temizle
      }

      // Filtreleri temizle
      clearPivotFilters()
      setGridPanelColor('transparent')

      toast.push(
        <Notification type="success" duration={2000}>
          {translate('::ListForms.ListForm.GridStateReset')}
        </Notification>,
        { placement: 'top-end' },
      )
    }
  }, [listFormCode, storageKey, clearPivotFilters, translate])

  const onExporting = useCallback(
    async (e: PivotGridTypes.ExportingEvent) => {
      e.cancel = true

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

      try {
        // PivotGrid sadece Excel export destekliyor
        const [{ Workbook }, { saveAs }, { exportPivotGrid }] = await Promise.all([
          import('exceljs'),
          import('file-saver'),
          import('devextreme/excel_exporter'),
        ])

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

        await exportPivotGrid({
          component: pivot as any,
          worksheet,
        })

        const buffer = await workbook.xlsx.writeBuffer()
        saveAs(
          new Blob([buffer], { type: 'application/octet-stream' }),
          `${listFormCode}_pivot_export.xlsx`,
        )
      } catch (err) {
        console.error('Pivot 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' },
        )
      }
    },
    [listFormCode, translate],
  )

  // StateStoring fonksiyonlarını ref'e kaydet
  const customSaveState = useCallback(
    (state: any) => {
      return postListFormCustomization({
        listFormCode: listFormCode,
        customizationType: ListFormCustomizationTypeEnum.GridState,
        filterName: `pivot-${storageKey}`,
        customizationData: JSON.stringify(state),
      }).then(() => {
        setGridPanelColor(statedGridPanelColor)
      })
    },
    [listFormCode, storageKey],
  )

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

  useEffect(() => {
    refListFormCode.current = listFormCode
  }, [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)
      }
    }

    // Set initial chart visibility
    setShowChart(gridDto.gridOptions.pivotOptionDto.showChart ?? false)
  }, [gridDto])

  // Kolonları memoize et
  const memoizedColumns = useMemo(() => {
    if (!gridDto || !config) return undefined

    const cols = getBandedColumns()
    return cols?.filter((a) => a.colData?.pivotSettingsDto.isPivot)
  }, [gridDto, config])

  // DataSource'u memoize et
  const memoizedDataSource = useMemo(() => {
    if (!gridDto) return undefined

    const cols = getBandedColumns()
    return createSelectDataSource(
      gridDto.gridOptions,
      listFormCode,
      searchParams,
      layoutTypes.pivot,
      cols,
    )
  }, [gridDto, listFormCode, createSelectDataSource])

  useEffect(() => {
    if (memoizedColumns) {
      setColumnData(memoizedColumns)
    }
  }, [memoizedColumns])

  useEffect(() => {
    if (memoizedDataSource) {
      setGridDataSource(memoizedDataSource)
    }
  }, [memoizedDataSource])

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

    const instance = gridRef?.current?.instance()
    if (instance) {
      instance.option('stateStoring', {
        enabled: false,
      })
    }
  }, [gridDto])

  // Pivot dataSource ve fields'i set et
  useEffect(() => {
    if (!columnData || !gridDataSource || !gridRef?.current || !gridDto) {
      return
    }

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

    // Default fields'i hazırla
    const defaultFields: any = columnData?.map((b) => {
      return {
        dataField: b.dataField,
        caption: b.caption,
        dataType: pivotFieldConvertDataType(b.dataType),
        area: b.colData?.pivotSettingsDto.area,
        format: b.colData?.pivotSettingsDto.format,
        summaryType: b.colData?.pivotSettingsDto.summaryType,
        groupInterval: b.colData?.pivotSettingsDto.groupInterval,
        sortOrder: b.colData?.pivotSettingsDto.sortOrder,
        expanded: b.colData?.pivotSettingsDto.expanded,
        wordWrapEnabled: b.colData?.pivotSettingsDto.wordWrapEnabled,
        visible: true,
        width: b.width,
      } as Field
    })

    // DataSource'u ayarla
    const dataSource: PivotGridTypes.Properties['dataSource'] = {
      remoteOperations: true,
      store: gridDataSource,
      fields: defaultFields,
    }

    instance.option('dataSource', dataSource)
  }, [columnData, gridDataSource, gridDto])

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

    const instance = gridRef?.current?.instance()
    if (instance) {
      customLoadState()
        .then((state) => {
          if (state) {
            const ds = instance.getDataSource()
            if (ds && typeof ds.state === 'function') {
              ds.state(state)
            }
          }
        })
        .catch((err) => {
          console.error('Pivot state load error:', err)
        })
    }
  }, [gridDto, columnData, gridDataSource, customLoadState])

  // Chart binding - showChart değiştiğinde de çalışmalı
  useEffect(() => {
    if (!showChart || !gridRef?.current || !chartRef?.current) return

    const pivotInstance = gridRef?.current?.instance()
    const chartInstance = chartRef?.current?.instance()
    if (pivotInstance && chartInstance) {
      pivotInstance.bindChart(chartInstance, {
        dataFieldsDisplayMode: 'splitPanes',
        alternateDataFields: false,
      })
    }
  }, [showChart, gridDto])

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

      <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 ">
            <div className="flex justify-end items-center text-black">
              <div className="relative flex gap-1">
                <label className="flex items-center gap-1 text-xs cursor-pointer dark:text-white">
                  <span>{translate('::ListForms.ListFormEdit.ShowChart')}</span>
                  <Checkbox checked={showChart} onChange={(checked) => setShowChart(checked)} />
                </label>
                <div className="dx-menu">
                  <Dropdown
                    placement="bottom-end"
                    renderTitle={
                      <Button
                        size="sm"
                        variant={'plain'}
                        className="text-sm flex items-center gap-1 border-0"
                        title="Menu"
                      >
                        <i className="dx-icon dx-icon-overflow" style={{ fontSize: '17px' }}></i>
                        <span className="text-black dark:text-white" style={{ fontSize: '13px' }}>
                          {translate('::ListForms.ListForm.GridMenu')}
                        </span>
                        <FaCaretDown className="ml-2 w-2 h-3" />
                      </Button>
                    }
                  >
                    <Dropdown.Item
                      eventKey="removeFilter"
                      onClick={clearPivotFilters}
                      className="px-2"
                    >
                      <span className="flex items-center gap-2">
                        <FaTimes className="w-3 h-3" />
                        <span>{translate('::ListForms.ListForm.RemoveFilter')}</span>
                      </span>
                    </Dropdown.Item>

                    <Dropdown.Item
                      eventKey="saveGridState"
                      onClick={() => {
                        const instance = gridRef.current?.instance()
                        if (instance) {
                          const ds = instance.getDataSource()
                          if (ds && typeof ds.state === 'function') {
                            const currentState = ds.state()
                            customSaveState(currentState)
                              .then(() => {
                                toast.push(
                                  <Notification type="success" duration={2000}>
                                    {translate('::ListForms.ListForm.GridStateSaved')}
                                  </Notification>,
                                  { placement: 'top-end' },
                                )
                              })
                              .catch(() => {
                                toast.push(
                                  <Notification type="danger" duration={2500}>
                                    {translate('::ListForms.ListForm.GridStateSaveError')}
                                  </Notification>,
                                  { placement: 'top-end' },
                                )
                              })
                          }
                        }
                      }}
                      className="px-2"
                    >
                      <span className="flex items-center gap-2">
                        <FaSave className="w-3 h-3" />
                        <span>{translate('::ListForms.ListForm.SaveGridState')}</span>
                      </span>
                    </Dropdown.Item>

                    <Dropdown.Item
                      eventKey="resetGridState"
                      onClick={resetPivotGridState}
                      className="px-2"
                    >
                      <span className="flex items-center gap-2">
                        <FaUndo className="w-3 h-3" />
                        <span>{translate('::ListForms.ListForm.ResetGridState')}</span>
                      </span>
                    </Dropdown.Item>

                    {checkPermission(gridDto?.gridOptions.permissionDto.u) && (
                      <Dropdown.Item
                        eventKey="formManager"
                        onClick={() => {
                          window.open(
                            ROUTES_ENUM.protected.saas.listFormManagement.edit.replace(
                              ':listFormCode',
                              listFormCode,
                            ),
                            isPwaMode ? '_self' : '_blank',
                          )
                        }}
                        className="px-2"
                      >
                        <span className="flex items-center gap-2">
                          <FaCog className="w-3 h-3" />
                          <span>{translate('::ListForms.ListForm.Manage')}</span>
                        </span>
                      </Dropdown.Item>
                    )}
                  </Dropdown>
                </div>
              </div>
            </div>
            {showChart && (
              <Chart ref={chartRef as any}>
                <Size height={gridDto.gridOptions.pivotOptionDto.chartHeight} />
                <Tooltip enabled={true}></Tooltip>
                <CommonSeriesSettings
                  type={gridDto.gridOptions.pivotOptionDto.chartCommonSeriesType}
                />
              </Chart>
            )}

            <div className="dx-datagrid-header-panel h-1"></div>

            <PivotGrid
              ref={gridRef as any}
              id={'Pivot-' + listFormCode}
              allowFiltering={gridDto.gridOptions.filterRowDto.visible}
              allowSorting={gridDto.gridOptions.sortMode !== 'none'}
              allowSortingBySummary={gridDto.gridOptions.sortMode !== 'none'}
              height={gridDto.gridOptions.height || '100%'}
              width={gridDto.gridOptions.width || '100%'}
              showBorders={gridDto.gridOptions.columnOptionDto?.showBorders}
              rtlEnabled={gridDto.gridOptions.columnOptionDto?.rtlEnabled}
              hoverStateEnabled={gridDto.gridOptions.columnOptionDto?.hoverStateEnabled}
              onCellPrepared={onCellPrepared}
              onExporting={onExporting}
            >
              <Export enabled={gridDto.gridOptions.exportDto?.enabled} />
              <HeaderFilter
                allowSelectAll={gridDto.gridOptions.selectionDto.allowSelectAll}
                width={gridDto.gridOptions.headerFilterDto.width}
                height={gridDto.gridOptions.headerFilterDto.height}
              >
                <Search
                  enabled={gridDto.gridOptions.headerFilterDto.allowSearch}
                  timeout={gridDto.gridOptions.headerFilterDto.searchTimeout}
                ></Search>
              </HeaderFilter>
              <FieldPanel
                allowFieldDragging={gridDto.gridOptions.pivotOptionDto.allowFieldDragging}
                visible={gridDto.gridOptions.pivotOptionDto.showFieldPanel}
                showDataFields={gridDto.gridOptions.pivotOptionDto.showDataFields}
                showColumnFields={gridDto.gridOptions.pivotOptionDto.showColumnFields}
                showRowFields={gridDto.gridOptions.pivotOptionDto.showRowFields}
                showFilterFields={gridDto.gridOptions.pivotOptionDto.showFilterFields}
              />
              <FieldChooser
                enabled={gridDto.gridOptions.pivotOptionDto.columnChooserEnabled}
                height={500}
              />
              <LoadPanel
                enabled={
                  gridDto.gridOptions.pagerOptionDto?.loadPanelEnabled as boolean | undefined
                }
                text={gridDto.gridOptions.pagerOptionDto?.loadPanelText}
              />
              <Scrolling mode={gridDto.gridOptions.pagerOptionDto.scrollingMode} />
            </PivotGrid>
          </div>
        )}
      </Container>
    </>
  )
}

export default Pivot
