"use client";

/**
 * SingleTableWithSticky — shared table renderer
 *
 * 2026-05-19 FlowWidget 의 sticky 테이블 구현을 흡수한 헬퍼.
 * 현재는 `frontend/components/screen/widgets/FlowWidget.tsx` 에서만 사용한다.
 *
 * 본 파일은 자체 minimal `ColumnConfig` 를 export 하며 외부 타입을 의존하지 않는다.
 * canonical table runtime 은 `frontend/lib/registry/components/table/TableComponent.tsx` 사용.
 */

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 정의.
 */
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;
}

interface SingleTableWithStickyProps<TColumn extends ColumnConfig = ColumnConfig> {
  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;
  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>;
  searchHighlights?: Set<string>;
  currentSearchIndex?: number;
  searchTerm?: string;
}

export function SingleTableWithSticky<TColumn extends ColumnConfig = ColumnConfig>({
  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,
  searchHighlights,
  currentSearchIndex = 0,
  searchTerm = "",
}: SingleTableWithStickyProps<TColumn>) {
  const { getTranslatedText } = useScreenMultiLang();
  const checkboxConfig = tableConfig?.checkbox || {};
  const actualColumns = visibleColumns || columns || [];
  const sortHandler = onSort || handleSort || (() => {});
  const actualData = data || [];

  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">
        <Table
          noWrapper
          className="w-full"
          style={{ width: "100%", tableLayout: "auto", boxSizing: "border-box" }}
        >
          <TableHeader
            className={cn(
              "bg-background border-b",
              tableConfig?.stickyHeader && "sticky top-0 z-30 shadow-sm",
            )}
          >
            <TableRow className="border-b">
              {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 =
                  "bg-background h-9 border-0 px-3 py-1.5 text-center align-middle sm:px-4 sm:py-2";
                const headDataBaseClass =
                  "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";

                return (
                  <TableHead
                    key={column.columnName}
                    className={cn(
                      isCheckboxCol ? headCheckboxBaseClass : headDataBaseClass,
                      `text-${column.align}`,
                      column.sortable && "hover:bg-primary/10",
                      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: getColumnWidth(column),
                      minWidth: "100px",
                      maxWidth: "300px",
                      boxSizing: "border-box",
                      overflow: "hidden",
                      textOverflow: "ellipsis",
                      whiteSpace: "nowrap",
                      backgroundColor: "hsl(var(--background))",
                      ...(column.fixed === "left" && { left: leftFixedWidth }),
                      ...(column.fixed === "right" && { right: rightFixedWidth }),
                    }}
                    onClick={() => column.sortable && sortHandler(column.columnName)}
                  >
                    <div className="flex items-center gap-2">
                      {isCheckboxCol ? (
                        checkboxConfig.selectAll && (
                          <Checkbox
                            checked={isAllSelected}
                            onCheckedChange={handleSelectAll}
                            aria-label="전체 선택"
                            style={{ 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) => {
                const rowClass = 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;

                      const rawCellValue: React.ReactNode =
                        formatCellValue(row[column.columnName], column.format, column.columnName, row) || " ";

                      const renderCellContent = () => {
                        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}
                          </>
                        );
                      };

                      const cellClass = 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",
                      );

                      return (
                        <TableCell
                          key={`cell-${column.columnName}`}
                          id={isCurrentSearchResult ? "current-search-result" : undefined}
                          className={cellClass}
                          style={{
                            width: getColumnWidth(column),
                            minWidth: "100px",
                            maxWidth: "300px",
                            boxSizing: "border-box",
                            overflow: "hidden",
                            textOverflow: "ellipsis",
                            whiteSpace: "nowrap",
                            ...(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 ? (
                            <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>
  );
}
