import { useCallback, useEffect, useState, useRef, KeyboardEvent, useMemo } from 'react'
import { GridDto } from '@/proxy/form/models'
import { Button, Pagination, Select, Checkbox } from '@/components/ui'
import classNames from 'classnames'
import { FaCog, FaSearch, FaSortAmountDown, FaSortAmountUp } 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'
import { useListFormCustomDataSource } from './useListFormCustomDataSource'

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[]>([])
  
  // Selection features - gridDto değiştiğinde güncellenmeli
  const [selectedKeys, setSelectedKeys] = useState<Set<any>>(new Set())
  const selectionMode: 'none' | 'single' | 'multiple' = useMemo(() => {
    if (!gridDto?.gridOptions?.selectionDto?.mode) return 'none'
    const mode = gridDto.gridOptions.selectionDto.mode.toLowerCase()
    if (mode === 'single') return 'single'
    if (mode === 'multiple') return 'multiple'
    return 'none'
  }, [gridDto])
  
  // Sorting features
  const [sortColumn, setSortColumn] = useState<string | null>(null)
  const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('asc')
  
  // Focus and keyboard navigation
  const [focusedCardIndex, setFocusedCardIndex] = useState<number>(-1)
  const cardRefs = useRef<(HTMLDivElement | null)[]>([])
  const containerRef = useRef<HTMLDivElement>(null)
  
  // Hover state
  const [hoveredCardKey, setHoveredCardKey] = useState<any>(null)

  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>(() => {
    const params = searchParams ? new URLSearchParams(searchParams) : new URLSearchParams()
    
    // Initialize sort state from URL params
    const sortParam = params.get('sort')
    if (sortParam) {
      try {
        const sortArray = JSON.parse(sortParam)
        if (sortArray && sortArray.length > 0) {
          setSortColumn(sortArray[0].selector)
          setSortOrder(sortArray[0].desc ? 'desc' : 'asc')
        }
      } catch (e) {
        console.error('Sort param parse error:', e)
      }
    }
    
    return params
  })

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

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

  const toggleSort = (columnName: string) => {
    const newParams = new URLSearchParams(urlSearchParams.toString())
    
    if (sortColumn === columnName) {
      const newOrder = sortOrder === 'asc' ? 'desc' : 'asc'
      setSortOrder(newOrder)
      newParams.set('sort', JSON.stringify([{ selector: columnName, desc: newOrder === 'desc' }]))
    } else {
      setSortColumn(columnName)
      setSortOrder('asc')
      newParams.set('sort', JSON.stringify([{ selector: columnName, desc: false }]))
    }
    
    setUrlSearchParams(newParams)
    setCurrentPage(1) // Reset to first page when sorting
  }

  const handleSelectAll = (checked: boolean) => {
    if (checked) {
      const keyField = gridDto?.gridOptions.keyFieldName
      if (keyField) {
        const allKeys = new Set(data.map(row => row[keyField]))
        setSelectedKeys(allKeys)
      }
    } else {
      setSelectedKeys(new Set())
    }
  }

  const handleCardSelection = (key: any, checked: boolean) => {
    const newSelection = new Set(selectedKeys)
    if (checked) {
      if (selectionMode === 'single') {
        newSelection.clear()
      }
      newSelection.add(key)
    } else {
      newSelection.delete(key)
    }
    setSelectedKeys(newSelection)
  }

  const handleCardClick = (key: any, index: number, event: React.MouseEvent) => {
    setFocusedCardIndex(index)
    if (selectionMode !== 'none' && event.ctrlKey) {
      handleCardSelection(key, !selectedKeys.has(key))
    }
  }

  const handleCardDoubleClick = (key: any, row: any) => {
    // Navigate to edit page on double click
    const navigate = window.location
    window.open(
      ROUTES_ENUM.protected.admin.formEdit
        .replace(':listFormCode', listFormCode)
        .replace(':id', key),
      isPwaMode ? '_self' : '_blank'
    )
  }

  const handleExport = async (format: 'xlsx' | 'csv' | 'pdf', selectedOnly: boolean = false) => {
    try {
      const exportData = selectedOnly 
        ? data.filter(row => {
            const keyField = gridDto?.gridOptions.keyFieldName
            return keyField && selectedKeys.has(row[keyField])
          })
        : data

      if (exportData.length === 0) {
        return
      }

      if (format === 'xlsx' || format === 'csv') {
        const [{ Workbook }, { saveAs }] = await Promise.all([
          import('exceljs'),
          import('file-saver'),
        ])

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

        // Header row - visible columns only
        const visibleColumns = gridDto?.columnFormats?.filter(
          col => col.visible && col.dataType !== 'buttons'
        ) || []
        
        const headerRow = visibleColumns.map(col => col.fieldName)
        worksheet.addRow(headerRow)
        worksheet.getRow(1).font = { bold: true }

        // Data rows
        exportData.forEach(row => {
          const dataRow = visibleColumns.map(col => row[col.fieldName!])
          worksheet.addRow(dataRow)
        })

        // Auto-fit columns
        worksheet.columns.forEach((column: any) => {
          column.width = 15
        })

        if (format === 'xlsx') {
          const buffer = await workbook.xlsx.writeBuffer()
          saveAs(
            new Blob([buffer], { type: 'application/octet-stream' }),
            `${listFormCode}_export${selectedOnly ? '_selected' : ''}.xlsx`,
          )
        } else {
          const buffer = await workbook.csv.writeBuffer()
          saveAs(
            new Blob([buffer], { type: 'application/octet-stream' }),
            `${listFormCode}_export${selectedOnly ? '_selected' : ''}.csv`,
          )
        }
      } else if (format === 'pdf') {
        const [jspdfMod] = await Promise.all([
          import('jspdf'),
        ])

        const JsPDFCtor = (jspdfMod as any).default ?? (jspdfMod as any).jsPDF
        const doc = new JsPDFCtor({ orientation: 'landscape' })

        // Header
        const visibleColumns = gridDto?.columnFormats?.filter(
          col => col.visible && col.dataType !== 'buttons'
        ) || []

        let yPos = 10
        doc.setFontSize(16)
        doc.text(gridDto?.gridOptions.title || listFormCode, 10, yPos)
        yPos += 10

        // Table
        doc.setFontSize(10)
        const headers = visibleColumns.map(col => col.fieldName)
        const rows = exportData.map(row => 
          visibleColumns.map(col => String(row[col.fieldName!] || ''))
        )

        // Simple table rendering
        doc.text(headers.join(' | '), 10, yPos)
        yPos += 7
        
        rows.forEach(row => {
          if (yPos > 190) {
            doc.addPage()
            yPos = 10
          }
          doc.text(row.join(' | '), 10, yPos)
          yPos += 7
        })

        doc.save(`${listFormCode}_export${selectedOnly ? '_selected' : ''}.pdf`)
      }
    } catch (err) {
      console.error('Export error:', err)
    }
  }

  const handleKeyDown = (e: KeyboardEvent) => {
    if (data.length === 0) return

    const keyField = gridDto?.gridOptions.keyFieldName
    if (!keyField) return

    switch (e.key) {
      case 'ArrowRight':
        e.preventDefault()
        if (focusedCardIndex < data.length - 1) {
          const newIndex = focusedCardIndex + 1
          setFocusedCardIndex(newIndex)
          cardRefs.current[newIndex]?.focus()
        }
        break
      case 'ArrowLeft':
        e.preventDefault()
        if (focusedCardIndex > 0) {
          const newIndex = focusedCardIndex - 1
          setFocusedCardIndex(newIndex)
          cardRefs.current[newIndex]?.focus()
        }
        break
      case 'ArrowDown':
        e.preventDefault()
        if (focusedCardIndex + layoutCount < data.length) {
          const newIndex = focusedCardIndex + layoutCount
          setFocusedCardIndex(newIndex)
          cardRefs.current[newIndex]?.focus()
        }
        break
      case 'ArrowUp':
        e.preventDefault()
        if (focusedCardIndex - layoutCount >= 0) {
          const newIndex = focusedCardIndex - layoutCount
          setFocusedCardIndex(newIndex)
          cardRefs.current[newIndex]?.focus()
        }
        break
      case 'Enter':
        e.preventDefault()
        if (focusedCardIndex >= 0 && focusedCardIndex < data.length) {
          const row = data[focusedCardIndex]
          handleCardDoubleClick(row[keyField], row)
        }
        break
      case ' ': // Space key for selection
        e.preventDefault()
        if (selectionMode !== 'none' && focusedCardIndex >= 0) {
          const key = data[focusedCardIndex][keyField]
          handleCardSelection(key, !selectedKeys.has(key))
        }
        break
    }
  }

  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, states])

  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
          ref={containerRef}
          onKeyDown={handleKeyDown}
          tabIndex={0}
          className="outline-none"
        >
          <div className="flex justify-between items-center mb-2">
            <div className="flex items-center gap-4">
              {selectionMode === 'multiple' && gridDto?.gridOptions?.selectionDto?.allowSelectAll && (
                <div className="flex items-center">
                  <Checkbox
                    checked={selectedKeys.size > 0 && selectedKeys.size === data.length}
                    onChange={(checked: boolean) => handleSelectAll(checked)}
                    className="cursor-pointer"
                  />
                  <span className="text-sm text-gray-600 dark:text-gray-300">
                    {selectedKeys.size > 0 ? `${selectedKeys.size} seçili` : 'Tümünü Seç'}
                  </span>
                </div>
              )}
              
              {selectionMode !== 'none' && selectedKeys.size > 0 && !gridDto?.gridOptions?.selectionDto?.allowSelectAll && (
                <div className="flex items-center gap-2">
                  <span className="text-sm text-gray-600 dark:text-gray-300">
                    {selectedKeys.size} seçili
                  </span>
                </div>
              )}
            </div>
            
            <div className="flex justify-end items-center gap-2">
              {/* Export Buttons */}
              {gridDto?.gridOptions?.exportDto?.enabled && (
                <div className="flex items-center gap-1">
                  <Button
                    size="xs"
                    variant="default"
                    onClick={() => handleExport('xlsx', selectionMode !== 'none' && selectedKeys.size > 0)}
                    title={selectionMode !== 'none' && selectedKeys.size > 0 ? `Seçilenleri Excel'e Aktar (${selectedKeys.size})` : "Tümünü Excel'e Aktar"}
                  >
                    📊 {selectionMode !== 'none' && selectedKeys.size > 0 ? `Seçilenleri Excel'e Aktar (${selectedKeys.size})` : `Tümünü Excel'e Aktar`}
                  </Button>
                </div>
              )}
              
              {/* Sort Dropdown */}
              {gridDto && gridDto.columnFormats && gridDto.columnFormats.length > 0 && (
                <div className="flex items-center gap-1">
                  <select
                    className="text-xs border rounded px-2 py-1 dark:bg-neutral-700 dark:text-white dark:border-neutral-600"
                    onChange={(e) => {
                      if (e.target.value) {
                        toggleSort(e.target.value)
                      } else {
                        // "Sıralama Yok" seçildiğinde temizle
                        const newParams = new URLSearchParams(urlSearchParams.toString())
                        newParams.delete('sort')
                        setUrlSearchParams(newParams)
                        setSortColumn(null)
                        setSortOrder('asc')
                      }
                    }}
                    value={sortColumn || ''}
                  >
                    <option value="">Sıralama Yok</option>
                    {gridDto.columnFormats
                      .filter((col) => col.visible && col.dataType !== 'buttons')
                      .map((col) => (
                        <option key={col.fieldName} value={col.fieldName}>
                          {col.fieldName}
                        </option>
                      ))}
                  </select>
                  {sortColumn && (
                    <button
                      onClick={() => toggleSort(sortColumn)}
                      className="text-gray-600 dark:text-gray-300 hover:text-blue-500 p-1"
                      title="Sıralama yönünü değiştir"
                    >
                      {sortOrder === 'asc' ? <FaSortAmountUp className="w-3 h-3" /> : <FaSortAmountDown className="w-3 h-3" />}
                    </button>
                  )}
                </div>
              )}
              
              <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>
          </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!]
                  const isSelected = selectedKeys.has(rowId)
                  const isFocused = focusedCardIndex === idx
                  const isHovered = hoveredCardKey === rowId

                  return (
                    <CardItem
                      ref={(el) => (cardRefs.current[idx] = el)}
                      isSubForm={true}
                      key={rowId || idx}
                      row={row}
                      gridDto={gridDto}
                      listFormCode={listFormCode}
                      dataSource={gridDataSource}
                      refreshData={loadData}
                      getCachedLookupDataSource={getLookupDataSource}
                      isSelected={isSelected}
                      isFocused={isFocused}
                      isHovered={isHovered}
                      onSelectionChange={(checked) => handleCardSelection(rowId, checked)}
                      onClick={(e) => handleCardClick(rowId, idx, e)}
                      onDoubleClick={() => handleCardDoubleClick(rowId, row)}
                      onMouseEnter={() => setHoveredCardKey(rowId)}
                      onMouseLeave={() => setHoveredCardKey(null)}
                      tabIndex={isFocused ? 0 : -1}
                    />
                  )
                })}
            </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
