import Container from '@/components/shared/Container'
import { APP_NAME, DX_CLASSNAMES } from '@/constants/app.constant'
import {
  DbTypeEnum,
  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, autoNumber } 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 { EditingFormItemDto } from '@/proxy/form/models'
import { RowMode, SimpleItemWithColData } from '../form/types'
import { captionize } from 'devextreme/core/utils/inflector'
import { AppointmentFormOpeningEvent } from 'devextreme/ui/scheduler'

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 [mode, setMode] = useState<RowMode>('view')

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

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

  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: AppointmentFormOpeningEvent) => {
      if (!gridDto) return

      // Yeni appointment mı yoksa düzenleme mi kontrol et
      const isNewAppointment =
        !e.appointmentData ||
        (!e.appointmentData.id && !e.appointmentData[gridDto.gridOptions.keyFieldName || 'id'])

      const currentMode = isNewAppointment ? 'new' : 'edit'
      setMode(currentMode)

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

      // Toolbar butonlarını ekle
      e.popup.option('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 {
                  // 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',
                )
              }
            },
          },
        },
      ])

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

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

        // Tüm tabbed items'ları topla (Grid'deki gibi)
        const tabbedItems = sortedFormDto.filter((e: any) => e.itemType === 'tabbed')

        // Ortak item mapper fonksiyonu - hem group hem tab için kullanılır
        const mapFormItem = (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)

          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' &&
            currentMode === 'new'
          ) {
            editorOptions = {
              ...editorOptions,
              value: autoNumber(),
            }
          }

          // EditorType belirleme
          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

            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 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 ((currentMode == 'edit' && !item.canUpdate) || (currentMode == 'new' && !item.canCreate)) {
            item.editorOptions = {
              ...item.editorOptions,
              readOnly: true,
            }
          }

          return item
        }

        sortedFormDto.forEach((e: any) => {
          // Items'ları da order'a göre sırala
          const sortedItems = (e.items || [])
            .slice()
            .sort((a: any, b: any) => (a.order >= b.order ? 1 : -1))

          const groupItems = sortedItems.map(mapFormItem)

          if (e.itemType !== 'tabbed') {
            // Grup kullanmadan direkt items'ları ekle - form'un colCount'u geçerli olsun
            result.push(...groupItems)
          } else if (e.itemType === 'tabbed' && tabbedItems.length > 0 && e === tabbedItems[0]) {
            // Tabbed için caption OLMAMALI - sadece tabs array içinde title kullan
            result.push({
              itemType: 'tabbed',
              // colCount tabbed item için OLMAMALI - sadece colSpan
              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 || 2

                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 (currentMode === 'new') {
                        return a.canCreate || a.canRead
                      } else if (currentMode === 'edit') {
                        return a.canUpdate || a.canRead
                      }
                      return false
                    }),
                }
              }),
            })
          }
        })
      }

      // Form'u tamamen yeniden yapılandır
      const hasTabbedItems = result.some((item: any) => item.itemType === 'tabbed')

      // Form'u tamamen yeniden baştan yapılandır
      e.form.option(
        'colCount',
        hasTabbedItems ? 1 : gridDto.gridOptions.editingFormDto?.[0]?.colCount || 2,
      )
      e.form.option(
        'colCount',
        hasTabbedItems ? 1 : gridDto.gridOptions.editingFormDto?.[0]?.colCount || 2,
      )
      e.form.option('showValidationSummary', false)
      e.form.option('items', result)

      // Yeni versiyonlarda bu şekilde Style değiştirme işlemi yapmak zorunda olmayabiliriz.
      // Yani geçici olarak eklenmiştir.
      // Tabbed varsa belirli class'lara sahip elementi bul ve flex-direction'ı değiştir
      if (hasTabbedItems) {
        setTimeout(() => {
          const targetElement = document.querySelector('.dx-item-content.dx-box-item-content.dx-box-flex.dx-box.dx-widget.dx-collection')
          if (targetElement) {
            const htmlElement = targetElement as HTMLElement
            
            // Mevcut style'ı al ve flex-direction: row'u column'a çevir
            const currentStyle = htmlElement.getAttribute('style') || ''
            const updatedStyle = currentStyle.replace(/flex-direction:\s*row/gi, 'flex-direction: column')
            htmlElement.setAttribute('style', updatedStyle)
          } 
        }, 100)
      }
      
    },
    [gridDto, translate, isPopupFullScreen, listFormCode],
  )

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

      <Container className={DX_CLASSNAMES}>
        {!isSubForm && (
          <Helmet
            titleTemplate={`%s | ${APP_NAME}`}
            title={translate('::' + gridDto?.gridOptions.title)}
            defaultTitle={APP_NAME}
          ></Helmet>
        )}
        {!gridDto && (
          <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}
                dateSerializationFormat='yyyy-MM-ddTHH:mm:ss'
                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?.allowEditing ?? 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
