"use client"

import * as React from "react"
import { flexRender, type Table as TanstackTable } from "@tanstack/react-table"
import { ChevronRight, ChevronUp, Loader2 } from "lucide-react"
import { useIntersection } from "@mantine/hooks"

import { cn } from "@/lib/utils"
import { getCommonPinningStylesWithBorder } from "@/lib/data-table"
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"
import { Button } from "@/components/ui/button"
import { DataTableResizer } from "@/components/data-table/data-table-resizer"
import { useAutoSizeColumns } from "@/hooks/useAutoSizeColumns"

interface InfiniteDataTableProps<TData> extends React.HTMLAttributes<HTMLDivElement> {
  table: TanstackTable<TData>
  floatingBar?: React.ReactNode | null
  autoSizeColumns?: boolean
  compact?: boolean
  // 무한 스크롤 관련 props
  hasNextPage?: boolean
  isLoadingMore?: boolean
  onLoadMore?: () => void
  totalCount?: number | null
  isEmpty?: boolean
}

/**
 * 무한 스크롤 지원 DataTable
 */
export function InfiniteDataTable<TData>({
  table,
  floatingBar = null,
  autoSizeColumns = true,
  compact = false,
  hasNextPage = false,
  isLoadingMore = false,
  onLoadMore,
  totalCount = null,
  isEmpty = false,
  children,
  className,
  maxHeight,
  ...props
}: InfiniteDataTableProps<TData> & { maxHeight?: string | number }) {

  useAutoSizeColumns(table, autoSizeColumns)

  // nested header 감지: columns 속성을 가진 헤더가 있는지 확인
  const hasNestedHeader = React.useMemo(() => {
    return table.getHeaderGroups().some(headerGroup =>
      headerGroup.headers.some(header => 'columns' in header.column.columnDef)
    )
  }, [table])

  // 🎯 스크롤 상태 감지 추가
  const [isScrolled, setIsScrolled] = React.useState(false)

  // Intersection Observer for infinite scroll
  const { ref: loadMoreRef, entry } = useIntersection({
    threshold: 0.1,
  })

  // 자동 로딩 트리거
  React.useEffect(() => {
    if (entry?.isIntersecting && hasNextPage && !isLoadingMore && onLoadMore) {
      onLoadMore()
    }
  }, [entry?.isIntersecting, hasNextPage, isLoadingMore, onLoadMore])

  // 🎯 스크롤 핸들러 추가
  const handleScroll = (e: React.UIEvent<HTMLDivElement>) => {
    const scrollLeft = e.currentTarget.scrollLeft
    setIsScrolled(scrollLeft > 0)
  }

  // 🎯 동적 핀 스타일 함수 (width 중복 제거)
  const getPinnedStyle = (column: any, isHeader: boolean = false) => {
    const baseStyle = getCommonPinningStylesWithBorder({ column })
    const pinnedSide = column.getIsPinned()
    
    // width를 제외한 나머지 스타일만 반환
    const { width, ...restBaseStyle } = baseStyle
    
    return {
      ...restBaseStyle,
      // 헤더는 핀 여부와 관계없이 항상 배경 유지 (sticky로 고정되어 있기 때문)
      ...(isHeader && {
        background: "hsl(var(--background))",
        transition: "none",
      }),
      // 바디 셀은 핀된 경우에만 스크롤 상태에 따라 동적 변경
      ...(!isHeader && pinnedSide && {
        background: isScrolled 
          ? "hsl(var(--background))" 
          : "transparent",
        transition: "background-color 0.15s ease-out",
      }),
    }
  }

  // 🎯 테이블 총 너비 계산
  const getTableWidth = React.useCallback(() => {
    const totalSize = table.getCenterTotalSize() + table.getLeftTotalSize() + table.getRightTotalSize()
    return Math.max(totalSize, 800) // 최소 800px 보장
  }, [table])

  // 컴팩트 모드를 위한 클래스 정의
  const compactStyles = compact ? {
    row: "h-7",
    cell: "py-1 px-2 text-sm",
    header: "py-1 px-2 text-sm", // 헤더 스타일 추가
    headerRow: "h-8", // 헤더 행 높이 추가
    groupRow: "py-1 bg-muted/20 text-sm",
    emptyRow: "h-16",
  } : {
    row: "",
    cell: "",
    header: "", // 헤더 스타일 추가
    headerRow: "", // 헤더 행 높이 추가
    groupRow: "bg-muted/20",
    emptyRow: "h-24",
  }

  return (
    <div className={cn("w-full space-y-2.5", className)} {...props}>
      {children}
      
      {/* 총 개수 표시 */}
      {totalCount !== null && (
        <div className="text-sm text-muted-foreground">
          총 {totalCount.toLocaleString()}개 항목
          {table.getRowModel().rows.length > 0 && (
            <span className="ml-2">
              (현재 {table.getRowModel().rows.length.toLocaleString()}개 로드됨)
            </span>
          )}
        </div>
      )}

      <div 
        className="max-w-[100vw] overflow-auto" 
        style={{ maxHeight: maxHeight || '35rem' }}
        onScroll={handleScroll} // 🎯 스크롤 이벤트 핸들러 추가
      >
        <Table
          className={cn(
            "[&>thead]:sticky [&>thead]:top-0 [&>thead]:z-10",
            !hasNestedHeader && "table-fixed" // nested header가 없으면 table-fixed 적용
          )}>
          {/* nested header가 있으면 table-fixed 제거, 없으면 적용 */}
          {/* 테이블 헤더 */}
          <TableHeader>
            {table.getHeaderGroups().map((headerGroup) => (
              <TableRow key={headerGroup.id} className={compactStyles.headerRow}>
                {headerGroup.headers.map((header) => {
                  if (header.column.getIsGrouped()) {
                    return null
                  }

                  return (
                    <TableHead
                      key={header.id}
                      colSpan={header.colSpan}
                      data-column-id={header.column.id}
                      className={compactStyles.header}
                      style={{
                        ...getPinnedStyle(header.column, true), // 🎯 헤더임을 명시
                        // 부모 그룹 헤더는 colSpan으로 너비가 결정되므로 width 설정하지 않음
                        // 자식 헤더만 개별 width 설정
                        ...(!('columns' in header.column.columnDef) && { width: header.getSize() }),
                      }}
                    >
                      <div style={{ position: "relative" }}>
                        {header.isPlaceholder
                          ? null
                          : flexRender(
                            header.column.columnDef.header,
                            header.getContext()
                          )}

                        {/* 부모 그룹 헤더는 리사이즈 불가, 자식 헤더만 리사이즈 가능 */}
                        {header.column.getCanResize() && !('columns' in header.column.columnDef) && (
                          <DataTableResizer header={header} />
                        )}
                      </div>
                    </TableHead>
                  )
                })}
              </TableRow>
            ))}
          </TableHeader>

          {/* 테이블 바디 */}
          <TableBody>
            {table.getRowModel().rows?.length ? (
              <>
                {table.getRowModel().rows.map((row) => {
                  // 그룹핑 헤더 Row
                  if (row.getIsGrouped()) {
                    const groupingColumnId = row.groupingColumnId ?? ""
                    const groupingColumn = table.getColumn(groupingColumnId)

                    let columnLabel = groupingColumnId
                    if (groupingColumn) {
                      const headerDef = groupingColumn.columnDef.meta?.excelHeader
                      if (typeof headerDef === "string") {
                        columnLabel = headerDef
                      }
                    }

                    return (
                      <TableRow
                        key={row.id}
                        className={compactStyles.groupRow}
                        data-state={row.getIsExpanded() && "expanded"}
                      >
                        <TableCell 
                          colSpan={table.getVisibleFlatColumns().length}
                          className={compact ? "py-1 px-2" : ""}
                        >
                          {row.getCanExpand() && (
                            <button
                              onClick={row.getToggleExpandedHandler()}
                              className="inline-flex items-center justify-center mr-2 w-5 h-5"
                              style={{
                                marginLeft: `${row.depth * 1.5}rem`,
                              }}
                            >
                              {row.getIsExpanded() ? (
                                <ChevronUp size={compact ? 14 : 16} />
                              ) : (
                                <ChevronRight size={compact ? 14 : 16} />
                              )}
                            </button>
                          )}

                          <span className="font-semibold">
                            {columnLabel}: {row.getValue(groupingColumnId)}
                          </span>
                          <span className="ml-2 text-xs text-muted-foreground">
                            ({row.subRows.length} rows)
                          </span>
                        </TableCell>
                      </TableRow>
                    )
                  }

                  // 일반 Row
                  return (
                    <TableRow
                      key={row.id}
                      className={compactStyles.row}
                      data-state={row.getIsSelected() && "selected"}
                    >
                      {row.getVisibleCells().map((cell) => {
                        if (cell.column.getIsGrouped()) {
                          return null
                        }

                        return (
                          <TableCell
                            key={cell.id}
                            data-column-id={cell.column.id}
                            className={compactStyles.cell}
                            style={{
                              ...getPinnedStyle(cell.column, false), // 🎯 바디 셀임을 명시
                              width: cell.column.getSize(), // 🎯 width 별도 설정
                            }}
                          >
                            {flexRender(
                              cell.column.columnDef.cell,
                              cell.getContext()
                            )}
                          </TableCell>
                        )
                      })}
                    </TableRow>
                  )
                })}
              </>
            ) : isEmpty ? (
              // 데이터가 없을 때
              <TableRow>
                <TableCell
                  colSpan={table.getAllColumns().length}
                  className={compactStyles.emptyRow + " text-center"}
                >
                  No results.
                </TableCell>
              </TableRow>
            ) : null}
          </TableBody>
        </Table>
      </div>

      {/* 무한 스크롤 로딩 영역 */}
      <div className="flex flex-col items-center space-y-4 py-4">
        {hasNextPage && (
          <>
            {/* Intersection Observer 타겟 */}
            <div ref={loadMoreRef} className="h-1" />
            
            {isLoadingMore && (
              <div className="flex items-center space-x-2">
                <Loader2 className="h-4 w-4 animate-spin" />
                <span className="text-sm text-muted-foreground">
                  로딩 중...
                </span>
              </div>
            )}
            
            {/* 수동 로드 버튼 (자동 로딩 실패 시 대안) */}
            {!isLoadingMore && onLoadMore && (
              <Button
                variant="outline"
                onClick={onLoadMore}
                className="w-full max-w-md"
              >
                더 보기
              </Button>
            )}
          </>
        )}
        
        {!hasNextPage && table.getRowModel().rows.length > 0 && (
          <p className="text-sm text-muted-foreground">
            모든 데이터를 불러왔습니다.
          </p>
        )}
      </div>

      <div className="flex flex-col gap-2.5">
        {/* 선택된 행 정보 */}
        {table.getFilteredSelectedRowModel().rows.length > 0 && (
          <div className="text-sm text-muted-foreground">
            {table.getFilteredSelectedRowModel().rows.length} of{" "}
            {table.getRowModel().rows.length} row(s) selected.
          </div>
        )}

        {/* Floating Bar (선택된 행 있을 때) */}
        {table.getFilteredSelectedRowModel().rows.length > 0 && floatingBar}
      </div>
    </div>
  )
}