"use client";

/**
 * SingleTableWithSticky — shared table renderer
 *
 * 2026-05-19 FlowWidget hard blocker 제거를 위해 legacy
 * `lib/registry/components/table-list/SingleTableWithSticky.tsx` 에서 이동.
 *
 * 2026-05-20 v2-table-list 의 중복 sticky 구현을 흡수. `variant="v2"` prop 으로
 * v2 전용 헤더/행/셀 스타일, 인라인 편집(category/code select, date picker fallback,
 * number input), mobile scroll/minWidth, null/undefined/"" → "-" 표시(0 은 값) 분기.
 *
 * 이 파일은 legacy `table-list` / `v2-table-list` / FlowWidget 모두에서 공유한다.
 * legacy table-list / v2-table-list local type files 를 import 하지 않는다. 본 파일이 자체 minimal
 * `ColumnConfig` 를 export 한다.
 */

import React from "react";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Checkbox } from "@/components/ui/checkbox";
import { ArrowUp, ArrowDown } from "lucide-react";
import { cn } from "@/lib/utils";
import { useScreenMultiLang } from "@/contexts/ScreenMultiLangContext";

/**
 * SingleTableWithSticky 가 실제 사용하는 컬럼 메타 minimal 정의.
 *
 * legacy table-list / v2-table-list 의 `ColumnConfig` 가
 * 이 type 의 superset 이므로 구조적으로 호환된다. 따라서 legacy 호출부에서는
 * 별도 변환 없이 그대로 전달 가능.
 */
export interface ColumnConfig {
  columnName: string;
  displayName?: string;
  sortable?: boolean;
  align?: "left" | "center" | "right";
  format?: string;
  fixed?: "left" | "right" | false;
  hidden?: boolean;
  width?: number;
  langKey?: string;
  [key: string]: any;
}

export type SingleTableVariant = "default" | "v2";

interface SingleTableWithStickyProps<TColumn extends ColumnConfig = ColumnConfig> {
  /** 시각/동작 분기 — 기본은 table-list / FlowWidget 기존 스타일, "v2" 는 v2-table-list 흡수 분기 */
  variant?: SingleTableVariant;
  visibleColumns?: TColumn[];
  columns?: TColumn[];
  data: Record<string, any>[];
  columnLabels: Record<string, string>;
  sortColumn: string | null;
  sortDirection: "asc" | "desc";
  tableConfig?: any;
  isDesignMode?: boolean;
  isAllSelected?: boolean;
  handleSort?: (columnName: string) => void;
  onSort?: (columnName: string) => void;
  handleSelectAll?: (checked: boolean) => void;
  handleRowClick?: (row: any, index: number, e: React.MouseEvent) => void;
  renderCheckboxCell?: (row: any, index: number) => React.ReactNode;
  renderCheckboxHeader?: () => React.ReactNode;
  /** v2 에서는 ReactNode (이미지/JSX) 반환 가능. 기본 호출부는 string 반환해도 ReactNode subset 이라 호환 */
  formatCellValue: (
    value: any,
    format?: string,
    columnName?: string,
    rowData?: Record<string, any>,
  ) => React.ReactNode;
  getColumnWidth: (column: TColumn) => number;
  containerWidth?: string;
  loading?: boolean;
  error?: string | null;
  onCellDoubleClick?: (rowIndex: number, colIndex: number, columnName: string, value: any) => void;
  editingCell?: { rowIndex: number; colIndex: number; columnName: string; originalValue: any } | null;
  editingValue?: string;
  onEditingValueChange?: (value: string) => void;
  onEditKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
  editInputRef?: React.RefObject<HTMLInputElement | null>;
  /** v2 전용: Enter/blur 시 저장 콜백 (date picker fallback 포함 통합 저장 경로) */
  onEditSave?: () => void;
  /** v2 전용: 컬럼별 inputType (select/category/code, number, date, datetime) */
  columnMeta?: Record<string, { inputType?: string }>;
  /** v2 전용: category/code 컬럼의 옵션 매핑 */
  categoryMappings?: Record<string, Record<string, { label: string }>>;
  searchHighlights?: Set<string>;
  currentSearchIndex?: number;
  searchTerm?: string;
}

export function SingleTableWithSticky<TColumn extends ColumnConfig = ColumnConfig>({
  variant = "default",
  visibleColumns,
  columns,
  data,
  columnLabels,
  sortColumn,
  sortDirection,
  tableConfig,
  isDesignMode = false,
  isAllSelected = false,
  handleSort,
  onSort,
  handleSelectAll,
  handleRowClick,
  renderCheckboxCell,
  renderCheckboxHeader,
  formatCellValue,
  getColumnWidth,
  containerWidth,
  loading = false,
  error = null,
  onCellDoubleClick,
  editingCell,
  editingValue,
  onEditingValueChange,
  onEditKeyDown,
  editInputRef,
  onEditSave,
  columnMeta,
  categoryMappings,
  searchHighlights,
  currentSearchIndex = 0,
  searchTerm = "",
}: SingleTableWithStickyProps<TColumn>) {
  const { getTranslatedText } = useScreenMultiLang();
  const checkboxConfig = tableConfig?.checkbox || {};
  const actualColumns = visibleColumns || columns || [];
  const sortHandler = onSort || handleSort || (() => {});
  const actualData = data || [];

  const isV2 = variant === "v2";

  // ── 컨테이너/스크롤 분기 (v2 만 mobile scroll + minWidth 적용) ──
  const scrollContainerStyle: React.CSSProperties = isV2 ? { WebkitOverflowScrolling: "touch" } : {};
  const tableStyle: React.CSSProperties = {
    width: "100%",
    tableLayout: "auto",
    boxSizing: "border-box",
    ...(isV2 ? { minWidth: `${Math.max(actualColumns.length * 80, 400)}px` } : {}),
  };

  // ── 헤더 스타일 분기 ──
  const headerBaseClass = isV2 ? "border-b border-border/60" : "bg-background border-b";
  const headerStyle: React.CSSProperties = isV2 ? { backgroundColor: "hsl(var(--muted) / 0.4)" } : {};
  const headerRowClass = isV2 ? "border-b border-border/60" : "border-b";

  return (
    <div
      className="bg-background relative flex flex-1 flex-col overflow-hidden shadow-sm"
      style={{
        width: "100%",
        height: "100%",
        boxSizing: "border-box",
      }}
    >
      <div className="relative flex-1 overflow-auto" style={scrollContainerStyle}>
        <Table noWrapper className="w-full" style={tableStyle}>
          <TableHeader
            className={cn(headerBaseClass, tableConfig?.stickyHeader && "sticky top-0 z-30 shadow-sm")}
            style={headerStyle}
          >
            <TableRow className={headerRowClass}>
              {actualColumns.map((column, colIndex) => {
                const leftFixedWidth = actualColumns
                  .slice(0, colIndex)
                  .filter((col) => col.fixed === "left")
                  .reduce((sum, col) => sum + getColumnWidth(col), 0);

                const rightFixedColumns = actualColumns.filter((col) => col.fixed === "right");
                const rightFixedIndex = rightFixedColumns.findIndex((col) => col.columnName === column.columnName);
                const rightFixedWidth =
                  rightFixedIndex >= 0
                    ? rightFixedColumns.slice(rightFixedIndex + 1).reduce((sum, col) => sum + getColumnWidth(col), 0)
                    : 0;

                const isCheckboxCol = column.columnName === "__checkbox__";

                const headCheckboxBaseClass = isV2
                  ? "h-9 border-0 px-3 py-1.5 text-center align-middle sm:px-4 sm:py-2"
                  : "bg-background h-9 border-0 px-3 py-1.5 text-center align-middle sm:px-4 sm:py-2";
                const headDataBaseClass = isV2
                  ? "text-muted-foreground hover:text-foreground h-9 cursor-pointer border-0 px-3 py-1.5 text-left align-middle text-[10px] font-bold uppercase tracking-[0.04em] whitespace-nowrap transition-all duration-200 select-none sm:px-4 sm:py-2 sm:text-xs"
                  : "text-foreground hover:text-foreground bg-background h-9 cursor-pointer border-0 px-3 py-1.5 text-left align-middle text-xs font-semibold whitespace-nowrap transition-all duration-200 select-none sm:px-4 sm:py-2 sm:text-sm";
                const sortableHoverClass = isV2 ? "hover:bg-muted/50" : "hover:bg-primary/10";

                // ── 셀 너비 / 헤더 width 분기 (v2 의 checkbox 48px 강제) ──
                const checkboxFixedWidth = 48;
                const headWidth = isV2 && isCheckboxCol ? checkboxFixedWidth : getColumnWidth(column);
                const headMinWidth = isV2 && isCheckboxCol ? "48px" : "100px";
                const headMaxWidth = isV2 && isCheckboxCol ? "48px" : "300px";
                const headBackground = isV2 ? "hsl(var(--muted) / 0.4)" : "hsl(var(--background))";

                return (
                  <TableHead
                    key={column.columnName}
                    className={cn(
                      isCheckboxCol ? headCheckboxBaseClass : headDataBaseClass,
                      `text-${column.align}`,
                      column.sortable && sortableHoverClass,
                      column.fixed === "left" && "border-border bg-background sticky z-40 border-r shadow-sm",
                      column.fixed === "right" && "border-border bg-background sticky z-40 border-l shadow-sm",
                      isDesignMode && column.hidden && "bg-muted/50 opacity-40",
                    )}
                    style={{
                      width: headWidth,
                      minWidth: headMinWidth,
                      maxWidth: headMaxWidth,
                      boxSizing: "border-box",
                      overflow: "hidden",
                      textOverflow: "ellipsis",
                      whiteSpace: "nowrap",
                      backgroundColor: headBackground,
                      ...(column.fixed === "left" && { left: leftFixedWidth }),
                      ...(column.fixed === "right" && { right: rightFixedWidth }),
                    }}
                    onClick={() => column.sortable && sortHandler(column.columnName)}
                  >
                    <div className={cn("flex items-center", isV2 && isCheckboxCol ? "justify-center" : "gap-2")}>
                      {isCheckboxCol ? (
                        checkboxConfig.selectAll && (
                          <Checkbox
                            checked={isAllSelected}
                            onCheckedChange={handleSelectAll}
                            aria-label="전체 선택"
                            style={
                              isV2
                                ? {
                                    width: 16,
                                    height: 16,
                                    borderWidth: 1.5,
                                    borderColor: isAllSelected
                                      ? "hsl(var(--primary))"
                                      : "hsl(var(--muted-foreground) / 0.5)",
                                    zIndex: 1,
                                  }
                                : { zIndex: 1 }
                            }
                          />
                        )
                      ) : (
                        <>
                          <span className="flex-1 truncate">
                            {(column as any).langKey
                              ? getTranslatedText(
                                  (column as any).langKey,
                                  columnLabels[column.columnName] || column.displayName || column.columnName,
                                )
                              : columnLabels[column.columnName] || column.displayName || column.columnName}
                          </span>
                          {column.sortable && sortColumn === column.columnName && (
                            <span className="bg-background/50 ml-1 flex h-4 w-4 items-center justify-center rounded-md shadow-sm sm:ml-2 sm:h-5 sm:w-5">
                              {sortDirection === "asc" ? (
                                <ArrowUp className="text-primary h-2.5 w-2.5 sm:h-3.5 sm:w-3.5" />
                              ) : (
                                <ArrowDown className="text-primary h-2.5 w-2.5 sm:h-3.5 sm:w-3.5" />
                              )}
                            </span>
                          )}
                        </>
                      )}
                    </div>
                  </TableHead>
                );
              })}
            </TableRow>
          </TableHeader>

          <TableBody>
            {actualData.length === 0 ? (
              <TableRow>
                <TableCell colSpan={actualColumns.length || 1} className="py-12 text-center">
                  <div className="flex flex-col items-center justify-center space-y-3">
                    <div className="bg-muted flex h-12 w-12 items-center justify-center rounded-full">
                      <svg
                        className="text-muted-foreground h-6 w-6"
                        fill="none"
                        stroke="currentColor"
                        viewBox="0 0 24 24"
                      >
                        <path
                          strokeLinecap="round"
                          strokeLinejoin="round"
                          strokeWidth={2}
                          d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
                        />
                      </svg>
                    </div>
                    <span className="text-muted-foreground text-sm font-medium">데이터가 없습니다</span>
                    <span className="bg-muted text-muted-foreground rounded-full px-3 py-1 text-xs">
                      조건을 변경하여 다시 검색해보세요
                    </span>
                  </div>
                </TableCell>
              </TableRow>
            ) : (
              actualData.map((row, index) => {
                // ── 행 className 분기 (v2 alternate background + hoverEffect 기본 true) ──
                const rowClass = isV2
                  ? cn(
                      "cursor-pointer border-b border-border/50 transition-[background] duration-75",
                      index % 2 === 0 ? "bg-background" : "bg-muted/20",
                      tableConfig?.tableStyle?.hoverEffect !== false && "hover:bg-accent",
                    )
                  : cn(
                      "bg-background h-10 cursor-pointer border-b transition-colors",
                      tableConfig?.tableStyle?.hoverEffect && "hover:bg-muted/50",
                    );

                return (
                  <TableRow key={`row-${index}`} className={rowClass} onClick={(e) => handleRowClick?.(row, index, e)}>
                    {actualColumns.map((column, colIndex) => {
                      const leftFixedWidth = actualColumns
                        .slice(0, colIndex)
                        .filter((col) => col.fixed === "left")
                        .reduce((sum, col) => sum + getColumnWidth(col), 0);

                      const rightFixedColumns = actualColumns.filter((col) => col.fixed === "right");
                      const rightFixedIndex = rightFixedColumns.findIndex(
                        (col) => col.columnName === column.columnName,
                      );
                      const rightFixedWidth =
                        rightFixedIndex >= 0
                          ? rightFixedColumns
                              .slice(rightFixedIndex + 1)
                              .reduce((sum, col) => sum + getColumnWidth(col), 0)
                          : 0;

                      const isEditing = editingCell?.rowIndex === index && editingCell?.colIndex === colIndex;
                      const isCheckboxCol = column.columnName === "__checkbox__";

                      const cellKey = `${index}-${colIndex}`;
                      const cellValueStr = String(row[column.columnName] ?? "").toLowerCase();
                      const hasSearchTerm = searchTerm ? cellValueStr.includes(searchTerm.toLowerCase()) : false;

                      const isHighlighted =
                        !isCheckboxCol && hasSearchTerm && (searchHighlights?.has(cellKey) ?? false);

                      const highlightArray = searchHighlights ? Array.from(searchHighlights) : [];
                      const isCurrentSearchResult =
                        isHighlighted &&
                        currentSearchIndex >= 0 &&
                        currentSearchIndex < highlightArray.length &&
                        highlightArray[currentSearchIndex] === cellKey;

                      // ── 셀 값 분기 ──
                      // v2: null/undefined/"" → "-" 표시 (0 은 값 그대로), ReactElement 가능
                      // default: falsy 면 nbsp fallback
                      let rawCellValue: React.ReactNode;
                      let isReactElement = false;
                      if (isV2) {
                        const formatted = formatCellValue(row[column.columnName], column.format, column.columnName, row);
                        if (formatted === null || formatted === undefined || formatted === "") {
                          rawCellValue = <span className="text-muted-foreground/50">-</span>;
                          isReactElement = true;
                        } else {
                          rawCellValue = formatted;
                          isReactElement = typeof formatted === "object" && React.isValidElement(formatted);
                        }
                      } else {
                        rawCellValue =
                          formatCellValue(row[column.columnName], column.format, column.columnName, row) || "\u00A0";
                      }

                      const renderCellContent = () => {
                        // ReactElement (v2 의 이미지/JSX) 는 그대로 렌더
                        if (isReactElement) {
                          return rawCellValue;
                        }

                        if (!isHighlighted || !searchTerm || isCheckboxCol) {
                          return rawCellValue;
                        }

                        const strValue = String(rawCellValue);
                        const lowerValue = strValue.toLowerCase();
                        const lowerTerm = searchTerm.toLowerCase();
                        const startIndex = lowerValue.indexOf(lowerTerm);

                        if (startIndex === -1) return rawCellValue;

                        const before = strValue.slice(0, startIndex);
                        const match = strValue.slice(startIndex, startIndex + searchTerm.length);
                        const after = strValue.slice(startIndex + searchTerm.length);

                        return (
                          <>
                            {before}
                            <mark
                              className={cn(
                                "rounded px-0.5",
                                isCurrentSearchResult
                                  ? "bg-orange-400 font-semibold text-white"
                                  : "bg-yellow-200 text-yellow-900",
                              )}
                            >
                              {match}
                            </mark>
                            {after}
                          </>
                        );
                      };

                      // ── 셀 className 분기 ──
                      const cellClass = isV2
                        ? cn(
                            "text-foreground h-10 align-middle text-[11px] transition-colors",
                            isCheckboxCol ? "px-0 py-[7px] text-center" : "px-3 py-[7px]",
                            !isReactElement && "whitespace-nowrap",
                            !isCheckboxCol && `text-${column.align}`,
                            column.fixed === "left" &&
                              "border-border bg-background/90 sticky z-10 border-r backdrop-blur-sm",
                            column.fixed === "right" &&
                              "border-border bg-background/90 sticky z-10 border-l backdrop-blur-sm",
                            onCellDoubleClick && !isCheckboxCol && "cursor-text",
                          )
                        : cn(
                            "text-foreground h-10 px-3 py-1.5 align-middle text-xs whitespace-nowrap transition-colors sm:px-4 sm:py-2 sm:text-sm",
                            `text-${column.align}`,
                            column.fixed === "left" &&
                              "border-border bg-background/90 sticky z-10 border-r backdrop-blur-sm",
                            column.fixed === "right" &&
                              "border-border bg-background/90 sticky z-10 border-l backdrop-blur-sm",
                            onCellDoubleClick && !isCheckboxCol && "cursor-text",
                          );

                      // ── 셀 width/style 분기 (v2 의 checkbox 48px) ──
                      const cellFixedWidth = isV2 && isCheckboxCol ? 48 : getColumnWidth(column);
                      const cellMinWidth = isV2 && isCheckboxCol ? "48px" : "100px";
                      const cellMaxWidth = isV2 && isCheckboxCol ? "48px" : "300px";
                      const cellOverflowStyle: React.CSSProperties =
                        isV2 && isReactElement
                          ? {}
                          : { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" };

                      return (
                        <TableCell
                          key={`cell-${column.columnName}`}
                          id={isCurrentSearchResult ? "current-search-result" : undefined}
                          className={cellClass}
                          style={{
                            width: cellFixedWidth,
                            minWidth: cellMinWidth,
                            maxWidth: cellMaxWidth,
                            boxSizing: "border-box",
                            ...cellOverflowStyle,
                            ...(column.fixed === "left" && { left: leftFixedWidth }),
                            ...(column.fixed === "right" && { right: rightFixedWidth }),
                          }}
                          onDoubleClick={(e) => {
                            if (onCellDoubleClick && !isCheckboxCol) {
                              e.stopPropagation();
                              onCellDoubleClick(index, colIndex, column.columnName, row[column.columnName]);
                            }
                          }}
                        >
                          {isCheckboxCol ? (
                            renderCheckboxCell?.(row, index)
                          ) : isEditing ? (
                            isV2 ? (
                              // ── v2 인라인 편집: inputType 에 따라 select(category/code), date/datetime, number, text ──
                              (() => {
                                const meta = columnMeta?.[column.columnName];
                                const inputType = meta?.inputType ?? (column as { inputType?: string }).inputType;
                                const isNumeric = inputType === "number" || inputType === "decimal";
                                const isCategoryType = inputType === "category" || inputType === "code";
                                const categoryOptions = categoryMappings?.[column.columnName];
                                const hasCategoryOptions =
                                  isCategoryType && categoryOptions && Object.keys(categoryOptions).length > 0;

                                const commonInputClass =
                                  "border-primary bg-background focus:ring-primary h-8 w-full shrink-0 rounded border px-2 text-xs focus:ring-2 focus:outline-none sm:text-sm";
                                const handleBlurSave = () => {
                                  if (onEditKeyDown) {
                                    const fakeEvent = {
                                      key: "Enter",
                                      preventDefault: () => {},
                                    } as React.KeyboardEvent<HTMLInputElement>;
                                    onEditKeyDown(fakeEvent);
                                  }
                                  onEditSave?.();
                                };

                                if (hasCategoryOptions) {
                                  const selectOptions = Object.entries(categoryOptions).map(([value, info]) => ({
                                    value,
                                    label: info.label,
                                  }));
                                  return (
                                    <select
                                      ref={editInputRef as unknown as React.RefObject<HTMLSelectElement>}
                                      value={editingValue ?? ""}
                                      onChange={(e) => onEditingValueChange?.(e.target.value)}
                                      onKeyDown={onEditKeyDown as unknown as React.KeyboardEventHandler<HTMLSelectElement>}
                                      onBlur={handleBlurSave}
                                      className={cn(commonInputClass, "h-8")}
                                      onClick={(e) => e.stopPropagation()}
                                    >
                                      <option value="">선택하세요</option>
                                      {selectOptions.map((opt) => (
                                        <option key={opt.value} value={opt.value}>
                                          {opt.label}
                                        </option>
                                      ))}
                                    </select>
                                  );
                                }

                                if (inputType === "date" || inputType === "datetime") {
                                  try {
                                    // 외부 의존 모듈 — runtime require 실패 시 일반 text input 으로 폴백
                                    // eslint-disable-next-line @typescript-eslint/no-require-imports
                                    const { InlineCellDatePicker } = require("@/components/screen/filters/InlineCellDatePicker");
                                    return (
                                      <InlineCellDatePicker
                                        value={editingValue ?? ""}
                                        onChange={(v: string) => onEditingValueChange?.(v)}
                                        onSave={handleBlurSave}
                                        onKeyDown={onEditKeyDown}
                                        inputRef={editInputRef}
                                      />
                                    );
                                  } catch {
                                    return (
                                      <input
                                        ref={editInputRef}
                                        type="text"
                                        value={editingValue ?? ""}
                                        onChange={(e) => onEditingValueChange?.(e.target.value)}
                                        onKeyDown={onEditKeyDown}
                                        onBlur={handleBlurSave}
                                        className={commonInputClass}
                                        onClick={(e) => e.stopPropagation()}
                                      />
                                    );
                                  }
                                }

                                return (
                                  <input
                                    ref={editInputRef}
                                    type={isNumeric ? "number" : "text"}
                                    value={editingValue ?? ""}
                                    onChange={(e) => onEditingValueChange?.(e.target.value)}
                                    onKeyDown={onEditKeyDown}
                                    onBlur={handleBlurSave}
                                    className={commonInputClass}
                                    style={isNumeric ? { textAlign: "right" } : undefined}
                                    onClick={(e) => e.stopPropagation()}
                                  />
                                );
                              })()
                            ) : (
                              // ── 기본 인라인 편집: 단순 text input (table-list / FlowWidget 기존 동작) ──
                              <input
                                ref={editInputRef}
                                type="text"
                                value={editingValue ?? ""}
                                onChange={(e) => onEditingValueChange?.(e.target.value)}
                                onKeyDown={onEditKeyDown}
                                onBlur={() => {
                                  if (onEditKeyDown) {
                                    const fakeEvent = {
                                      key: "Enter",
                                      preventDefault: () => {},
                                    } as React.KeyboardEvent<HTMLInputElement>;
                                    onEditKeyDown(fakeEvent);
                                  }
                                }}
                                className="border-primary bg-background focus:ring-primary h-8 w-full rounded border px-2 text-xs focus:ring-2 focus:outline-none sm:text-sm"
                                onClick={(e) => e.stopPropagation()}
                              />
                            )
                          ) : (
                            renderCellContent()
                          )}
                        </TableCell>
                      );
                    })}
                  </TableRow>
                );
              })
            )}
          </TableBody>
        </Table>
      </div>
    </div>
  );
}
