"use client";

import { ReactNode, memo, useCallback } from "react";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Card, CardContent } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { ChevronLeft, ChevronRight, LucideIcon } from "lucide-react";
import { StatusBadge, StatusType } from "@/components/molecules/StatusBadge";
import { IconWithBadge } from "@/components/molecules/IconWithBadge";
import { TableActions } from "@/components/molecules/TableActions";
import { Badge } from "@/components/ui/badge";
import { cn } from "@/lib/utils";
import { formatNumber } from '@/lib/utils/amount';

// 셀 타입 정의
export type CellType =
  | "text"           // 일반 텍스트
  | "number"         // 숫자 (우측 정렬)
  | "currency"       // 통화 (₩ 표시)
  | "date"           // 날짜
  | "datetime"       // 날짜 + 시간
  | "status"         // 상태 배지
  | "badge"          // 일반 배지
  | "icon"           // 아이콘
  | "iconBadge"      // 아이콘 + 배지
  | "actions"        // 액션 버튼들
  | "custom";        // 커스텀 렌더링

export interface Column<T> {
  key: keyof T | string;
  label: string;
  type?: CellType;
  width?: string;
  align?: "left" | "center" | "right";
  sortable?: boolean;
  className?: string;

  // 타입별 설정
  statusConfig?: {
    showDot?: boolean;
  };
  badgeConfig?: {
    variant?: "default" | "secondary" | "destructive" | "outline";
    className?: string;
  };
  iconConfig?: {
    iconColor?: string;
    iconBgColor?: string;
    size?: "sm" | "md" | "lg";
  };
  currencyConfig?: {
    locale?: string;
    currency?: string;
  };
  dateConfig?: {
    format?: "short" | "long" | "relative";
  };

  // 커스텀 렌더링
  render?: (value: any, row: T, index?: number) => ReactNode;

  // 값 변환
  format?: (value: any) => string | number;
}

interface DataTableProps<T extends object> {
  columns: Column<T>[];
  data: T[];
  keyField: keyof T;
  onRowClick?: (row: T) => void;
  loading?: boolean;
  emptyMessage?: string;
  pagination?: {
    currentPage: number;
    totalPages: number;
    onPageChange: (page: number) => void;
    showInfo?: boolean;
  };
  striped?: boolean;
  hoverable?: boolean;
  compact?: boolean;
}

// 셀 렌더러
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- 다양한 셀 타입(text/date/icon/badge 등)을 다형적으로 처리
function renderCell<T>(column: Column<T>, value: any, row: T, index?: number): ReactNode {
  // 값 포맷팅 또는 render 호출
  let formattedValue: any;

  if (column.render) {
    formattedValue = column.render(value, row, index);
  } else if (column.format) {
    formattedValue = column.format(value);
  } else {
    formattedValue = value;
  }

  // 타입별 렌더링
  switch (column.type) {
    case "number":
      return <span className="font-mono">{formatNumber(formattedValue)}</span>;

    case "currency": {
      const locale = column.currencyConfig?.locale || "ko-KR";
      const currency = column.currencyConfig?.currency || "KRW";
      const currencyValue = typeof formattedValue === "number"
        ? formattedValue.toLocaleString(locale, { style: "currency", currency })
        : formattedValue;
      return <span className="font-mono">{currencyValue}</span>;
    }

    case "date": {
      if (!formattedValue) return "-";
      const dateValue = new Date(formattedValue);
      return <span className="text-sm">{dateValue.toLocaleDateString("ko-KR")}</span>;
    }

    case "datetime": {
      if (!formattedValue) return "-";
      const datetimeValue = new Date(formattedValue);
      return (
        <span className="text-sm">
          {datetimeValue.toLocaleDateString("ko-KR")} {datetimeValue.toLocaleTimeString("ko-KR", { hour: "2-digit", minute: "2-digit" })}
        </span>
      );
    }

    case "status":
      return (
        <StatusBadge
          label={formattedValue as string}
          variant={formattedValue as StatusType}
          showDot={column.statusConfig?.showDot}
        />
      );

    case "badge":
      return (
        <Badge
          variant={column.badgeConfig?.variant}
          className={column.badgeConfig?.className}
        >
          {formattedValue}
        </Badge>
      );

    case "icon": {
      const IconComponent = formattedValue as LucideIcon;
      return IconComponent ? (
        <IconWithBadge
          icon={IconComponent}
          iconColor={column.iconConfig?.iconColor}
          iconBgColor={column.iconConfig?.iconBgColor}
          size={column.iconConfig?.size}
        />
      ) : null;
    }

    case "iconBadge":
      // value should be { icon, label, badge }
      if (typeof formattedValue === "object" && formattedValue.icon) {
        return (
          <IconWithBadge
            icon={formattedValue.icon}
            label={formattedValue.label}
            badge={formattedValue.badge}
            iconColor={column.iconConfig?.iconColor}
            iconBgColor={column.iconConfig?.iconBgColor}
            size={column.iconConfig?.size}
          />
        );
      }
      return formattedValue;

    case "actions": {
      // render 함수가 TableAction[] 배열을 반환해야 함
      const actions = Array.isArray(formattedValue) ? formattedValue : [];
      return actions.length > 0 ? <TableActions actions={actions} /> : null;
    }

    case "custom":
      // 커스텀 타입은 이미 render 함수에서 처리됨
      return formattedValue;

    case "text":
    default:
      return formattedValue ?? "-";
  }
}

// 정렬 함수
function getAlignClass<T>(column: Column<T>): string {
  if (column.align) {
    return column.align === "center" ? "text-center" : column.align === "right" ? "text-right" : "text-left";
  }

  // 타입별 기본 정렬
  switch (column.type) {
    case "number":
    case "currency":
    case "actions":
      return "text-right";
    case "status":
    case "badge":
    case "icon":
    case "iconBadge":
      return "text-center";
    default:
      return "text-left";
  }
}

// 메모이즈드 행 컴포넌트 — 행 데이터가 변경되지 않으면 리렌더링 스킵
interface DataTableRowProps<T extends object> {
  row: T;
  rowIndex: number;
  columns: Column<T>[];
  onRowClick?: (row: T) => void;
  hoverable: boolean;
  striped: boolean;
  compact: boolean;
  rowKey: string;
}

function DataTableRowInner<T extends object>({
  row,
  rowIndex,
  columns,
  onRowClick,
  hoverable,
  striped,
  compact,
}: DataTableRowProps<T>) {
  const handleClick = useCallback(() => {
    onRowClick?.(row);
  }, [onRowClick, row]);

  return (
    <TableRow
      onClick={onRowClick ? handleClick : undefined}
      className={cn(
        onRowClick && "cursor-pointer",
        hoverable && "hover:bg-muted/50",
        striped && rowIndex % 2 === 1 && "bg-muted/20",
        compact && "h-10"
      )}
    >
      {columns.map((column) => {
        const value = column.key in row ? row[column.key as keyof T] : null;
        return (
          <TableCell
            key={String(column.key)}
            className={cn(
              getAlignClass(column),
              column.className,
              compact && "py-2"
            )}
          >
            {renderCell(column, value, row, rowIndex)}
          </TableCell>
        );
      })}
    </TableRow>
  );
}

const MemoizedDataTableRow = memo(DataTableRowInner) as typeof DataTableRowInner;

export function DataTable<T extends object>({
  columns,
  data,
  keyField,
  onRowClick,
  loading,
  emptyMessage = "데이터가 없습니다.",
  pagination,
  striped = false,
  hoverable = true,
  compact = false
}: DataTableProps<T>) {
  const stableOnRowClick = useCallback(
    (row: T) => onRowClick?.(row),
    [onRowClick]
  );

  return (
    <Card className="hidden md:block">
      <CardContent className="p-0">
        <div className="overflow-x-auto">
          <Table>
            <TableHeader>
              <TableRow>
                {columns.map((column) => (
                  <TableHead
                    key={String(column.key)}
                    className={cn(
                      getAlignClass(column),
                      column.className,
                      column.width && `w-[${column.width}]`
                    )}
                  >
                    {column.label}
                  </TableHead>
                ))}
              </TableRow>
            </TableHeader>
            <TableBody>
              {loading ? (
                <TableRow>
                  <TableCell colSpan={columns.length} className="text-center py-8 text-muted-foreground">
                    로딩 중...
                  </TableCell>
                </TableRow>
              ) : data.length === 0 ? (
                <TableRow>
                  <TableCell colSpan={columns.length} className="text-center py-8 text-muted-foreground">
                    {emptyMessage}
                  </TableCell>
                </TableRow>
              ) : (
                data.map((row, rowIndex) => (
                  <MemoizedDataTableRow<T>
                    key={row[keyField] ? String(row[keyField]) : `row-${rowIndex}`}
                    row={row}
                    rowIndex={rowIndex}
                    columns={columns}
                    onRowClick={onRowClick ? stableOnRowClick : undefined}
                    hoverable={hoverable}
                    striped={striped}
                    compact={compact}
                    rowKey={row[keyField] ? String(row[keyField]) : `row-${rowIndex}`}
                  />
                ))
              )}
            </TableBody>
          </Table>
        </div>

        {pagination && pagination.totalPages > 1 && (
          <div className="flex items-center justify-between p-4 border-t">
            {pagination.showInfo !== false && (
              <p className="text-sm text-muted-foreground">
                페이지 {pagination.currentPage} / {pagination.totalPages}
              </p>
            )}
            <div className="flex gap-2 ml-auto">
              <Button
                variant="outline"
                size="sm"
                onClick={() => pagination.onPageChange(pagination.currentPage - 1)}
                disabled={pagination.currentPage === 1}
              >
                <ChevronLeft className="w-4 h-4" />
              </Button>
              <Button
                variant="outline"
                size="sm"
                onClick={() => pagination.onPageChange(pagination.currentPage + 1)}
                disabled={pagination.currentPage === pagination.totalPages}
              >
                <ChevronRight className="w-4 h-4" />
              </Button>
            </div>
          </div>
        )}
      </CardContent>
    </Card>
  );
}