import { useCallback, useEffect, useState } from 'react'
import { GridDto } from '@/proxy/form/models'
import { useListFormCustomDataSource } from '@/shared/useListFormCustomDataSource'
import { Button, Pagination, Select } from '@/components/ui'
import classNames from 'classnames'
import { FaCog, FaSearch } from 'react-icons/fa'
import { ROUTES_ENUM } from '@/routes/route.constant'
import CustomStore from 'devextreme/data/custom_store'
import { usePermission } from '@/utils/hooks/usePermission'
import { useLookupDataSource } from '../form/useLookupDataSource'
import { Container, Loading } from '@/components/shared'
import WidgetGroup from '@/components/common/WidgetGroup'
import { GridExtraFilterState } from './Utils'
import { useStoreActions, useStoreState } from '@/store/store'
import { usePWA } from '@/utils/hooks/usePWA'
import CardItem from './CardItem'
import { layoutTypes } from '../admin/listForm/edit/types'

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

type Option = {
  value: number
  label: string
}

const Card = (props: CardProps) => {
  const { listFormCode, searchParams, gridDto } = props
  const { createSelectDataSource } = useListFormCustomDataSource({} as any)
  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 { getLookupDataSource } = useLookupDataSource({ listFormCode })
  const [layoutCount, setLayoutCount] = useState(4)
  const [searchText, setSearchText] = useState('')
  const [prevValue, setPrevValue] = useState('')
  const [loading, setLoading] = useState(false)
  const { checkPermission } = usePermission()
  const isPwaMode = usePWA()
  const [extraFilters, setExtraFilters] = useState<GridExtraFilterState[]>([])

  const { states } = useStoreState((state) => state.admin.lists)
  const { setStates } = useStoreActions((a) => a.admin.lists)

  // props.searchParams varsa onunla başlat
  const [urlSearchParams, setUrlSearchParams] = useState<URLSearchParams>(
    searchParams ? new URLSearchParams(searchParams) : new URLSearchParams(),
  )

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

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

  const onFilter = useCallback(
    (value?: string) => {
      const text = value !== undefined ? value.trim() : searchText.trim()

      if (!gridDto?.columnFormats) return

      const newParams = new URLSearchParams(urlSearchParams.toString())

      if (!text) {
        newParams.delete('filter')
        setUrlSearchParams(newParams)
        return
      }

      const merged = gridDto.columnFormats
        .filter(
          (col) =>
            col.dataType === 'string' &&
            col.visible &&
            col.width &&
            col.allowSearch &&
            col.width > 0,
        )
        .map((col) => [col.fieldName, 'contains', text])

      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, 'or', f]
        }, null as any)
      }

      if (filter) {
        newParams.set('filter', JSON.stringify(filter))
      } else {
        newParams.delete('filter')
      }

      setUrlSearchParams(newParams)
    },
    [gridDto, urlSearchParams, searchText],
  )

  useEffect(() => {
    if (gridDto) {
      const dataSource = createSelectDataSource(
        gridDto.gridOptions,
        listFormCode,
        urlSearchParams,
        [],
        layoutTypes.card,
      )
      setGridDataSource(dataSource)

      //listFormStates
      const listFormStates = states.find((a) => a.listFormCode === listFormCode)
      if (listFormStates) {
        setLayoutCount(listFormStates.cardLayoutColumn || 4)
      } else {
        setLayoutCount(gridDto.gridOptions.layoutDto.cardLayoutColumn || 4)
      }
    }
  }, [gridDto, listFormCode, urlSearchParams, createSelectDataSource])

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

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

    gridDataSource
      .load(loadOptions)
      .then((res: any) => {
        setData(res.data)
        setTotalCount(res.totalCount || 0)
        setLoading(false)
      })
      .catch(() => {
        setLoading(false)
      })
  }, [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])

  useEffect(() => {
    if (data.length > 0) {
      window.scrollTo({ top: 0, behavior: 'smooth' })

      if (data.length < 6) {
        setLayoutCount(data.length)
      }
    }
  }, [data])

  if (!gridDto) return null

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

      <Container>
        <div className="bg-white dark:bg-neutral-800 dark:border-neutral-700 ">
          <div className="flex justify-end items-center">
            <div className="relative py-1 flex gap-1 border-b-1">
              <FaSearch className="absolute left-2 top-1/2 -translate-y-1/2 text-gray-400 text-sm" />
              <input
                type="text"
                placeholder="Search..."
                value={searchText}
                onChange={(e) => setSearchText(e.target.value)}
                onKeyDown={(e) => {
                  if (e.key === 'Enter') {
                    onFilter(e.currentTarget.value)
                    setPrevValue(e.currentTarget.value.trim()) // Enter ile tetiklenirse güncelle
                  }
                }}
                onBlur={(e) => {
                  const newValue = e.currentTarget.value.trim()

                  // 1. Değer değişmemişse => hiçbir şey yapma
                  if (newValue === prevValue) return

                  // 2. Yeni değer boş, ama eskiden değer vardı => filtre temizle
                  // 3. Yeni değer dolu ve eskisinden farklı => filtre uygula
                  onFilter(newValue)
                  setPrevValue(newValue)
                }}
                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 === 1 ? 'solid' : 'default'}
                className="text-sm"
                onClick={() => {
                  setLayoutCount(1)
                  setStates({ listFormCode, layout: 'card', cardLayoutColumn: 1 })
                }}
                title="1 Sütunda Göster"
              >
                1
              </Button>
              <Button
                size="xs"
                variant={layoutCount === 2 ? 'solid' : 'default'}
                className="text-sm"
                onClick={() => {
                  setLayoutCount(2)
                  setStates({ listFormCode, layout: 'card', cardLayoutColumn: 2 })
                }}
                title="2 Sütunda Göster"
              >
                2
              </Button>
              <Button
                size="xs"
                variant={layoutCount === 3 ? 'solid' : 'default'}
                className="text-sm"
                onClick={() => {
                  setLayoutCount(3)
                  setStates({ listFormCode, layout: 'card', cardLayoutColumn: 3 })
                }}
                title="3 Sütunda Göster"
              >
                3
              </Button>
              <Button
                size="xs"
                variant={layoutCount === 4 ? 'solid' : 'default'}
                className="text-sm"
                onClick={() => {
                  setLayoutCount(4)
                  setStates({ listFormCode, layout: 'card', cardLayoutColumn: 4 })
                }}
                title="4 Sütunda Göster"
              >
                4
              </Button>
              <Button
                size="xs"
                variant={layoutCount === 5 ? 'solid' : 'default'}
                className="text-sm"
                onClick={() => {
                  setLayoutCount(5)
                  setStates({ listFormCode, layout: 'card', cardLayoutColumn: 5 })
                }}
                title="5 Sütunda Göster"
              >
                5
              </Button>

              {checkPermission(gridDto?.gridOptions.permissionDto.u) && (
                <Button
                  size="xs"
                  variant={'default'}
                  className="text-sm"
                  onClick={() => {
                    window.open(
                      ROUTES_ENUM.protected.saas.listFormManagement.edit.replace(
                        ':listFormCode',
                        listFormCode,
                      ),
                      isPwaMode ? '_self' : '_blank',
                    )
                  }}
                  title="Form Manager"
                >
                  <FaCog className="w-3 h-3" />
                </Button>
              )}
            </div>
          </div>

          {loading ? (
            <Loading loading={true} />
          ) : data.length === 0 ? (
            <div className="text-center py-12">
              <FaSearch className="mx-auto h-10 w-10 text-gray-400" />
              <h3 className="mt-2 text-sm font-medium text-gray-900 dark:text-gray-200">
                Uygun kayıt bulunamadı
              </h3>
              <p className="mt-1 text-xs text-gray-500 dark:text-gray-400">
                Farklı filtreler deneyin veya yeni bir kayıt ekleyin.
              </p>
            </div>
          ) : (
            <div className={`bg-transparent grid grid-cols-1 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={getLookupDataSource}
                    />
                  )
                })}
            </div>
          )}

          {gridDto.gridOptions.pagerOptionDto?.visible && totalCount > pageSize && (
            <div className={classNames('flex items-center justify-between border-t-1 gap-4 mt-2')}>
              <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>
          )}
        </div>
      </Container>
    </>
  )
}

export default Card
