"use client";

/**
 * UnifiedList
 * 
 * 통합 리스트 컴포넌트
 * - table: 테이블 뷰
 * - card: 카드 뷰
 * - kanban: 칸반 뷰
 * - list: 단순 리스트 뷰
 */

import React, { forwardRef, useCallback, useMemo, useState } from "react";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import {
  Pagination,
  PaginationContent,
  PaginationItem,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
} from "@/components/ui/pagination";
import { cn } from "@/lib/utils";
import { UnifiedListProps, ListColumn } from "@/types/unified-components";
import { Search, ChevronUp, ChevronDown, MoreHorizontal, GripVertical } from "lucide-react";

/**
 * 테이블 뷰 컴포넌트
 */
const TableView = forwardRef<HTMLDivElement, {
  columns: ListColumn[];
  data: Record<string, unknown>[];
  selectedRows: Record<string, unknown>[];
  onRowSelect?: (rows: Record<string, unknown>[]) => void;
  onRowClick?: (row: Record<string, unknown>) => void;
  editable?: boolean;
  sortColumn?: string;
  sortDirection?: "asc" | "desc";
  onSort?: (column: string) => void;
  className?: string;
}>(({ 
  columns, 
  data, 
  selectedRows = [], 
  onRowSelect, 
  onRowClick,
  editable,
  sortColumn,
  sortDirection,
  onSort,
  className 
}, ref) => {
  // 행 선택 처리
  const isRowSelected = useCallback((row: Record<string, unknown>) => {
    return selectedRows.some((r) => r === row || JSON.stringify(r) === JSON.stringify(row));
  }, [selectedRows]);

  const handleSelectAll = useCallback((checked: boolean) => {
    if (checked) {
      onRowSelect?.(data);
    } else {
      onRowSelect?.([]);
    }
  }, [data, onRowSelect]);

  const handleSelectRow = useCallback((row: Record<string, unknown>, checked: boolean) => {
    if (checked) {
      onRowSelect?.([...selectedRows, row]);
    } else {
      onRowSelect?.(selectedRows.filter((r) => r !== row && JSON.stringify(r) !== JSON.stringify(row)));
    }
  }, [selectedRows, onRowSelect]);

  const allSelected = data.length > 0 && selectedRows.length === data.length;
  const someSelected = selectedRows.length > 0 && selectedRows.length < data.length;

  return (
    <div ref={ref} className={cn("border rounded-md overflow-hidden", className)}>
      <Table>
        <TableHeader>
          <TableRow className="bg-muted/50">
            {onRowSelect && (
              <TableHead className="w-10">
                <Checkbox
                  checked={allSelected}
                  // indeterminate 상태는 data-state로 처리
                  data-state={someSelected ? "indeterminate" : allSelected ? "checked" : "unchecked"}
                  onCheckedChange={handleSelectAll}
                />
              </TableHead>
            )}
            {columns.map((column) => (
              <TableHead
                key={column.field}
                className={cn(
                  column.sortable && "cursor-pointer select-none hover:bg-muted",
                )}
                style={{ width: column.width ? `${column.width}px` : "auto" }}
                onClick={() => column.sortable && onSort?.(column.field)}
              >
                <div className="flex items-center gap-1">
                  {column.header}
                  {column.sortable && sortColumn === column.field && (
                    sortDirection === "asc" 
                      ? <ChevronUp className="h-4 w-4" />
                      : <ChevronDown className="h-4 w-4" />
                  )}
                </div>
              </TableHead>
            ))}
            {editable && <TableHead className="w-10" />}
          </TableRow>
        </TableHeader>
        <TableBody>
          {data.length === 0 ? (
            <TableRow>
              <TableCell
                colSpan={columns.length + (onRowSelect ? 1 : 0) + (editable ? 1 : 0)}
                className="h-24 text-center text-muted-foreground"
              >
                데이터가 없습니다
              </TableCell>
            </TableRow>
          ) : (
            data.map((row, index) => (
              <TableRow
                key={index}
                className={cn(
                  "cursor-pointer hover:bg-muted/50",
                  isRowSelected(row) && "bg-primary/10"
                )}
                onClick={() => onRowClick?.(row)}
              >
                {onRowSelect && (
                  <TableCell onClick={(e) => e.stopPropagation()}>
                    <Checkbox
                      checked={isRowSelected(row)}
                      onCheckedChange={(checked) => handleSelectRow(row, checked as boolean)}
                    />
                  </TableCell>
                )}
                {columns.map((column) => (
                  <TableCell key={column.field}>
                    {formatCellValue(row[column.field], column.format)}
                  </TableCell>
                ))}
                {editable && (
                  <TableCell onClick={(e) => e.stopPropagation()}>
                    <Button variant="ghost" size="icon" className="h-8 w-8">
                      <MoreHorizontal className="h-4 w-4" />
                    </Button>
                  </TableCell>
                )}
              </TableRow>
            ))
          )}
        </TableBody>
      </Table>
    </div>
  );
});
TableView.displayName = "TableView";

/**
 * 카드 뷰 컴포넌트
 */
const CardView = forwardRef<HTMLDivElement, {
  columns: ListColumn[];
  data: Record<string, unknown>[];
  selectedRows: Record<string, unknown>[];
  onRowSelect?: (rows: Record<string, unknown>[]) => void;
  onRowClick?: (row: Record<string, unknown>) => void;
  className?: string;
}>(({ columns, data, selectedRows = [], onRowSelect, onRowClick, className }, ref) => {
  const isRowSelected = useCallback((row: Record<string, unknown>) => {
    return selectedRows.some((r) => r === row || JSON.stringify(r) === JSON.stringify(row));
  }, [selectedRows]);

  const handleCardClick = useCallback((row: Record<string, unknown>) => {
    if (onRowSelect) {
      const isSelected = isRowSelected(row);
      if (isSelected) {
        onRowSelect(selectedRows.filter((r) => r !== row && JSON.stringify(r) !== JSON.stringify(row)));
      } else {
        onRowSelect([...selectedRows, row]);
      }
    }
    onRowClick?.(row);
  }, [selectedRows, isRowSelected, onRowSelect, onRowClick]);

  // 주요 컬럼 (첫 번째)과 나머지 구분
  const [primaryColumn, ...otherColumns] = columns;

  return (
    <div ref={ref} className={cn("grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4", className)}>
      {data.length === 0 ? (
        <div className="col-span-full py-12 text-center text-muted-foreground">
          데이터가 없습니다
        </div>
      ) : (
        data.map((row, index) => (
          <Card
            key={index}
            className={cn(
              "cursor-pointer transition-colors hover:border-primary",
              isRowSelected(row) && "border-primary bg-primary/5"
            )}
            onClick={() => handleCardClick(row)}
          >
            <CardHeader className="pb-2">
              <CardTitle className="text-base">
                {primaryColumn && formatCellValue(row[primaryColumn.field], primaryColumn.format)}
              </CardTitle>
            </CardHeader>
            <CardContent className="pt-0">
              <dl className="space-y-1 text-sm">
                {otherColumns.slice(0, 4).map((column) => (
                  <div key={column.field} className="flex justify-between">
                    <dt className="text-muted-foreground">{column.header}</dt>
                    <dd className="font-medium">
                      {formatCellValue(row[column.field], column.format)}
                    </dd>
                  </div>
                ))}
              </dl>
            </CardContent>
          </Card>
        ))
      )}
    </div>
  );
});
CardView.displayName = "CardView";

/**
 * 리스트 뷰 컴포넌트
 */
const ListView = forwardRef<HTMLDivElement, {
  columns: ListColumn[];
  data: Record<string, unknown>[];
  selectedRows: Record<string, unknown>[];
  onRowSelect?: (rows: Record<string, unknown>[]) => void;
  onRowClick?: (row: Record<string, unknown>) => void;
  className?: string;
}>(({ columns, data, selectedRows = [], onRowSelect, onRowClick, className }, ref) => {
  const isRowSelected = useCallback((row: Record<string, unknown>) => {
    return selectedRows.some((r) => r === row || JSON.stringify(r) === JSON.stringify(row));
  }, [selectedRows]);

  const handleItemClick = useCallback((row: Record<string, unknown>) => {
    if (onRowSelect) {
      const isSelected = isRowSelected(row);
      if (isSelected) {
        onRowSelect(selectedRows.filter((r) => r !== row && JSON.stringify(r) !== JSON.stringify(row)));
      } else {
        onRowSelect([...selectedRows, row]);
      }
    }
    onRowClick?.(row);
  }, [selectedRows, isRowSelected, onRowSelect, onRowClick]);

  const [primaryColumn, secondaryColumn] = columns;

  return (
    <div ref={ref} className={cn("divide-y border rounded-md", className)}>
      {data.length === 0 ? (
        <div className="py-12 text-center text-muted-foreground">
          데이터가 없습니다
        </div>
      ) : (
        data.map((row, index) => (
          <div
            key={index}
            className={cn(
              "flex items-center gap-3 p-3 cursor-pointer hover:bg-muted/50",
              isRowSelected(row) && "bg-primary/10"
            )}
            onClick={() => handleItemClick(row)}
          >
            {onRowSelect && (
              <Checkbox
                checked={isRowSelected(row)}
                onClick={(e) => e.stopPropagation()}
                onCheckedChange={(checked) => {
                  if (checked) {
                    onRowSelect([...selectedRows, row]);
                  } else {
                    onRowSelect(selectedRows.filter((r) => r !== row));
                  }
                }}
              />
            )}
            <GripVertical className="h-4 w-4 text-muted-foreground" />
            <div className="flex-1 min-w-0">
              <div className="font-medium truncate">
                {primaryColumn && formatCellValue(row[primaryColumn.field], primaryColumn.format)}
              </div>
              {secondaryColumn && (
                <div className="text-sm text-muted-foreground truncate">
                  {formatCellValue(row[secondaryColumn.field], secondaryColumn.format)}
                </div>
              )}
            </div>
          </div>
        ))
      )}
    </div>
  );
});
ListView.displayName = "ListView";

/**
 * 셀 값 포맷팅
 */
function formatCellValue(value: unknown, format?: string): React.ReactNode {
  if (value === null || value === undefined) return "-";

  if (format) {
    switch (format) {
      case "date":
        return new Date(String(value)).toLocaleDateString("ko-KR");
      case "datetime":
        return new Date(String(value)).toLocaleString("ko-KR");
      case "currency":
        return Number(value).toLocaleString("ko-KR") + "원";
      case "number":
        return Number(value).toLocaleString("ko-KR");
      case "percent":
        return Number(value).toFixed(1) + "%";
      default:
        return String(value);
    }
  }

  return String(value);
}

/**
 * 메인 UnifiedList 컴포넌트
 */
export const UnifiedList = forwardRef<HTMLDivElement, UnifiedListProps>(
  (props, ref) => {
    const {
      id,
      label,
      style,
      size,
      config: configProp,
      data = [],
      selectedRows = [],
      onRowSelect,
      onRowClick,
    } = props;

    // config가 없으면 기본값 사용
    const config = configProp || { viewMode: "table" as const, source: "static" as const, columns: [] };

    // 내부 상태
    const [searchTerm, setSearchTerm] = useState("");
    const [currentPage, setCurrentPage] = useState(1);
    const [sortColumn, setSortColumn] = useState<string | undefined>();
    const [sortDirection, setSortDirection] = useState<"asc" | "desc">("asc");

    const pageSize = config.pageSize || 10;
    const columns = config.columns || [];

    // 검색 필터링
    const filteredData = useMemo(() => {
      if (!searchTerm || !config.searchable) return data;
      
      const term = searchTerm.toLowerCase();
      return data.filter((row) =>
        columns.some((col) => {
          const value = row[col.field];
          return value && String(value).toLowerCase().includes(term);
        })
      );
    }, [data, searchTerm, config.searchable, columns]);

    // 정렬
    const sortedData = useMemo(() => {
      if (!sortColumn) return filteredData;
      
      return [...filteredData].sort((a, b) => {
        const aVal = a[sortColumn];
        const bVal = b[sortColumn];
        
        if (aVal === bVal) return 0;
        if (aVal === null || aVal === undefined) return 1;
        if (bVal === null || bVal === undefined) return -1;
        
        const comparison = String(aVal).localeCompare(String(bVal), "ko-KR", { numeric: true });
        return sortDirection === "asc" ? comparison : -comparison;
      });
    }, [filteredData, sortColumn, sortDirection]);

    // 페이지네이션
    const paginatedData = useMemo(() => {
      if (!config.pageable) return sortedData;
      
      const start = (currentPage - 1) * pageSize;
      return sortedData.slice(start, start + pageSize);
    }, [sortedData, currentPage, pageSize, config.pageable]);

    const totalPages = Math.ceil(sortedData.length / pageSize);

    // 정렬 핸들러
    const handleSort = useCallback((column: string) => {
      if (sortColumn === column) {
        setSortDirection((d) => (d === "asc" ? "desc" : "asc"));
      } else {
        setSortColumn(column);
        setSortDirection("asc");
      }
    }, [sortColumn]);

    // 뷰모드별 렌더링
    const renderView = () => {
      const viewProps = {
        columns,
        data: paginatedData,
        selectedRows,
        onRowSelect,
        onRowClick,
        editable: config.editable,
        sortColumn,
        sortDirection,
        onSort: handleSort,
      };

      switch (config.viewMode) {
        case "table":
          return <TableView {...viewProps} />;
        case "card":
          return <CardView {...viewProps} />;
        case "list":
          return <ListView {...viewProps} />;
        case "kanban":
          // TODO: 칸반 뷰 구현
          return (
            <div className="p-4 border rounded text-center text-muted-foreground">
              칸반 뷰 (미구현)
            </div>
          );
        default:
          return <TableView {...viewProps} />;
      }
    };

    const showLabel = label && style?.labelDisplay !== false;
    const showSearch = config.searchable;
    const componentWidth = size?.width || style?.width;
    const componentHeight = size?.height || style?.height;

    return (
      <div
        ref={ref}
        id={id}
        className="flex flex-col gap-4"
        style={{
          width: componentWidth,
          height: componentHeight,
        }}
      >
        {/* 헤더 영역 */}
        {(showLabel || showSearch) && (
          <div className="flex items-center justify-between gap-4 flex-shrink-0">
            {showLabel && (
              <Label className="text-lg font-semibold">{label}</Label>
            )}
            
            {/* 검색 */}
            {showSearch && (
              <div className="relative flex-1 max-w-sm">
                <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
                <Input
                  type="text"
                  placeholder="검색..."
                  value={searchTerm}
                  onChange={(e) => {
                    setSearchTerm(e.target.value);
                    setCurrentPage(1);
                  }}
                  className="pl-10 h-9"
                />
              </div>
            )}
          </div>
        )}

        {/* 데이터 뷰 */}
        <div className="flex-1 min-h-0 overflow-auto">
          {renderView()}
        </div>

        {/* 페이지네이션 */}
        {config.pageable && totalPages > 1 && (
          <div className="flex items-center justify-between">
            <div className="text-sm text-muted-foreground">
              총 {sortedData.length}건 중 {(currentPage - 1) * pageSize + 1}-
              {Math.min(currentPage * pageSize, sortedData.length)}건
            </div>
            <Pagination>
              <PaginationContent>
                <PaginationItem>
                  <PaginationPrevious
                    onClick={() => setCurrentPage((p) => Math.max(1, p - 1))}
                    className={currentPage === 1 ? "pointer-events-none opacity-50" : "cursor-pointer"}
                  />
                </PaginationItem>
                {Array.from({ length: Math.min(5, totalPages) }, (_, i) => {
                  const page = i + 1;
                  return (
                    <PaginationItem key={page}>
                      <PaginationLink
                        onClick={() => setCurrentPage(page)}
                        isActive={currentPage === page}
                        className="cursor-pointer"
                      >
                        {page}
                      </PaginationLink>
                    </PaginationItem>
                  );
                })}
                <PaginationItem>
                  <PaginationNext
                    onClick={() => setCurrentPage((p) => Math.min(totalPages, p + 1))}
                    className={currentPage === totalPages ? "pointer-events-none opacity-50" : "cursor-pointer"}
                  />
                </PaginationItem>
              </PaginationContent>
            </Pagination>
          </div>
        )}
      </div>
    );
  }
);

UnifiedList.displayName = "UnifiedList";

export default UnifiedList;

