import Container from '@/components/shared/Container'
import { DX_CLASSNAMES } from '@/constants/app.constant'
import { GridDto, PlatformEditorTypes, UiLookupDataSourceTypeEnum } from '@/proxy/form/models'
import { useLocalization } from '@/utils/hooks/useLocalization'
import Scheduler, {
  Editing,
  Item,
  Resource,
  SchedulerRef,
  Toolbar,
  View,
} from 'devextreme-react/scheduler'
import { useCallback, useEffect, useRef, useState } from 'react'
import { Helmet } from 'react-helmet'
import { getList } from '@/services/form.service'
import { useListFormCustomDataSource } from './useListFormCustomDataSource'
import { addCss, addJs } from './Utils'
import { layoutTypes } from '../admin/listForm/edit/types'
import WidgetGroup from '@/components/ui/Widget/WidgetGroup'
import { ROUTES_ENUM } from '@/routes/route.constant'
import { usePWA } from '@/utils/hooks/usePWA'
import CustomStore from 'devextreme/data/custom_store'
import { Loading } from '@/components/shared'
import { usePermission } from '@/utils/hooks/usePermission'
import { useListFormColumns } from './useListFormColumns'
import { EditingFormItemDto } from '@/proxy/form/models'
import useResponsive from '@/utils/hooks/useResponsive'
import { SimpleItemWithColData } from '../form/types'

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

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

  const schedulerRef = useRef<SchedulerRef>()
  const refListFormCode = useRef('')
  const widgetGroupRef = useRef<HTMLDivElement>(null)
  const { checkPermission } = usePermission()
  const { smaller } = useResponsive()

  const [schedulerDataSource, setSchedulerDataSource] = useState<CustomStore<any, any>>()
  const [gridDto, setGridDto] = useState<GridDto>()
  const [widgetGroupHeight, setWidgetGroupHeight] = useState(0)
  const [currentView, setCurrentView] = useState<string>('week')
  const [isPopupFullScreen, setIsPopupFullScreen] = useState(false)
  const layout = layoutTypes.scheduler || 'scheduler'

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

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

    setCurrentView(extGridDto?.gridOptions.schedulerOptionDto?.defaultView || 'week')
  }, [listFormCode, extGridDto])

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

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

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

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

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

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

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

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

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

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

    calculateWidgetHeight()

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

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

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

  const handleRefresh = useCallback(() => {
    const instance = schedulerRef.current?.instance()
    if (instance) {
      const dataSource = instance.getDataSource()
      if (dataSource) {
        dataSource.reload()
      }
    }
  }, [])

  const onCurrentViewChange = useCallback((value: string) => {
    setCurrentView(value)
  }, [])

  const onAppointmentFormOpening = useCallback(
    (e: any) => {
      if (!gridDto) return

      // Popup ayarlarını her açılışta yeniden yapılandır
      e.popup.option('title', translate('::' + gridDto.gridOptions.editingOptionDto?.popup?.title))
      e.popup.option('showTitle', gridDto.gridOptions.editingOptionDto?.popup?.showTitle)
      e.popup.option('width', gridDto.gridOptions.editingOptionDto?.popup?.width || 800)
      e.popup.option('height', gridDto.gridOptions.editingOptionDto?.popup?.height || 600)
      e.popup.option('resizeEnabled', gridDto.gridOptions.editingOptionDto?.popup?.resizeEnabled)
      e.popup.option('fullScreen', isPopupFullScreen)

      // Toolbar butonlarını ekle
      const toolbarItems = [
        {
          widget: 'dxButton',
          toolbar: 'bottom',
          location: 'after',
          options: {
            text: translate('::Save'),
            type: 'default',
            onClick: async () => {
              const formInstance = e.form
              const validationResult = formInstance.validate()

              if (validationResult.isValid) {
                // Form verilerini al
                const formData = formInstance.option('formData')

                try {0
                  // Scheduler instance'ını al
                  const scheduler = schedulerRef.current?.instance()

                  if (e.appointmentData && scheduler) {
                    // Yeni appointment mı yoksa güncelleme mi kontrol et
                    if (
                      e.appointmentData.id ||
                      e.appointmentData[gridDto.gridOptions.keyFieldName || 'id']
                    ) {
                      // Güncelleme
                      await scheduler.updateAppointment(e.appointmentData, formData)
                    } else {
                      // Yeni ekleme
                      await scheduler.addAppointment(formData)
                    }

                    // Popup'ı kapat
                    e.popup.hide()

                    // RefreshData varsa çağır
                    if (props.refreshData) {
                      await props.refreshData()
                    }
                  }
                } catch (error) {
                  console.error('Appointment save error:', error)
                }
              }
            },
          },
        },
        {
          widget: 'dxButton',
          toolbar: 'bottom',
          location: 'after',
          options: {
            text: translate('::Cancel'),
            onClick: () => {
              e.cancel = true
              e.popup.hide()
            },
          },
        },
        {
          widget: 'dxButton',
          toolbar: 'top',
          location: 'after',
          options: {
            icon: 'fullscreen',
            hint: translate('::Tam Ekran'),
            stylingMode: 'text',
            onClick: () => {
              // Popup'tan mevcut fullScreen durumunu al
              const currentFullScreen = e.popup.option('fullScreen')
              const newFullScreenState = !currentFullScreen
              
              // State'i güncelle
              setIsPopupFullScreen(newFullScreenState)
              
              // Popup'ı güncelle
              e.popup.option('fullScreen', newFullScreenState)
              
              // Width ve height'i da güncelle
              if (newFullScreenState) {
                e.popup.option('width', '100%')
                e.popup.option('height', '100%')
              } else {
                e.popup.option('width', gridDto.gridOptions.editingOptionDto?.popup?.width || 600)
                e.popup.option('height', gridDto.gridOptions.editingOptionDto?.popup?.height || 'auto')
              }
              
              // Button icon ve hint'i güncelle
              const button = e.popup._$element.find('.dx-toolbar-after .dx-button').last()
              if (button.length) {
                const buttonInstance = button.dxButton('instance')
                if (buttonInstance) {
                  buttonInstance.option('icon', newFullScreenState ? 'collapse' : 'fullscreen')
                  buttonInstance.option('hint', newFullScreenState ? translate('::Normal Boyut') : translate('::Tam Ekran'))
                }
              }
            },
          },
        },
      ]

      e.popup.option('toolbarItems', toolbarItems)

      // EditingFormDto'dan form items oluştur
      const formItems: any[] = []

      if (gridDto.gridOptions.editingFormDto?.length > 0) {
        const sortedFormDto = gridDto.gridOptions.editingFormDto
          .slice()
          .sort((a: any, b: any) => (a.order >= b.order ? 1 : -1))

        sortedFormDto.forEach((group: any) => {
          // Items'ları da order'a göre sırala
          const sortedItems = (group.items || [])
            .slice()
            .sort((a: any, b: any) => (a.order >= b.order ? 1 : -1))
          
          const groupItems = sortedItems.map((i: EditingFormItemDto) => {
            let editorOptions: any = {}
            try {
              if (i.editorOptions) {
                editorOptions = JSON.parse(i.editorOptions)
              }
            } catch {}

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

            // EditorType belirleme - Grid'deki gibi
            let editorType: any = i.editorType2 || i.editorType
            if (i.editorType2 === PlatformEditorTypes.dxGridBox) {
              editorType = 'dxDropDownBox'
            } else if (i.editorType2) {
              editorType = i.editorType2
            }

            // Lookup DataSource oluştur
            if (listFormField?.lookupDto) {
              const lookup = listFormField.lookupDto

              // EditorType'ı dxSelectBox olarak ayarla
              if (!editorType || editorType === 'dxTextBox') {
                editorType = 'dxSelectBox'
              }

              if (lookup.dataSourceType === UiLookupDataSourceTypeEnum.Query) {
                editorOptions.dataSource = new CustomStore({
                  key: 'key',
                  loadMode: 'raw',
                  load: async () => {
                    try {
                      const { dynamicFetch } = await import('@/services/form.service')
                      const response = await dynamicFetch('list-form-select/lookup', 'POST', null, {
                        listFormCode,
                        listFormFieldName: fieldName,
                        filters: [],
                      })
                      return (response.data ?? []).map((a: any) => ({
                        key: a.Key,
                        name: a.Name,
                        group: a.Group,
                      }))
                    } catch (error) {
                      console.error('Lookup load error:', error)
                      return []
                    }
                  },
                })

                editorOptions.valueExpr = 'key'
                editorOptions.displayExpr = 'name'
              } else if (lookup.dataSourceType === UiLookupDataSourceTypeEnum.StaticData) {
                if (lookup.lookupQuery) {
                  try {
                    const staticData = JSON.parse(lookup.lookupQuery)
                    editorOptions.dataSource = staticData
                    editorOptions.valueExpr = lookup.valueExpr || 'key'
                    editorOptions.displayExpr = lookup.displayExpr || 'name'
                  } catch (error) {
                    console.error('Static data parse error:', error)
                  }
                }
              }
            }

            // Validation rules
            const validationRules: any[] = []
            if (i.isRequired) {
              validationRules.push({ type: 'required' })
            }

            const item: any = {
              dataField: i.dataField,
              name: i.dataField,
              editorType,
              colSpan: i.colSpan,
              editorOptions,
              validationRules: validationRules.length > 0 ? validationRules : undefined,
            }

            // Label sadece caption varsa ekle
            if (listFormField?.captionName) {
              item.label = { text: translate('::' + listFormField.captionName) }
            }

            return item
          })

          if (group.itemType === 'group') {
            // Grup kullanmadan direkt items'ları ekle - form'un colCount'u geçerli olsun
            formItems.push(...groupItems)
          } else if (group.itemType === 'tabbed') {
            formItems.push({
              itemType: 'tabbed',
              tabs: (group.tabs || []).map((tab: any) => {
                // Tab items'larını da order'a göre sırala
                const sortedTabItems = (tab.items || [])
                  .slice()
                  .sort((a: any, b: any) => (a.order >= b.order ? 1 : -1))
                
                return {
                  title: translate('::' + tab.title),
                  colCount: tab.colCount || 2,
                  items: sortedTabItems.map((i: EditingFormItemDto) => {
                  // Tab içindeki itemlar için de aynı mapping
                  let editorOptions: any = {}
                  try {
                    if (i.editorOptions) {
                      editorOptions = JSON.parse(i.editorOptions)
                    }
                  } catch {}

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

                  // EditorType belirleme - Grid'deki gibi
                  let editorType: any = i.editorType2 || i.editorType
                  if (i.editorType2 === PlatformEditorTypes.dxGridBox) {
                    editorType = 'dxDropDownBox'
                  } else if (i.editorType2) {
                    editorType = i.editorType2
                  }

                  if (listFormField?.lookupDto) {
                    const lookup = listFormField.lookupDto

                    // EditorType'ı dxSelectBox olarak ayarla
                    if (!editorType || editorType === 'dxTextBox') {
                      editorType = 'dxSelectBox'
                    }

                    if (lookup.dataSourceType === UiLookupDataSourceTypeEnum.Query) {
                      editorOptions.dataSource = new CustomStore({
                        key: 'key',
                        loadMode: 'raw',
                        load: async () => {
                          try {
                            const { dynamicFetch } = await import('@/services/form.service')
                            const response = await dynamicFetch(
                              'list-form-select/lookup',
                              'POST',
                              null,
                              {
                                listFormCode,
                                listFormFieldName: fieldName,
                                filters: [],
                              },
                            )
                            return (response.data ?? []).map((a: any) => ({
                              key: a.Key,
                              name: a.Name,
                              group: a.Group,
                            }))
                          } catch (error) {
                            console.error('Lookup load error:', error)
                            return []
                          }
                        },
                      })

                      editorOptions.valueExpr = 'key'
                      editorOptions.displayExpr = 'name'
                    } else if (lookup.dataSourceType === UiLookupDataSourceTypeEnum.StaticData) {
                      if (lookup.lookupQuery) {
                        try {
                          const staticData = JSON.parse(lookup.lookupQuery)
                          editorOptions.dataSource = staticData
                          editorOptions.valueExpr = lookup.valueExpr || 'key'
                          editorOptions.displayExpr = lookup.displayExpr || 'name'
                        } catch (error) {
                          console.error('Static data parse error:', error)
                        }
                      }
                    }
                  }

                  const validationRules: any[] = []
                  if (i.isRequired) {
                    validationRules.push({ type: 'required' })
                  }

                  const item: any = {
                    dataField: i.dataField,
                    name: i.dataField,
                    editorType,
                    colSpan: i.colSpan,
                    editorOptions,
                    validationRules: validationRules.length > 0 ? validationRules : undefined,
                  }

                  // Label sadece caption varsa ekle
                  if (listFormField?.captionName) {
                    item.label = { text: translate('::' + listFormField.captionName) }
                  }

                  return item
                }),
                }
              }),
            })
          } else {
            // No group, add items directly
            formItems.push(...groupItems)
          }
        })
      }

      // Form'u tamamen yeniden yapılandır
      const formConfig = {
        colCount: gridDto.gridOptions.editingFormDto?.[0]?.colCount || 2,
        showValidationSummary: false,
        items: formItems,
      }
      
      // Form'u tamamen yeniden baştan yapılandır
      e.form.option('colCount', formConfig.colCount)
      e.form.option('showValidationSummary', formConfig.showValidationSummary)
      e.form.option('items', formConfig.items)
      
      // Form'u repaint et
      e.form.repaint()
    },
    [gridDto, translate, isPopupFullScreen, listFormCode],
  )

  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 scheduler configuration...</Loading>
          </div>
        )}
        {gridDto && !schedulerDataSource && (
          <div className="p-4">
            <Loading loading>Loading data source...</Loading>
          </div>
        )}
        {gridDto && schedulerDataSource && (
          <>
            <div className="p-1">
              <Scheduler
                ref={schedulerRef as any}
                key={`Scheduler-${listFormCode}-${schedulerDataSource ? 'loaded' : 'loading'}`}
                id={'Scheduler-' + listFormCode}
                dataSource={schedulerDataSource}
                textExpr={gridDto.gridOptions.schedulerOptionDto?.textExpr || 'text'}
                startDateExpr={gridDto.gridOptions.schedulerOptionDto?.startDateExpr || 'startDate'}
                endDateExpr={gridDto.gridOptions.schedulerOptionDto?.endDateExpr || 'endDate'}
                allDayExpr={gridDto.gridOptions.schedulerOptionDto?.allDayExpr}
                recurrenceRuleExpr={gridDto.gridOptions.schedulerOptionDto?.recurrenceRuleExpr}
                recurrenceExceptionExpr={
                  gridDto.gridOptions.schedulerOptionDto?.recurrenceExceptionExpr
                }
                startDayHour={gridDto.gridOptions.schedulerOptionDto?.startDayHour || 8}
                endDayHour={gridDto.gridOptions.schedulerOptionDto?.endDayHour || 18}
                currentView={currentView}
                onCurrentViewChange={onCurrentViewChange}
                onAppointmentFormOpening={onAppointmentFormOpening}
                onAppointmentAdding={() => {
                  props.refreshData?.()
                }}
                onAppointmentUpdating={() => {
                  props.refreshData?.()
                }}
                onAppointmentDeleting={() => {
                  props.refreshData?.()
                }}
                height={
                  gridDto.gridOptions.height > 0
                    ? gridDto.gridOptions.height
                    : gridDto.gridOptions.fullHeight
                      ? `calc(100vh - ${170 + widgetGroupHeight}px)`
                      : undefined
                }
                showAllDayPanel={gridDto.gridOptions.schedulerOptionDto?.showAllDayPanel ?? true}
                crossScrollingEnabled={
                  gridDto.gridOptions.schedulerOptionDto?.crossScrollingEnabled ?? false
                }
                cellDuration={gridDto.gridOptions.schedulerOptionDto?.cellDuration || 30}
                firstDayOfWeek={
                  (gridDto.gridOptions.schedulerOptionDto?.firstDayOfWeek as
                    | 0
                    | 1
                    | 2
                    | 3
                    | 4
                    | 5
                    | 6) || 1
                }
                adaptivityEnabled={true}
              >
                <Toolbar>
                  <Item name="dateNavigator" />
                  <Item name="today" />
                  <Item name="viewSwitcher" />
                  <Item
                    location="after"
                    widget="dxButton"
                    options={{
                      icon: 'refresh',
                      hint: translate('::ListForms.ListForm.Refresh'),
                      onClick: handleRefresh,
                    }}
                  />
                  {checkPermission(gridDto?.gridOptions.permissionDto.u) && (
                    <Item
                      location="after"
                      widget="dxButton"
                      options={{
                        icon: 'preferences',
                        hint: 'Settings',
                        onClick: settingButtonClick,
                      }}
                    />
                  )}
                </Toolbar>

                <Editing
                  allowAdding={gridDto.gridOptions.schedulerOptionDto?.allowAdding ?? false}
                  allowUpdating={gridDto.gridOptions.schedulerOptionDto?.allowUpdating ?? false}
                  allowDeleting={gridDto.gridOptions.schedulerOptionDto?.allowDeleting ?? false}
                  allowResizing={gridDto.gridOptions.schedulerOptionDto?.allowResizing ?? false}
                  allowDragging={gridDto.gridOptions.schedulerOptionDto?.allowDragging ?? false}
                />

                <View type="day" name={translate('::ListForms.SchedulerOptions.Day')} />
                <View type="week" name={translate('::ListForms.SchedulerOptions.Week')} />
                <View type="workWeek" name={translate('::ListForms.SchedulerOptions.WorkWeek')} />
                <View type="month" name={translate('::ListForms.SchedulerOptions.Month')} />
                <View
                  type="timelineDay"
                  name={translate('::ListForms.SchedulerOptions.TimelineDay')}
                  maxAppointmentsPerCell="unlimited"
                />
                <View
                  type="timelineWeek"
                  name={translate('::ListForms.SchedulerOptions.TimelineWeek')}
                  maxAppointmentsPerCell="unlimited"
                />
                <View
                  type="timelineMonth"
                  name={translate('::ListForms.SchedulerOptions.TimelineMonth')}
                  maxAppointmentsPerCell="unlimited"
                />
                <View type="agenda" name={translate('::ListForms.SchedulerOptions.Agenda')} />

                {gridDto.gridOptions.schedulerOptionDto?.resources?.map((resource, index) => (
                  <Resource
                    key={index}
                    fieldExpr={resource.fieldExpr}
                    dataSource={resource.dataSource}
                    label={resource.label}
                    useColorAsDefault={resource.useColorAsDefault}
                  />
                ))}
              </Scheduler>
            </div>
          </>
        )}
      </Container>
    </>
  )
}

export default SchedulerView
