"use client";

import * as React from "react";
import { useVirtualizer } from "@tanstack/react-virtual";
import { cn } from "@/lib/utils";

const ROW_HEIGHT = 36;
const HEADER_HEIGHT = 40;

export type DealImportVirtualGridColumn<TRow> = {
  key: string;
  name: string;
  width: number;
  minWidth?: number;
  frozen?: boolean;
  editable?: boolean;
  renderHeaderCell?: () => React.ReactNode;
  renderCell: (props: {
    row: TRow;
    rowIdx: number;
    globalRowIdx: number;
  }) => React.ReactNode;
};

export type DealImportVirtualGridProps<TRow extends Record<string, unknown>> = {
  columns: DealImportVirtualGridColumn<TRow>[];
  rows: TRow[];
  rowOffset?: number;
  locked?: boolean;
  selectedPosition: { rowIdx: number; colIdx: number } | null;
  onSelectedCellChange: (position: { rowIdx: number; colIdx: number }) => void;
  onRowsChange: (rows: TRow[]) => void;
  getRowClassName?: (row: TRow) => string;
  isRowEditable?: (row: TRow) => boolean;
};

function getFrozenLeftOffset<TRow>(
  columns: DealImportVirtualGridColumn<TRow>[],
  columnIndex: number,
): number {
  let offset = 0;
  for (let i = 0; i < columnIndex; i++) {
    if (columns[i]?.frozen) {
      offset += columns[i].width;
    }
  }
  return offset;
}

export function DealImportVirtualGrid<TRow extends Record<string, unknown>>({
  columns,
  rows,
  rowOffset = 0,
  locked = false,
  selectedPosition,
  onSelectedCellChange,
  onRowsChange,
  getRowClassName,
  isRowEditable,
}: DealImportVirtualGridProps<TRow>) {
  const scrollRef = React.useRef<HTMLDivElement>(null);
  const [editingCell, setEditingCell] = React.useState<{
    rowIdx: number;
    colKey: string;
  } | null>(null);

  const rowVirtualizer = useVirtualizer({
    count: rows.length,
    getScrollElement: () => scrollRef.current,
    estimateSize: () => ROW_HEIGHT,
    overscan: 8,
    enabled: rows.length > 0,
    getItemKey: (index) => `${rowOffset + index}`,
  });

  const totalWidth = React.useMemo(
    () => columns.reduce((sum, column) => sum + column.width, 0),
    [columns],
  );

  const commitCellValue = React.useCallback(
    (rowIdx: number, colKey: string, value: string) => {
      const row = rows[rowIdx];
      if (!row) return;
      const nextRows = [...rows];
      nextRows[rowIdx] = { ...row, [colKey]: value };
      onRowsChange(nextRows);
      setEditingCell(null);
    },
    [onRowsChange, rows],
  );

  const virtualRows = rowVirtualizer.getVirtualItems();

  return (
    <div
      ref={scrollRef}
      className={cn(
        "h-full min-h-0 flex-1 overflow-auto border-t border-gray-100 bg-white",
        locked && "pointer-events-none opacity-50",
      )}
    >
      <div style={{ minWidth: totalWidth }}>
        <div
          className="sticky top-0 z-30 flex border-b border-gray-200 bg-[#f8f9ff]"
          style={{ height: HEADER_HEIGHT }}
        >
          {columns.map((column, colIdx) => {
            const frozenLeft = column.frozen
              ? getFrozenLeftOffset(columns, colIdx)
              : undefined;
            return (
              <div
                key={column.key}
                className={cn(
                  "flex shrink-0 items-center border-r border-gray-200 px-2 text-[11px] font-bold text-gray-800",
                  column.frozen && "sticky z-40 bg-[#f8f9ff]",
                )}
                style={{
                  width: column.width,
                  minWidth: column.minWidth ?? column.width,
                  left: frozenLeft,
                }}
              >
                {column.renderHeaderCell ? (
                  column.renderHeaderCell()
                ) : (
                  <span className="truncate">{column.name}</span>
                )}
              </div>
            );
          })}
        </div>

        <div
          className="relative w-full"
          style={{ height: rowVirtualizer.getTotalSize() }}
        >
          {virtualRows.map((virtualRow) => {
            const row = rows[virtualRow.index];
            if (!row) return null;

            const globalRowIdx = rowOffset + virtualRow.index;
            const rowClassName = getRowClassName?.(row) ?? "";
            const rowEditable = isRowEditable?.(row) ?? true;

            return (
              <div
                key={virtualRow.key}
                data-index={virtualRow.index}
                className={cn(
                  "absolute left-0 flex w-full border-b border-gray-100",
                  rowClassName,
                )}
                style={{
                  top: virtualRow.start,
                  height: virtualRow.size,
                }}
              >
                {columns.map((column, colIdx) => {
                  const frozenLeft = column.frozen
                    ? getFrozenLeftOffset(columns, colIdx)
                    : undefined;
                  const isSelected =
                    selectedPosition?.rowIdx === globalRowIdx &&
                    selectedPosition.colIdx === colIdx;
                  const isEditing =
                    editingCell?.rowIdx === virtualRow.index &&
                    editingCell.colKey === column.key;
                  const canEdit =
                    column.editable &&
                    rowEditable &&
                    !locked &&
                    !column.key.startsWith("__");

                  const cellBgClass = rowClassName.includes("bg-emerald")
                    ? "bg-emerald-50"
                    : rowClassName.includes("bg-red")
                      ? "bg-red-50"
                      : "bg-white";

                  return (
                    <div
                      key={column.key}
                      className={cn(
                        "flex shrink-0 items-center border-r border-gray-100 text-[13px] text-gray-800",
                        column.frozen && "sticky z-20",
                        column.frozen && cellBgClass,
                        isSelected && !isEditing && "bg-[#eef0ff]",
                        canEdit && !isEditing && "cursor-cell",
                      )}
                      style={{
                        width: column.width,
                        minWidth: column.minWidth ?? column.width,
                        left: frozenLeft,
                        height: ROW_HEIGHT,
                      }}
                      onClick={() => {
                        if (locked) return;
                        onSelectedCellChange({
                          rowIdx: globalRowIdx,
                          colIdx,
                        });
                        if (canEdit) {
                          setEditingCell({
                            rowIdx: virtualRow.index,
                            colKey: column.key,
                          });
                        }
                      }}
                    >
                      {isEditing ? (
                        <input
                          autoFocus
                          defaultValue={
                            row[column.key] != null
                              ? String(row[column.key])
                              : ""
                          }
                          className="h-full w-full border-none bg-[#eef0ff] px-2 text-[13px] outline-none"
                          onBlur={(event) =>
                            commitCellValue(
                              virtualRow.index,
                              column.key,
                              event.target.value,
                            )
                          }
                          onKeyDown={(event) => {
                            if (event.key === "Enter") {
                              commitCellValue(
                                virtualRow.index,
                                column.key,
                                (event.target as HTMLInputElement).value,
                              );
                            }
                            if (event.key === "Escape") {
                              setEditingCell(null);
                            }
                            event.stopPropagation();
                          }}
                          onClick={(event) => event.stopPropagation()}
                        />
                      ) : (
                        <div className="h-full w-full overflow-hidden">
                          {column.renderCell({
                            row,
                            rowIdx: virtualRow.index,
                            globalRowIdx,
                          })}
                        </div>
                      )}
                    </div>
                  );
                })}
              </div>
            );
          })}
        </div>

        {rows.length === 0 ? (
          <div className="flex h-24 items-center justify-center text-[13px] text-gray-400">
            No rows to display
          </div>
        ) : null}
      </div>
    </div>
  );
}
