import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { EditingFormItemDto, GridDto, PlatformEditorTypes } from '@/proxy/form/models'
import { captionize } from 'devextreme/core/utils/inflector'
import { useListFormCustomDataSource } from '@/shared/useListFormCustomDataSource'
import { Button, Pagination, Select } from '@/components/ui'
import classNames from 'classnames'
import { getList } from '@/services/form.service'
import { FaInbox, FaSearch } from 'react-icons/fa'
import FormDevExpress from '../form/FormDevExpress'
import { GroupItem } from 'devextreme/ui/form'
import { Form as FormDx } from 'devextreme-react/form'
import FormButtons from '../form/FormButtons'
import { useNavigate } from 'react-router-dom'
import { ROUTES_ENUM } from '@/routes/route.constant'
import CustomStore from 'devextreme/data/custom_store'
import { PermissionResults, SimpleItemWithColData } from '../form/types'
import { usePermission } from '@/utils/hooks/usePermission'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { useLookupDataSource } from '../form/useLookupDataSource'
import { Container, Loading } from '@/components/shared'
import WidgetGroup from '@/components/common/WidgetGroup'
import { GridExtraFilterState } from './Utils'

interface CardProps {
  listFormCode: string
  searchParams?: URLSearchParams
}

type Option = {
  value: number
  label: string
}

const CardItem = ({
  isSubForm,
  row,
  gridDto,
  listFormCode,
  dataSource,
  refreshData,
  getCachedLookupDataSource,
}: {
  isSubForm?: boolean
  row: any
  gridDto: GridDto
  listFormCode: string
  dataSource: CustomStore
  refreshData: () => void
  getCachedLookupDataSource: (editorOptions: any, colData: any) => any
}) => {
  const [formData, setFormData] = useState(row)
  const refForm = useRef<FormDx>(null)
  const navigate = useNavigate()
  const { checkPermission } = usePermission()
  const { translate } = useLocalization()

  const keyField = gridDto.gridOptions.keyFieldName
  const rowId = row[keyField!]

  // Form Items
  const formItems: GroupItem[] = useMemo(() => {
    if (!gridDto) return []

    return gridDto.gridOptions.editingFormDto
      ?.sort((a, b) => (a.order >= b.order ? 1 : -1))
      .map((e) => {
        return {
          itemType: e.itemType,
          colCount: e.colCount,
          colSpan: e.colSpan,
          caption: e.caption,
          items: e.items
            ?.sort((a, b) => (a.order >= b.order ? 1 : -1))
            .map((i: EditingFormItemDto) => {
              let editorOptions = {}
              const colData = gridDto.columnFormats.find((x) => x.fieldName === i.dataField)

              try {
                editorOptions = i.editorOptions && JSON.parse(i.editorOptions)
              } catch {}

              const item: SimpleItemWithColData = {
                canRead: colData?.canRead ?? false,
                canUpdate: colData?.canUpdate ?? false,
                canCreate: colData?.canCreate ?? false,
                canExport: colData?.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: {
                  ...editorOptions,
                  ...(colData?.lookupDto?.dataSourceType
                    ? {
                        dataSource: getCachedLookupDataSource(colData?.editorOptions, colData),
                        valueExpr: colData?.lookupDto?.valueExpr?.toLowerCase(),
                        displayExpr: colData?.lookupDto?.displayExpr?.toLowerCase(),
                      }
                    : {}),
                },
                colData,
                tagBoxOptions: i.tagBoxOptions,
                gridBoxOptions: i.gridBoxOptions,
              }
              if (i.dataField.indexOf(':') >= 0) {
                item.label = { text: captionize(i.dataField.split(':')[1]) }
              }
              item.editorOptions = {
                ...item.editorOptions,
                readOnly: true,
              }
              return item
            }),
        } as GroupItem
      })
  }, [gridDto, getCachedLookupDataSource])

  const permissionResults: PermissionResults = {
    c:
      gridDto?.gridOptions.editingOptionDto.allowAdding === true &&
      checkPermission(gridDto?.gridOptions.permissionDto.c),
    r: checkPermission(gridDto?.gridOptions.permissionDto.r),
    u:
      gridDto?.gridOptions.editingOptionDto.allowUpdating === true &&
      checkPermission(gridDto?.gridOptions.permissionDto.u),
    d:
      gridDto?.gridOptions.editingOptionDto.allowDeleting === true &&
      checkPermission(gridDto?.gridOptions.permissionDto.d),
    e: checkPermission(gridDto?.gridOptions.permissionDto.e),
    i: checkPermission(gridDto?.gridOptions.permissionDto.i),
  }

  const onActionEdit = () => {
    navigate(
      ROUTES_ENUM.protected.admin.formEdit
        .replace(':listFormCode', listFormCode)
        .replace(':id', rowId!),
    )
  }

  const onActionNew = () => {
    navigate(ROUTES_ENUM.protected.admin.formNew.replace(':listFormCode', listFormCode))
  }

  return (
    <div className="bg-white dark:bg-neutral-800 border dark:border-neutral-700 flex flex-col groupp p-2">
      <div className={`flex items-center mb-2 ${isSubForm ? 'justify-center' : 'justify-between'}`}>
        {!isSubForm && <h3>{translate('::' + gridDto?.gridOptions.title)}</h3>}
        {permissionResults && (
          <FormButtons
            isSubForm={true}
            mode="view"
            listFormCode={listFormCode}
            id={rowId}
            gridDto={gridDto}
            commandColumnData={{ buttons: [] }}
            dataSource={dataSource}
            permissions={permissionResults}
            handleSubmit={() => ({})}
            refreshData={refreshData}
            getSelectedRowKeys={() => [rowId]}
            getSelectedRowsData={() => [row]}
            getFilter={() => null}
            onActionEdit={onActionEdit}
            onActionNew={onActionNew}
          />
        )}
      </div>
      <div className="flex-grow">
        <FormDevExpress
          mode="view"
          refForm={refForm}
          formData={formData}
          formItems={formItems}
          setFormData={setFormData}
          listFormCode={listFormCode}
        />
      </div>
    </div>
  )
}

const Card = ({ listFormCode, searchParams }: CardProps) => {
  const { createSelectDataSource } = useListFormCustomDataSource({})
  const [gridDto, setGridDto] = useState<GridDto>()
  const [data, setData] = useState<any[]>([])
  const [totalCount, setTotalCount] = useState(0)
  const [currentPage, setCurrentPage] = useState(1)
  const [pageSize, setPageSize] = useState(20)
  const [pageSizeOptions, setPageSizeOptions] = useState<Option[]>([])
  const [gridDataSource, setGridDataSource] = useState<CustomStore<any, any>>()
  const [extraFilters, setExtraFilters] = useState<GridExtraFilterState[]>([])
  const [layoutCount, setLayoutCount] = useState(4)

  const { getLookupDataSource } = useLookupDataSource({ listFormCode })
  const lookupCache = useRef<Map<string, any>>(new Map())

  const getCachedLookupDataSource = useCallback(
    (editorOptions: any, colData: any) => {
      const key = colData?.fieldName
      if (!key) return null

      if (!lookupCache.current.has(key)) {
        lookupCache.current.set(key, getLookupDataSource(editorOptions, colData))
      }
      return lookupCache.current.get(key)
    },
    [getLookupDataSource],
  )

  const onPageSizeSelect = ({ value }: Option) => {
    setPageSize(value)
    setCurrentPage(1)
  }

  const onPageChange = (page: number) => {
    setCurrentPage(page)
  }

  useEffect(() => {
    getList({ listFormCode }).then((res: any) => setGridDto(res.data))
  }, [listFormCode])

  useEffect(() => {
    if (gridDto) {
      const dataSource = createSelectDataSource(gridDto.gridOptions, listFormCode, searchParams)
      setGridDataSource(dataSource)
    }
  }, [gridDto, listFormCode, searchParams, createSelectDataSource])

  const loadData = useCallback(() => {
    if (!gridDataSource) return

    const loadOptions = {
      skip: (currentPage - 1) * pageSize,
      take: pageSize,
      requireTotalCount: true,
    }

    gridDataSource.load(loadOptions).then((res: any) => {
      setData(res.data)
      setTotalCount(res.totalCount || 0)
    })
  }, [gridDataSource, currentPage, pageSize])

  useEffect(() => {
    if (gridDataSource) {
      loadData()
    }
  }, [gridDataSource, loadData])

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

    const pagerOptions = gridDto.gridOptions.pagerOptionDto
    const allowedSizes = pagerOptions?.allowedPageSizes
      ?.split(',')
      .map((s) => Number(s.trim()))
      .filter((n) => !isNaN(n) && n > 0) || [10, 20, 50, 100]

    setPageSizeOptions(allowedSizes.map((size) => ({ value: size, label: `${size} page` })))
  }, [gridDto, listFormCode, searchParams])

  // Data güncellendiğinde sayfanın en üstüne kaydır
  useEffect(() => {
    if (data.length > 0) {
      window.scrollTo({ top: 0, behavior: 'smooth' })
    }
  }, [data])

  if (!gridDto) return null

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

      <Container>
        <div className="bg-white border border-solid border-1 dark:bg-neutral-800 dark:border-neutral-700 flex justify-end items-center">
          <div className="relative py-1 px-2 flex gap-1">
            <FaSearch className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 text-sm" />
            <input
              type="text"
              placeholder="Search..."
              className="p-1 pl-6 pr-2  border border-1 outline-none text-xs text-gray-700 dark:text-gray-200 placeholder-gray-400 rounded"
            />

            <Button
              size="xs"
              variant={layoutCount === 3 ? 'solid' : 'default'}
              className="text-sm"
              onClick={() => setLayoutCount(3)}
            >
              3
            </Button>
            <Button
              size="xs"
              variant={layoutCount === 4 ? 'solid' : 'default'}
              className="text-sm"
              onClick={() => setLayoutCount(4)}
            >
              4
            </Button>
            <Button
              size="xs"
              variant={layoutCount === 5 ? 'solid' : 'default'}
              className="text-sm"
              onClick={() => setLayoutCount(5)}
            >
              5
            </Button>
          </div>
        </div>

        <div className={`grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-${layoutCount} gap-4`}>
          {gridDataSource &&
            data.map((row, idx) => {
              const keyField = gridDto.gridOptions.keyFieldName
              const rowId = row[keyField!]

              return (
                <CardItem
                  isSubForm={true}
                  key={rowId || idx}
                  row={row}
                  gridDto={gridDto}
                  listFormCode={listFormCode}
                  dataSource={gridDataSource}
                  refreshData={loadData}
                  getCachedLookupDataSource={getCachedLookupDataSource}
                />
              )
            })}
        </div>

        {gridDto.gridOptions.pagerOptionDto?.visible && totalCount > pageSize && (
          <div className={classNames('flex items-center justify-between border-t-1 gap-4 mt-4')}>
            <div className="flex items-center gap-2">
              <span className="text-xs text-gray-600 dark:text-gray-300">
                Toplam {totalCount} kayıt
              </span>
              <Select
                size="xs"
                menuPlacement="top"
                value={pageSizeOptions.find((o) => o.value === pageSize)}
                options={pageSizeOptions}
                onChange={(selected) => onPageSizeSelect(selected as Option)}
              />
            </div>
            <Pagination
              currentPage={currentPage}
              total={totalCount}
              pageSize={pageSize}
              onChange={onPageChange}
            />
          </div>
        )}

        {data.length === 0 && (
          <Loading loading={!data.length} />
          // <div className="flex flex-col items-center justify-center p-10 bg-gray-50 dark:bg-neutral-800/50 rounded-md border-2 border-dashed border-gray-200 dark:border-neutral-700">
          //   <div className="text-center">
          //     <FaInbox className="mx-auto h-12 w-12 text-gray-400 dark:text-gray-500" />
          //     <p className="mt-4 text-lg font-semibold text-gray-700 dark:text-gray-300">
          //       Kayıt Bulunamadı
          //     </p>
          //     <p className="text-sm text-gray-500 dark:text-gray-400 mt-1">
          //       Görüntülenecek herhangi bir veri yok.
          //     </p>
          //   </div>
          // </div>
        )}
      </Container>
    </>
  )
}

export default Card
