'use client';

import { useMemo, useState, useCallback, useEffect } from 'react';
import {
  useReactTable,
  getCoreRowModel,
  getSortedRowModel,
  flexRender,
  type ColumnDef,
  type SortingState,
  type RowSelectionState,
} from '@tanstack/react-table';
import { ArrowUpDown, ArrowUp, ArrowDown, Loader2 } from 'lucide-react';
import { Checkbox } from '@/components/ui/checkbox';
import { CellRenderer } from './table/CellRenderer';
import type { FieldConfig, TableConfig } from '@/types/invyone-component';

const DEFAULT_CONFIG: TableConfig = {
  pageSize: 20,
  selectionMode: 'single',
  showCheckbox: false,
  inlineEdit: false,
  autoLoad: true,
  toolbar: { showExcel: false, showRefresh: true, showFilter: false },
  style: 'compact',
};

interface FcTableProps {
  fields: FieldConfig[];
  data: Record<string, any>[];
  config?: Partial<TableConfig>;
  loading?: boolean;
  onRowSelect?: (row: Record<string, any>) => void;
  onRowsSelect?: (rows: Record<string, any>[]) => void;
  selectedRowIndex?: number;
}

export function FcTable({
  fields,
  data,
  config: configOverride,
  loading,
  onRowSelect,
  onRowsSelect,
  selectedRowIndex,
}: FcTableProps) {
  const config = useMemo(() => ({ ...DEFAULT_CONFIG, ...configOverride }), [configOverride]);

  const [sorting, setSorting] = useState<SortingState>(
    config.defaultSort
      ? [{ id: config.defaultSort.column, desc: config.defaultSort.direction === 'desc' }]
      : [],
  );
  const [rowSelection, setRowSelection] = useState<RowSelectionState>({});

  // visible + order 기준으로 필드 정렬
  const visibleFields = useMemo(
    () => fields.filter((f) => f.visible).sort((a, b) => a.order - b.order),
    [fields],
  );

  // TanStack 컬럼 정의 생성
  const columns = useMemo<ColumnDef<Record<string, any>>[]>(() => {
    const cols: ColumnDef<Record<string, any>>[] = [];

    // 체크박스 컬럼
    if (config.showCheckbox && config.selectionMode === 'multiple') {
      cols.push({
        id: '_select',
        header: ({ table }) => (
          <Checkbox
            checked={table.getIsAllPageRowsSelected()}
            onCheckedChange={(v) => table.toggleAllPageRowsSelected(!!v)}
          />
        ),
        cell: ({ row }) => (
          <Checkbox
            checked={row.getIsSelected()}
            onCheckedChange={(v) => row.toggleSelected(!!v)}
          />
        ),
        size: 36,
        enableSorting: false,
      });
    }

    // 데이터 컬럼
    for (const field of visibleFields) {
      cols.push({
        id: field.column,
        accessorKey: field.column,
        header: ({ column }) => {
          if (!field.sortable) {
            return <span>{field.label}</span>;
          }
          return (
            <button
              type="button"
              className="flex items-center gap-0.5 hover:text-[var(--v5-primary)] transition-colors"
              onClick={() => column.toggleSorting()}
            >
              <span>{field.label}</span>
              {column.getIsSorted() === 'asc' ? (
                <ArrowUp className="h-3 w-3" />
              ) : column.getIsSorted() === 'desc' ? (
                <ArrowDown className="h-3 w-3" />
              ) : (
                <ArrowUpDown className="h-2.5 w-2.5 opacity-40" />
              )}
            </button>
          );
        },
        cell: ({ getValue }) => <CellRenderer field={field} value={getValue()} />,
        size: field.width ?? getDefaultWidth(field.type),
        enableSorting: field.sortable ?? true,
        meta: { align: field.align ?? (field.type === 'number' ? 'right' : 'left') },
      });
    }

    return cols;
  }, [visibleFields, config.showCheckbox, config.selectionMode]);

  // 행 선택 변경 콜백
  const handleRowSelectionChange = useCallback(
    (updater: RowSelectionState | ((old: RowSelectionState) => RowSelectionState)) => {
      setRowSelection((prev) => {
        const next = typeof updater === 'function' ? updater(prev) : updater;
        if (onRowsSelect) {
          const selectedRows = Object.keys(next)
            .filter((k) => next[k])
            .map((k) => data[Number(k)])
            .filter(Boolean);
          onRowsSelect(selectedRows);
        }
        return next;
      });
    },
    [data, onRowsSelect],
  );

  const table = useReactTable({
    data,
    columns,
    state: { sorting, rowSelection },
    onSortingChange: setSorting,
    onRowSelectionChange: handleRowSelectionChange,
    getCoreRowModel: getCoreRowModel(),
    getSortedRowModel: getSortedRowModel(),
    enableMultiRowSelection: config.selectionMode === 'multiple',
  });

  // 데이터 변경 시 선택 초기화
  useEffect(() => {
    setRowSelection({});
  }, [data]);

  return (
    <div className="fc-table-wrap rounded-md border border-[var(--v5-glass-border)] overflow-hidden
      bg-[var(--v5-glass)] backdrop-blur-[20px]">
      <div className="overflow-x-auto">
        <table className="w-full border-collapse text-xs">
          <thead>
            {table.getHeaderGroups().map((hg) => (
              <tr key={hg.id} className="border-b border-[var(--v5-border)]">
                {hg.headers.map((header) => (
                  <th
                    key={header.id}
                    className="px-2 py-1.5 text-left font-semibold text-[var(--v5-text-sec)]
                      bg-[var(--v5-surface)] whitespace-nowrap select-none"
                    style={{ width: header.getSize() }}
                  >
                    {header.isPlaceholder
                      ? null
                      : flexRender(header.column.columnDef.header, header.getContext())}
                  </th>
                ))}
              </tr>
            ))}
          </thead>
          <tbody>
            {loading ? (
              <tr>
                <td colSpan={columns.length} className="text-center py-8">
                  <Loader2 className="h-5 w-5 animate-spin mx-auto text-[var(--v5-primary)]" />
                </td>
              </tr>
            ) : data.length === 0 ? (
              <tr>
                <td colSpan={columns.length} className="text-center py-8 text-[var(--v5-text-muted)]">
                  데이터가 없습니다
                </td>
              </tr>
            ) : (
              table.getRowModel().rows.map((row, idx) => (
                <tr
                  key={row.id}
                  onClick={() => onRowSelect?.(row.original)}
                  className={`border-b border-[var(--v5-border-subtle)] cursor-pointer transition-colors
                    hover:bg-[var(--v5-surface-hover)]
                    ${selectedRowIndex === idx ? 'bg-[var(--v5-primary-glow)]' : ''}`}
                >
                  {row.getVisibleCells().map((cell) => {
                    const align = (cell.column.columnDef.meta as any)?.align ?? 'left';
                    return (
                      <td
                        key={cell.id}
                        className={`px-2 py-1 whitespace-nowrap text-[var(--v5-text)]
                          ${align === 'right' ? 'text-right' : align === 'center' ? 'text-center' : 'text-left'}`}
                        style={{ maxWidth: cell.column.getSize() }}
                      >
                        {flexRender(cell.column.columnDef.cell, cell.getContext())}
                      </td>
                    );
                  })}
                </tr>
              ))
            )}
          </tbody>
        </table>
      </div>
    </div>
  );
}

function getDefaultWidth(type: string): number {
  switch (type) {
    case 'number': return 100;
    case 'date': return 120;
    case 'datetime': return 160;
    case 'checkbox': return 60;
    case 'entity': return 180;
    case 'textarea': return 200;
    case 'code': return 120;
    default: return 150;
  }
}
