import { EditingFormItemDto, GridDto, PlatformEditorTypes } from "@/proxy/form/models"
import { useLocalization } from "@/utils/hooks/useLocalization"
import { usePermission } from "@/utils/hooks/usePermission"
import { usePWA } from "@/utils/hooks/usePWA"
import CustomStore from "devextreme/data/custom_store"
import { useMemo, useRef, useState, forwardRef, memo, useEffect } from "react"
import { useNavigate } from "react-router-dom"
import { GroupItem } from 'devextreme/ui/form'
import { PermissionResults, SimpleItemWithColData } from "../form/types"
import { captionize } from 'devextreme/core/utils/inflector'
import { ROUTES_ENUM } from "@/routes/route.constant"
import FormButtons from "../form/FormButtons"
import FormDevExpress from "../form/FormDevExpress"
import { FormRef } from "devextreme-react/cjs/form"
import { Checkbox } from "@/components/ui"
import classNames from "classnames"

interface CardItemProps {
  isSubForm?: boolean
  row: any
  gridDto: GridDto
  listFormCode: string
  dataSource: CustomStore
  refreshData: () => void
  getCachedLookupDataSource: (editorOptions: any, colData: any, row?: any) => any
  // Selection and interaction props
  isSelected?: boolean
  isFocused?: boolean
  isHovered?: boolean
  onSelectionChange?: (checked: boolean) => void
  onClick?: (e: React.MouseEvent) => void
  onDoubleClick?: () => void
  onMouseEnter?: () => void
  onMouseLeave?: () => void
  tabIndex?: number
}

const CardItem = forwardRef<HTMLDivElement, CardItemProps>((
  {
    isSubForm,
    row,
    gridDto,
    listFormCode,
    dataSource,
    refreshData,
    getCachedLookupDataSource,
    isSelected = false,
    isFocused = false,
    isHovered = false,
    onSelectionChange,
    onClick,
    onDoubleClick,
    onMouseEnter,
    onMouseLeave,
    tabIndex = -1,
  },
  ref
) => {
  // Selection mode'u gridDto'dan al
  const selectionMode = 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])
  const [formData, setFormData] = useState(row)
  const refForm = useRef<FormRef>(null)
  const cardElementRef = useRef<HTMLDivElement | null>(null)
  const navigate = useNavigate()
  const { translate } = useLocalization()
  const { checkPermission } = usePermission()
  const isPwaMode = usePWA()
  
  // Lazy load form with Intersection Observer - sadece görünür kartları render et
  const [shouldRenderForm, setShouldRenderForm] = useState(false)
  
  useEffect(() => {
    const element = cardElementRef.current
    if (!element) return
    
    // Intersection Observer ile görünürlük kontrolü
    const observer = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            // Kart görünür hale geldiğinde form'u render et
            setShouldRenderForm(true)
            // Bir kez render edildikten sonra observer'ı kaldır
            observer.disconnect()
          }
        })
      },
      {
        rootMargin: '50px', // 50px önceden yüklemeye başla
        threshold: 0.01, // %1 görünür olduğunda tetikle
      }
    )
    
    observer.observe(element)
    
    return () => {
      observer.disconnect()
    }
  }, [])

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

  // Form Items - memoized to prevent recalculation on every render
  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,
                label: { text: colData?.captionName ? translate('::' + colData?.captionName) : 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,
                editorScript: i.editorScript,
              }
              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, translate])

  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
      ref={(element) => {
        // Forward ref to parent
        if (typeof ref === 'function') {
          ref(element)
        } else if (ref) {
          ref.current = element
        }
        // Also save to local ref for Intersection Observer
        cardElementRef.current = element
      }}
      tabIndex={tabIndex}
      onClick={onClick}
      onDoubleClick={onDoubleClick}
      onMouseEnter={onMouseEnter}
      onMouseLeave={onMouseLeave}
      className={classNames(
        "bg-white dark:bg-neutral-800 border flex flex-col transition-all duration-200 outline-none",
        {
          "border-blue-500 shadow-lg ring-2 ring-blue-300": isSelected,
          "border-blue-400 shadow-md": isFocused && !isSelected,
          "border-gray-300 dark:border-neutral-600": !isSelected && !isFocused,
          "shadow-md transform scale-[1.02]": isHovered,
          "cursor-pointer": selectionMode !== 'none',
        }
      )}
      role="article"
      aria-selected={isSelected}
      aria-label={`Card ${rowId}`}
    >
      <div
        className={`flex items-center pt-2 px-2 gap-2 ${isSubForm ? 'justify-between' : 'justify-between'}`}
      >
        <div className="flex items-center gap-2">
          {selectionMode !== 'none' && onSelectionChange && (
            <div 
              onClick={(e) => {
                e.stopPropagation()
                onSelectionChange(!isSelected)
              }}
            >
              <Checkbox
                checked={isSelected}
                onChange={(checked: boolean) => {
                  onSelectionChange(checked)
                }}
                className="cursor-pointer"
                aria-label="Select card"
              />
            </div>
          )}
          
          {!isSubForm && (
            <h3>{translate('::' + gridDto?.gridOptions.title)}</h3>
          )}
        </div>
        
        {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">
        {shouldRenderForm ? (
          <FormDevExpress
            listFormCode={listFormCode}
            mode="view"
            refForm={refForm}
            formData={formData}
            formItems={formItems}
            setFormData={setFormData}
          />
        ) : (
          <div className="p-4">
            <div className="animate-pulse space-y-2">
              <div className="h-4 bg-gray-200 dark:bg-gray-700 rounded w-3/4"></div>
              <div className="h-4 bg-gray-200 dark:bg-gray-700 rounded w-1/2"></div>
            </div>
          </div>
        )}
      </div>
    </div>
  )
})

CardItem.displayName = 'CardItem'

// Memoize to prevent unnecessary re-renders when parent re-renders
export default memo(CardItem, (prevProps, nextProps) => {
  // Custom comparison to prevent re-render when not needed
  return (
    prevProps.row === nextProps.row &&
    prevProps.isSelected === nextProps.isSelected &&
    prevProps.isFocused === nextProps.isFocused &&
    prevProps.isHovered === nextProps.isHovered &&
    prevProps.gridDto === nextProps.gridDto &&
    prevProps.listFormCode === nextProps.listFormCode
  )
})