"use client"

import * as React from "react"
import { RowData, type Table } from "@tanstack/react-table"
import {
  Check,
  ChevronsUpDown,
  GripVertical,
  Settings2,
} from "lucide-react"

import { cn, toSentenceCase } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from "@/components/ui/command"
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover"
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@/components/ui/tooltip"

// Sortable
import {
  Sortable,
  SortableItem,
  SortableDragHandle,
} from "@/components/ui/sortable"


/**
 * ViewOptionsProps:
 * - table: TanStack Table instance
 * - resetAutoSize: Function to reset autosize calculations (optional)
 */
interface DataTableViewOptionsProps<TData> {
  table: Table<TData>
  resetAutoSize?: () => void
}

declare module "@tanstack/table-core" {
  interface ColumnMeta<TData extends RowData, TValue> {
    excelHeader?: string
    group?: string
    type?: string
    // ...anything else you want
  }
}
/**
 * DataTableViewOptions:
 * - Renders a Popover with hideable columns
 * - Lets user reorder columns (drag & drop) + toggle visibility
 */
export function DataTableViewOptions<TData>({
  table,
  resetAutoSize,
}: DataTableViewOptionsProps<TData>) {
  const triggerRef = React.useRef<HTMLButtonElement>(null)

  // 1) Identify columns that can be hidden
  const hideableCols = React.useMemo(() => {
    return table
      .getAllLeafColumns()
      .filter((col) =>  col.getCanHide())
  }, [table])


  // 2) local state for "columnOrder" (just the ID of hideable columns)
  //    We'll reorder these with drag & drop
  const [columnOrder, setColumnOrder] = React.useState<string[]>(() =>
    hideableCols.map((c) => c.id)
  )

  // 3) onMove: when user finishes drag
  //    - update local `columnOrder` only (no table.setColumnOrder yet)
  const handleMove = React.useCallback(
    ({ activeIndex, overIndex }: { activeIndex: number; overIndex: number }) => {
      setColumnOrder((prev) => {
        const newOrder = [...prev]
        const [removed] = newOrder.splice(activeIndex, 1)
        newOrder.splice(overIndex, 0, removed)
        return newOrder
      })
    },
    []
  )

  // 4) After local state changes, reflect in tanstack table
  //    - We do this in useEffect to avoid "update a different component" error
  React.useEffect(() => {
    // Also consider "non-hideable" columns, if any, to keep them in original positions
    const nonHideable = table
      .getAllColumns()
      .filter((col) => !hideableCols.some((hc) => hc.id === col.id))
      .map((c) => c.id)

    // e.g. place nonHideable at the front, then our local hideable order
    const finalOrder = [...nonHideable, ...columnOrder]

    // Now we set the table's official column order
    table.setColumnOrder(finalOrder)
    
    // Reset auto-size when column order changes
    resetAutoSize?.()
  }, [columnOrder, hideableCols, table, resetAutoSize])


  return (
    <Popover modal>
      <PopoverTrigger asChild>
        <Button
          ref={triggerRef}
          aria-label="Toggle columns"
          variant="outline"
          role="combobox"
          size="sm"
          className="gap-2"
        >
          <Settings2 className="size-4" />
          <span className="hidden sm:inline">보기</span>
          <ChevronsUpDown className="ml-auto size-4 shrink-0 opacity-50 hidden sm:inline" />
        </Button>
      </PopoverTrigger>

      <PopoverContent
        align="end"
        className="w-44 p-0"
        onCloseAutoFocus={() => triggerRef.current?.focus()}
      >
        <Command>
          <CommandInput placeholder="Search columns..." />
          <CommandList>
            <CommandEmpty>No columns found.</CommandEmpty>

            <CommandGroup>
              {/**
               * 5) Sortable: we pass an array of { id: string } from `columnOrder`,
               *    so we can reorder them with drag & drop
               */}
              <Sortable
                value={columnOrder.map((id) => ({ id }))}
                onMove={handleMove}
              >
                {columnOrder.map((colId) => {
                  // find column instance
                  const column = hideableCols.find((c) => c.id === colId)
    
                  if (!column) return null

                  const columnLabel = column?.columnDef?.meta?.excelHeader || column.id

                  return (
                    <SortableItem key={colId} value={colId} asChild>
                      <CommandItem
                        onSelect={() => {
                          column.toggleVisibility(!column.getIsVisible())
                          // Reset autosize calculations when toggling columns
                          resetAutoSize?.()
                        }}
                      >
                        {/* Drag handle on the left */}
                        <SortableDragHandle
                          variant="outline"
                          size="icon"
                          className="mr-2 size-5 shrink-0 rounded cursor-grab active:cursor-grabbing"
                        >
                          <GripVertical className="size-3.5" aria-hidden="true" />
                        </SortableDragHandle>

                        {/* label with tooltip for long names */}
                        <TooltipProvider>
                          <Tooltip>
                            <TooltipTrigger asChild>
                              <span className="truncate">
                                {columnLabel}
                              </span>
                            </TooltipTrigger>
                            <TooltipContent>
                              {columnLabel}
                            </TooltipContent>
                          </Tooltip>
                        </TooltipProvider>

                        {/* check if visible */}
                        <Check
                          className={cn(
                            "ml-auto size-4 shrink-0",
                            column.getIsVisible() ? "opacity-100" : "opacity-0"
                          )}
                        />
                      </CommandItem>
                    </SortableItem>
                  )
                })}
              </Sortable>
            </CommandGroup>
          </CommandList>
        </Command>
      </PopoverContent>
    </Popover>
  )
}