"use client";

import React, { useState, useCallback } from "react";
import { ComponentRendererProps } from "@/types/component";
import { filterDOMProps } from "@/lib/utils/domPropsFilter";
import {
  TableConfig,
  TableDisplayMode,
  TableColumn,
  TableRowHeight,
} from "./types";
import { useTableData } from "./useTableData";
import { GroupedView } from "./views/GroupedView";
import { CardView } from "./views/CardView";
import { PivotView } from "./views/PivotView";

const VALID_MODES: TableDisplayMode[] = ["table", "split", "grouped", "pivot", "card"];
const ROW_HEIGHT_PRESETS: Record<TableRowHeight, string> = {
  compact: "28px",
  normal: "36px",
  relaxed: "44px",
};
const DESIGN_PREVIEW_ROWS = 5;

export interface TableComponentProps extends ComponentRendererProps {
  config?: TableConfig;
}

export const TableComponent: React.FC<TableComponentProps> = ({
  component,
  isDesignMode = false,
  isSelected = false,
  onClick,
  onDragStart,
  onDragEnd,
  config,
  className,
  style,
  ...props
}) => {
  // ─── 4경로 머지 ───
  const fromProps: Partial<TableConfig> = {};
  const p = props as any;
  if (typeof p.displayMode === "string" && (VALID_MODES as string[]).includes(p.displayMode))
    fromProps.displayMode = p.displayMode as TableDisplayMode;
  if (Array.isArray(p.columns)) fromProps.columns = p.columns;
  if (Array.isArray(p.fields)) fromProps.fields = p.fields;
  if (typeof p.selectionMode === "string") fromProps.selectionMode = p.selectionMode;
  if (typeof p.showCheckbox === "boolean") fromProps.showCheckbox = p.showCheckbox;
  if (typeof p.showHeader === "boolean") fromProps.showHeader = p.showHeader;
  if (typeof p.showFooter === "boolean") fromProps.showFooter = p.showFooter;
  if (p.pagination && typeof p.pagination === "object") fromProps.pagination = p.pagination;
  if (typeof p.rowHeight === "string") fromProps.rowHeight = p.rowHeight;
  if (typeof p.striped === "boolean") fromProps.striped = p.striped;
  if (typeof p.hoverable === "boolean") fromProps.hoverable = p.hoverable;
  if (typeof p.bordered === "boolean") fromProps.bordered = p.bordered;
  if (typeof p.splitRatio === "number") fromProps.splitRatio = p.splitRatio;
  if (typeof p.groupBy === "string") fromProps.groupBy = p.groupBy;
  if (typeof p.emptyMessage === "string") fromProps.emptyMessage = p.emptyMessage;
  if (typeof p.showToolbar === "boolean") fromProps.showToolbar = p.showToolbar;
  if (typeof p.showExcel === "boolean") fromProps.showExcel = p.showExcel;
  if (typeof p.showRefresh === "boolean") fromProps.showRefresh = p.showRefresh;

  const componentConfig = {
    ...config,
    ...((component as any).config ?? {}),
    ...((component as any).componentConfig ?? {}),
    ...fromProps,
  } as TableConfig;

  const displayMode: TableDisplayMode = (VALID_MODES as string[]).includes(
    componentConfig.displayMode as string,
  )
    ? (componentConfig.displayMode as TableDisplayMode)
    : "table";

  // ─── 테이블명 결정 ───
  const tableName =
    componentConfig.selectedTable ||
    (component as any).tableName ||
    (component as any).componentConfig?.selectedTable ||
    (component as any).componentConfig?.tableName ||
    (props as any).tableName;

  // ─── columns 결정 ───
  const columns: TableColumn[] = (() => {
    if (Array.isArray(componentConfig.fields) && componentConfig.fields.length > 0) {
      return componentConfig.fields
        .filter((f) => f.visible !== false && !f.system)
        .sort((a, b) => (a.order ?? 0) - (b.order ?? 0))
        .map<TableColumn>((f) => ({
          key: f.column,
          label: f.label,
          width: f.width,
          align: f.align ?? (f.type === "number" ? "right" : "left"),
          sortable: f.sortable ?? true,
          visible: f.visible !== false,
          format: f.format,
        }));
    }
    if (Array.isArray(componentConfig.columns) && componentConfig.columns.length > 0) {
      return componentConfig.columns.filter((c) => c.visible !== false);
    }
    return [];
  })();

  const showHeader = componentConfig.showHeader !== false;
  const showFooter = componentConfig.showFooter !== false;
  const showCheckbox = componentConfig.showCheckbox ?? false;
  const striped = componentConfig.striped ?? true;
  const hoverable = componentConfig.hoverable ?? true;
  const rowHeight = ROW_HEIGHT_PRESETS[componentConfig.rowHeight ?? "normal"];
  const showToolbar = componentConfig.showToolbar ?? true;
  const emptyMessage = componentConfig.emptyMessage ?? "데이터가 없습니다";

  // ─── 외부 검색 파라미터 (Search 컴포넌트가 onSearch 로 업데이트) ───
  const externalSearch =
    (props as any).searchParams && typeof (props as any).searchParams === "object"
      ? ((props as any).searchParams as Record<string, any>)
      : undefined;

  // ─── 데이터 fetch ───
  const tableData = useTableData({
    tableName,
    enabled: !!tableName,
    pageSize: isDesignMode
      ? Math.min(componentConfig.pagination?.pageSize ?? DESIGN_PREVIEW_ROWS, DESIGN_PREVIEW_ROWS)
      : componentConfig.pagination?.pageSize ?? 20,
    search: isDesignMode ? undefined : externalSearch,
  });

  // ─── 렌더할 데이터 결정 ───
  const rows = isDesignMode
    ? (tableData.data.length > 0
        ? tableData.data.slice(0, DESIGN_PREVIEW_ROWS)
        : (columns.length > 0 ? [{}, {}, {}] : []))
    : tableData.data;

  // ─── 행 선택 ───
  const [selectedRowIdx, setSelectedRowIdx] = useState<number | null>(null);
  const [selectedRows, setSelectedRows] = useState<Set<number>>(new Set());

  const emitSelection = useCallback((nextSelectedRowIdx: number | null, nextSelectedRows: Set<number>) => {
    const runtimeRows = tableData.data;
    const onRowSelect =
      typeof (props as any).onRowSelect === "function"
        ? ((props as any).onRowSelect as (row: Record<string, any>) => void)
        : undefined;
    const onSelectedRowsChange =
      typeof (props as any).onSelectedRowsChange === "function"
        ? ((props as any).onSelectedRowsChange as (selectedRows: any[], selectedRowsData: any[]) => void)
        : undefined;

    const selectedRow =
      nextSelectedRowIdx != null ? runtimeRows[nextSelectedRowIdx] ?? null : null;
    const selectedRowsData = Array.from(nextSelectedRows)
      .sort((a, b) => a - b)
      .map((rowIdx) => runtimeRows[rowIdx])
      .filter(Boolean);

    if (selectedRow && onRowSelect) {
      onRowSelect(selectedRow);
    }
    if (onSelectedRowsChange) {
      onSelectedRowsChange(Array.from(nextSelectedRows), selectedRowsData);
    }
  }, [props, tableData.data]);

  const handleRowClick = useCallback((idx: number) => {
    if (isDesignMode) return;
    if (componentConfig.selectionMode === "multiple") {
      setSelectedRows((prev) => {
        const next = new Set(prev);
        next.has(idx) ? next.delete(idx) : next.add(idx);
        setSelectedRowIdx(idx);
        emitSelection(idx, next);
        return next;
      });
    } else {
      setSelectedRowIdx(idx);
      const next = new Set<number>([idx]);
      setSelectedRows(next);
      emitSelection(idx, next);
    }
  }, [isDesignMode, componentConfig.selectionMode, emitSelection]);

  const handleCheckboxToggle = useCallback((idx: number, checked?: boolean) => {
    if (isDesignMode) return;
    if (componentConfig.selectionMode === "multiple") {
      setSelectedRows((prev) => {
        const next = new Set(prev);
        const shouldSelect = checked ?? !next.has(idx);
        if (shouldSelect) next.add(idx);
        else next.delete(idx);
        setSelectedRowIdx(shouldSelect ? idx : selectedRowIdx === idx ? null : selectedRowIdx);
        emitSelection(shouldSelect ? idx : selectedRowIdx === idx ? null : selectedRowIdx, next);
        return next;
      });
      return;
    }

    const shouldSelect = checked ?? selectedRowIdx !== idx;
    const nextIdx = shouldSelect ? idx : null;
    const next = nextIdx != null ? new Set<number>([nextIdx]) : new Set<number>();
    setSelectedRowIdx(nextIdx);
    setSelectedRows(next);
    emitSelection(nextIdx, next);
  }, [isDesignMode, componentConfig.selectionMode, emitSelection, selectedRowIdx]);

  const handleToggleAll = useCallback((checked: boolean) => {
    if (isDesignMode || componentConfig.selectionMode !== "multiple") return;
    const next = checked
      ? new Set(rows.map((_, idx) => idx))
      : new Set<number>();
    const nextSelectedIdx = checked && rows.length > 0 ? 0 : null;
    setSelectedRows(next);
    setSelectedRowIdx(nextSelectedIdx);
    emitSelection(nextSelectedIdx, next);
  }, [componentConfig.selectionMode, emitSelection, isDesignMode, rows]);

  // ─── DOM props 필터 ───
  /* eslint-disable @typescript-eslint/no-unused-vars */
  const {
    selectedScreen: _1, onZoneComponentDrop: _2, onZoneClick: _3,
    componentConfig: _4, component: _5, isSelected: _6,
    onClick: _7, onDragStart: _8, onDragEnd: _9,
    size: _10, position: _11, style: _12,
    screenId: _13, tableName: _14, onRefresh: _15, onClose: _16,
    web_type: _17, autoGeneration: _18, isInteractive: _19,
    formData: _20, onFormDataChange: _21,
    menuId: _22, menuObjid: _23, onSave: _24,
    userId: _25, userName: _26, companyCode: _27,
    isInModal: _28, readonly: _29,
    originalData: _30, _originalData: _31, _initialData: _32, _groupedData: _33,
    allComponents: _34, onUpdateLayout: _35,
    selectedRows: _36, selectedRowsData: _37, onSelectedRowsChange: _38,
    sortBy: _39, sortOrder: _40, tableDisplayData: _41,
    flowSelectedData: _42, flowSelectedStepId: _43,
    onFlowSelectedDataChange: _44, onConfigChange: _45,
    refreshKey: _46, flowRefreshKey: _47, onFlowRefresh: _48,
    isPreview: _49, groupedData: _50,
    displayMode: _51, columns: _52, fields: _53,
    selectionMode: _54, showCheckbox: _55, showHeader: _56, showFooter: _57,
    pagination: _58, rowHeight: _59, striped: _60, hoverable: _61, bordered: _62,
    splitRatio: _63, groupBy: _64, pivotRows: _65, pivotColumns: _66, pivotValues: _67,
    pivotFields: _67a, pivotTotals: _67a1, pivotStyle: _67a2,
    pivotFieldChooser: _67a3, pivotChart: _67a4, pivotExportConfig: _67a5,
    cardsPerRow: _67b, cardSpacing: _67c, cardStyle: _67d, cardColumnMapping: _67e,
    emptyMessage: _68, showToolbar: _69, showExcel: _70, showRefresh: _71,
    disabled: _72, required: _73,
    // Search ↔ Table 연동 props — DOM 에 흘리지 않음
    onSearch: _74, searchParams: _75,
    ...domProps
  } = props as any;
  /* eslint-enable @typescript-eslint/no-unused-vars */

  // ─── 스타일 ───
  const containerStyle: React.CSSProperties = {
    width: "100%",
    height: "100%",
    display: "flex",
    flexDirection: "column",
    background: "hsl(var(--card))",
    borderRadius: "6px",
    border: "1px solid hsl(var(--border))",
    overflow: "hidden",
    ...(component as any).style,
    ...style,
  };
  if (isDesignMode && isSelected) {
    containerStyle.outline = "2px solid hsl(var(--primary))";
    containerStyle.outlineOffset = "2px";
  }

  // ─── 서브 렌더 ───
  const renderToolbar = () =>
    showToolbar && (
      <div style={toolbarStyle}>
        <span style={{ fontSize: "11px", color: "hsl(var(--muted-foreground))", fontWeight: 600 }}>
          {tableName ? tableName : displayMode.toUpperCase()}
          {!isDesignMode && ` · ${tableData.total}건`}
          {isDesignMode && tableName && ` · 미리보기 ${Math.min(rows.length, DESIGN_PREVIEW_ROWS)}건`}
          {isDesignMode && !tableName && columns.length > 0 && ` · 컬럼 ${columns.length}개`}
        </span>
        <div style={{ display: "flex", gap: "4px" }}>
          {tableData.loading && (
            <span style={{ fontSize: "10px", color: "hsl(var(--primary))" }}>로딩...</span>
          )}
          {componentConfig.showRefresh && (
            <button type="button" style={btnStyle} onClick={tableData.refresh} disabled={isDesignMode}>
              ⟳
            </button>
          )}
          {componentConfig.showExcel && (
            <button type="button" style={btnStyle} disabled>📊</button>
          )}
        </div>
      </div>
    );

  const renderHeader = () =>
    showHeader && (
      <thead style={{ background: "hsl(var(--muted))", position: "sticky", top: 0, zIndex: 1 }}>
        <tr>
          {showCheckbox && (
            <th style={{ ...thStyle, width: "32px", textAlign: "center" }}>
              <input
                type="checkbox"
                checked={componentConfig.selectionMode === "multiple" && rows.length > 0 && selectedRows.size === rows.length}
                onChange={(e) => handleToggleAll(e.target.checked)}
                onClick={(e) => e.stopPropagation()}
                disabled={isDesignMode || componentConfig.selectionMode !== "multiple" || rows.length === 0}
              />
            </th>
          )}
          {columns.map((col) => (
            <th
              key={col.key}
              style={{
                ...thStyle,
                width: col.width ? `${col.width}px` : undefined,
                textAlign: col.align ?? "left",
                cursor: col.sortable && !isDesignMode ? "pointer" : "default",
              }}
              onClick={() => col.sortable && !isDesignMode && tableData.toggleSort(col.key)}
            >
              {col.label}
              {col.sortable && (
                <span style={{ marginLeft: "4px", fontSize: "10px", color: tableData.sortBy === col.key ? "hsl(var(--primary))" : "hsl(var(--muted-foreground))" }}>
                  {tableData.sortBy === col.key ? (tableData.sortOrder === "asc" ? "↑" : "↓") : "↕"}
                </span>
              )}
            </th>
          ))}
        </tr>
      </thead>
    );

  const renderRows = () => (
    <tbody>
      {rows.length > 0 ? rows.map((row, idx) => (
        <tr
          key={idx}
          style={{
            height: rowHeight,
            background:
              selectedRowIdx === idx
                ? "hsl(var(--primary) / 0.08)"
                : striped && idx % 2 === 1
                  ? "hsl(var(--muted) / 0.5)"
                  : "transparent",
            borderBottom: "1px solid hsl(var(--border) / 0.3)",
            cursor: hoverable && !isDesignMode ? "pointer" : "default",
            transition: "background 0.1s",
          }}
          onClick={() => handleRowClick(idx)}
        >
          {showCheckbox && (
            <td style={{ ...tdStyle, textAlign: "center" }}>
              <input
                type="checkbox"
                checked={componentConfig.selectionMode === "multiple" ? selectedRows.has(idx) : selectedRowIdx === idx}
                onChange={(e) => handleCheckboxToggle(idx, e.target.checked)}
                onClick={(e) => e.stopPropagation()}
                disabled={isDesignMode}
              />
            </td>
          )}
          {columns.map((col) => (
            <td key={col.key} style={{ ...tdStyle, textAlign: col.align ?? "left" }}>
              {isDesignMode ? (
                <span style={{ color: "hsl(var(--muted-foreground))" }}>
                  {row[col.key] != null ? String(row[col.key]) : "..."}
                </span>
              ) : (
                <span>{row[col.key] != null ? String(row[col.key]) : ""}</span>
              )}
            </td>
          ))}
        </tr>
      )) : (
        <tr>
          <td
            colSpan={columns.length + (showCheckbox ? 1 : 0) || 1}
            style={{ padding: "24px", textAlign: "center", color: "hsl(var(--muted-foreground))", fontSize: "11px" }}
          >
            {!tableName
              ? "테이블을 연결하세요"
              : columns.length === 0
                ? "컬럼을 자동 로드하세요"
                : tableData.loading
                  ? "로딩 중..."
                  : (tableData.error || emptyMessage)}
          </td>
        </tr>
      )}
    </tbody>
  );

  const renderFooter = () =>
    showFooter && (
      <div style={footerStyle}>
        <span>{isDesignMode ? `미리보기 ${rows.length}건` : `총 ${tableData.total}건`}</span>
        <div style={{ display: "flex", gap: "4px", alignItems: "center" }}>
          <button
            type="button"
            style={btnStyle}
            disabled={isDesignMode || tableData.page <= 1}
            onClick={() => tableData.setPage(tableData.page - 1)}
          >
            ‹
          </button>
          <span style={{ padding: "2px 8px", fontSize: "11px" }}>
            {isDesignMode ? "1 / 1" : `${tableData.page} / ${tableData.totalPages}`}
          </span>
          <button
            type="button"
            style={btnStyle}
            disabled={isDesignMode || tableData.page >= tableData.totalPages}
            onClick={() => tableData.setPage(tableData.page + 1)}
          >
            ›
          </button>
        </div>
      </div>
    );

  // ─── 메인 렌더 ───
  const renderBasicTable = () => (
    <div style={{ flex: 1, minHeight: 0, overflow: "auto" }}>
      {columns.length > 0 ? (
        <table style={{ width: "100%", borderCollapse: "collapse", fontSize: "12px" }}>
          {renderHeader()}
          {renderRows()}
        </table>
      ) : (
        <div style={{ padding: "24px", textAlign: "center", color: "hsl(var(--muted-foreground))", fontSize: "11px" }}>
          {!tableName
            ? "테이블을 연결하세요"
            : isDesignMode
              ? "컬럼을 자동 로드하면 미리보기가 표시됩니다"
              : emptyMessage}
        </div>
      )}
    </div>
  );

  const renderSplitMode = () => {
    const ratio = componentConfig.splitRatio ?? 0.5;
    const selectedRow = selectedRowIdx != null ? rows[selectedRowIdx] : null;
    return (
      <div style={{ flex: 1, display: "flex", minHeight: 0 }}>
        <div style={{ flex: ratio, borderRight: "1px solid hsl(var(--border))", minWidth: 0, overflow: "auto" }}>
          {renderBasicTable()}
        </div>
        <div style={{ flex: 1 - ratio, padding: "10px", background: "hsl(var(--muted) / 0.3)", minWidth: 0, overflow: "auto" }}>
          {selectedRow ? (
            <div style={{ fontSize: "11px" }}>
              {columns.map((col) => (
                <div key={col.key} style={{ padding: "4px 0", borderBottom: "1px solid hsl(var(--border) / 0.2)" }}>
                  <span style={{ color: "hsl(var(--muted-foreground))", marginRight: "8px", fontWeight: 600, fontSize: "10px" }}>{col.label}</span>
                  <span>{selectedRow[col.key] != null ? String(selectedRow[col.key]) : "-"}</span>
                </div>
              ))}
            </div>
          ) : (
            <div style={{ textAlign: "center", color: "hsl(var(--muted-foreground))", fontSize: "11px", paddingTop: "20px" }}>
              좌측 행을 클릭하면 상세 표시
            </div>
          )}
        </div>
      </div>
    );
  };

  const renderBody = () => {
    switch (displayMode) {
      case "split":
        return renderSplitMode();
      case "grouped":
        return (
          <GroupedView
            config={componentConfig}
            columns={columns}
            data={rows}
            rowHeightPx={rowHeight}
            isDesignMode={isDesignMode}
            onRowClick={isDesignMode ? undefined : (row) => {
              const idx = tableData.data.indexOf(row);
              if (idx >= 0) handleRowClick(idx);
            }}
          />
        );
      case "card":
        return (
          <CardView
            config={componentConfig}
            data={rows}
            isDesignMode={isDesignMode}
            onCardClick={isDesignMode ? undefined : (row) => {
              const idx = tableData.data.indexOf(row);
              if (idx >= 0) handleRowClick(idx);
            }}
          />
        );
      case "pivot":
        return (
          <PivotView
            data={rows}
            fields={componentConfig.pivotFields}
            totals={componentConfig.pivotTotals}
            style={componentConfig.pivotStyle}
            fieldChooser={componentConfig.pivotFieldChooser}
            chart={componentConfig.pivotChart}
            exportConfig={componentConfig.pivotExportConfig}
          />
        );
      case "table":
      default:
        return renderBasicTable();
    }
  };

  return (
    <div
      style={containerStyle}
      className={className}
      onClick={(e) => { e.stopPropagation(); onClick?.(); }}
      onDragStart={onDragStart}
      onDragEnd={onDragEnd}
      {...filterDOMProps(domProps)}
    >
      {renderToolbar()}
      {renderBody()}
      {renderFooter()}
    </div>
  );
};

// ─── 스타일 상수 ───
const thStyle: React.CSSProperties = {
  padding: "8px 10px", fontSize: "11px", fontWeight: 700,
  color: "hsl(var(--foreground))", textTransform: "uppercase",
  letterSpacing: "0.03em", borderBottom: "1px solid hsl(var(--border))",
  whiteSpace: "nowrap",
};
const tdStyle: React.CSSProperties = {
  padding: "6px 10px", fontSize: "12px", color: "hsl(var(--foreground))",
};
const btnStyle: React.CSSProperties = {
  padding: "2px 8px", fontSize: "11px",
  border: "1px solid hsl(var(--border))", background: "hsl(var(--card))",
  borderRadius: "4px", cursor: "pointer",
};
const toolbarStyle: React.CSSProperties = {
  display: "flex", alignItems: "center", justifyContent: "space-between",
  padding: "6px 10px", borderBottom: "1px solid hsl(var(--border))",
  background: "hsl(var(--muted))", flexShrink: 0,
};
const footerStyle: React.CSSProperties = {
  display: "flex", alignItems: "center", justifyContent: "space-between",
  padding: "6px 10px", borderTop: "1px solid hsl(var(--border))",
  background: "hsl(var(--muted))", fontSize: "11px",
  color: "hsl(var(--muted-foreground))", flexShrink: 0,
};

export const TableWrapper: React.FC<TableComponentProps> = (props) => {
  return <TableComponent {...props} />;
};
