'use client';

import { useState, useCallback } from 'react';
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Plus, Trash2 } from 'lucide-react';
import { cn } from '@/lib/utils';

export interface EditableColumn<T> {
  key: keyof T;
  header: string;
  width?: string;
  align?: 'left' | 'center' | 'right';
  type?: 'text' | 'number' | 'select';
  placeholder?: string;
  options?: { label: string; value: string }[]; // for select type
  render?: (value: T[keyof T], row: T, index: number, onChange: (value: T[keyof T]) => void) => React.ReactNode;
  editable?: boolean; // default true
}

export interface EditableTableProps<T extends { id: string | number }> {
  columns: EditableColumn<T>[];
  data: T[];
  onChange: (data: T[]) => void;

  // 새 행 생성 시 기본값
  createNewRow: () => T;

  // 옵션
  title?: string;
  addButtonLabel?: string;
  emptyMessage?: string;
  showRowNumber?: boolean;
  maxRows?: number;
  minRows?: number;

  // 대량 추가 옵션
  bulkAdd?: boolean; // 여러 행 한번에 추가 기능
  bulkAddLabel?: string; // 대량 추가 버튼 라벨

  // 스타일
  striped?: boolean;
  compact?: boolean;
}

export function EditableTable<T extends { id: string | number }>({
  columns,
  data,
  onChange,
  createNewRow,
  title,
  addButtonLabel = '행 추가',
  emptyMessage = '데이터가 없습니다. 행을 추가해주세요.',
  showRowNumber = true,
  maxRows,
  minRows = 0,
  bulkAdd = false,
  bulkAddLabel = '추가',
  striped = false,
  compact = false,
}: EditableTableProps<T>) {
  // 대량 추가 개수 상태
  const [bulkCount, setBulkCount] = useState(1);

  // 행 추가 (단일)
  const handleAddRow = useCallback(() => {
    if (maxRows && data.length >= maxRows) return;
    const newRow = createNewRow();
    onChange([...data, newRow]);
  }, [data, onChange, createNewRow, maxRows]);

  // 행 추가 (대량)
  const handleBulkAddRows = useCallback(() => {
    if (!bulkCount || bulkCount < 1) return;

    // 최대 개수 제한 계산
    let countToAdd = bulkCount;
    if (maxRows) {
      const remaining = maxRows - data.length;
      countToAdd = Math.min(countToAdd, remaining);
    }

    if (countToAdd <= 0) return;

    const newRows = Array.from({ length: countToAdd }, () => createNewRow());
    onChange([...data, ...newRows]);
    setBulkCount(1); // 입력값 초기화
  }, [bulkCount, data, onChange, createNewRow, maxRows]);

  // 행 삭제
  const handleDeleteRow = useCallback((index: number) => {
    if (data.length <= minRows) return;
    const newData = data.filter((_, i) => i !== index);
    onChange(newData);
  }, [data, onChange, minRows]);

  // 셀 값 변경
  const handleCellChange = useCallback((index: number, key: keyof T, value: T[keyof T]) => {
    const newData = [...data];
    newData[index] = { ...newData[index], [key]: value };
    onChange(newData);
  }, [data, onChange]);

  // 기본 셀 렌더링
  const renderCell = (
    column: EditableColumn<T>,
    row: T,
    rowIndex: number
  ) => {
    const value = row[column.key];
    const isEditable = column.editable !== false;

    // 커스텀 렌더러가 있으면 사용
    if (column.render) {
      return column.render(value, row, rowIndex, (newValue) => {
        handleCellChange(rowIndex, column.key, newValue);
      });
    }

    // 편집 불가능한 경우 텍스트로 표시
    if (!isEditable) {
      return <span className="text-muted-foreground">{String(value ?? '-')}</span>;
    }

    // 타입별 기본 렌더링
    switch (column.type) {
      case 'number':
        return (
          <Input
            type="number"
            value={value as number ?? ''}
            onChange={(e) => handleCellChange(rowIndex, column.key, Number(e.target.value) as T[keyof T])}
            placeholder={column.placeholder}
            className={cn('h-8', compact && 'h-7 text-sm')}
          />
        );

      case 'select':
        return (
          <select
            value={String(value ?? '')}
            onChange={(e) => handleCellChange(rowIndex, column.key, e.target.value as T[keyof T])}
            className={cn(
              'w-full h-8 px-2 rounded-md border border-input bg-background text-sm',
              compact && 'h-7'
            )}
          >
            <option value="">{column.placeholder || '선택'}</option>
            {column.options?.map((opt) => (
              <option key={opt.value} value={opt.value}>
                {opt.label}
              </option>
            ))}
          </select>
        );

      case 'text':
      default:
        return (
          <Input
            type="text"
            value={String(value ?? '')}
            onChange={(e) => handleCellChange(rowIndex, column.key, e.target.value as T[keyof T])}
            placeholder={column.placeholder}
            className={cn('h-8', compact && 'h-7 text-sm')}
          />
        );
    }
  };

  const canAddRow = !maxRows || data.length < maxRows;
  const canDeleteRow = data.length > minRows;

  return (
    <Card>
      {title && (
        <CardHeader className="pb-3">
          <div className="flex items-center justify-between">
            <CardTitle className="text-base">{title}</CardTitle>
            <span className="text-sm text-muted-foreground">
              {data.length}개 항목
              {maxRows && ` (최대 ${maxRows}개)`}
            </span>
          </div>
        </CardHeader>
      )}
      <CardContent className={cn(!title && 'pt-6')}>
        {/* 테이블 */}
        <div className="rounded-md border">
          <Table>
            <TableHeader>
              <TableRow>
                {showRowNumber && (
                  <TableHead className="w-[60px] text-center">번호</TableHead>
                )}
                {columns.map((column) => (
                  <TableHead
                    key={String(column.key)}
                    className={cn(
                      column.width && `w-[${column.width}]`,
                      column.align === 'center' && 'text-center',
                      column.align === 'right' && 'text-right'
                    )}
                  >
                    {column.header}
                  </TableHead>
                ))}
                <TableHead className="w-[60px] text-center">삭제</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {data.length === 0 ? (
                <TableRow>
                  <TableCell
                    colSpan={columns.length + (showRowNumber ? 1 : 0) + 1}
                    className="text-center py-8 text-muted-foreground"
                  >
                    {emptyMessage}
                  </TableCell>
                </TableRow>
              ) : (
                data.map((row, rowIndex) => (
                  <TableRow
                    key={row.id}
                    className={cn(
                      striped && rowIndex % 2 === 1 && 'bg-muted/30',
                      compact && 'h-10'
                    )}
                  >
                    {showRowNumber && (
                      <TableCell className="text-center text-muted-foreground">
                        {rowIndex + 1}
                      </TableCell>
                    )}
                    {columns.map((column) => (
                      <TableCell
                        key={String(column.key)}
                        className={cn(
                          column.align === 'center' && 'text-center',
                          column.align === 'right' && 'text-right',
                          compact && 'py-1'
                        )}
                      >
                        {renderCell(column, row, rowIndex)}
                      </TableCell>
                    ))}
                    <TableCell className="text-center">
                      <Button
                        variant="ghost"
                        size="sm"
                        onClick={() => handleDeleteRow(rowIndex)}
                        disabled={!canDeleteRow}
                        className="h-8 w-8 p-0 text-destructive hover:text-destructive hover:bg-destructive/10"
                      >
                        <Trash2 className="h-4 w-4" />
                      </Button>
                    </TableCell>
                  </TableRow>
                ))
              )}
            </TableBody>
          </Table>
        </div>

        {/* 행 추가 버튼 */}
        <div className="mt-4 flex gap-2">
          {bulkAdd ? (
            <>
              {/* 대량 추가: 숫자 입력 + 버튼 */}
              <div className="flex items-center gap-2 flex-1">
                <Input
                  type="number"
                  min={1}
                  max={maxRows ? maxRows - data.length : 100}
                  value={bulkCount}
                  onChange={(e) => setBulkCount(Math.max(1, parseInt(e.target.value) || 1))}
                  className="w-20 h-9"
                  placeholder="개수"
                />
                <span className="text-sm text-muted-foreground">개</span>
                <Button
                  variant="outline"
                  size="sm"
                  onClick={handleBulkAddRows}
                  disabled={!canAddRow}
                  className="h-9"
                >
                  <Plus className="h-4 w-4 mr-2" />
                  {bulkAddLabel}
                </Button>
              </div>
              {/* 단일 추가 버튼도 제공 */}
              <Button
                variant="ghost"
                size="sm"
                onClick={handleAddRow}
                disabled={!canAddRow}
                className="h-9 border border-dashed"
              >
                <Plus className="h-4 w-4 mr-1" />
                1개 추가
              </Button>
            </>
          ) : (
            /* 단일 추가만 */
            <Button
              variant="outline"
              size="sm"
              onClick={handleAddRow}
              disabled={!canAddRow}
              className="w-full border-dashed"
            >
              <Plus className="h-4 w-4 mr-2" />
              {addButtonLabel}
            </Button>
          )}
        </div>
      </CardContent>
    </Card>
  );
}

export default EditableTable;
