"use client";

import React, { ReactNode } from "react";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { cn } from "@/lib/utils";

// 컬럼 정의 타입
export interface RDVColumn<T> {
  key: string;
  label: string;
  width?: string;
  render?: (value: any, row: T, index: number) => ReactNode;
  hideOnMobile?: boolean;
  className?: string;
}

// 카드 필드 타입
export interface RDVCardField<T> {
  label: string;
  render: (item: T) => ReactNode;
  hideEmpty?: boolean;
}

// 메인 Props 타입
export interface ResponsiveDataViewProps<T> {
  data: T[];
  columns: RDVColumn<T>[];
  keyExtractor: (item: T) => string;

  // 로딩/빈 상태
  isLoading?: boolean;
  emptyMessage?: string;
  skeletonCount?: number;

  // 카드 설정 (모바일)
  cardTitle: (item: T) => ReactNode;
  cardSubtitle?: (item: T) => ReactNode;
  cardHeaderRight?: (item: T) => ReactNode;
  cardFields?: RDVCardField<T>[] | ((item: T) => RDVCardField<T>[]);

  // 액션 (테이블 마지막 컬럼 + 카드 하단)
  renderActions?: (item: T) => ReactNode;
  actionsLabel?: string;
  actionsWidth?: string;

  // 행 클릭
  onRowClick?: (item: T) => void;

  // 스타일 커스터마이징
  tableContainerClassName?: string;
  cardContainerClassName?: string;

  // 컴팩트 모드 — 행 높이 줄임 (h-16 → h-10), 큰 데이터셋용
  compact?: boolean;
  // 자체 스크롤 모드 — 테이블 컨테이너에 max-height + overflow-y-auto 적용,
  // 헤더 sticky. 부모가 height 결정 (예: flex-1 min-h-0).
  // 페이지 전체 스크롤 대신 테이블 안에서 스크롤 처리.
  scrollContainer?: boolean;
}

// 중첩 객체에서 키 경로로 값을 꺼내는 헬퍼
function getNestedValue(obj: any, path: string): any {
  return path.split(".").reduce((acc, key) => acc?.[key], obj);
}

export function ResponsiveDataView<T>({
  data,
  columns,
  keyExtractor,
  isLoading = false,
  emptyMessage,
  skeletonCount = 5,
  cardTitle,
  cardSubtitle,
  cardHeaderRight,
  cardFields,
  renderActions,
  actionsLabel,
  actionsWidth,
  onRowClick,
  tableContainerClassName,
  cardContainerClassName,
  compact = false,
  scrollContainer = false,
}: ResponsiveDataViewProps<T>) {
  const rowHeight = compact ? "h-10" : "h-16";
  const headHeight = compact ? "h-9" : "h-12";
  const bodyText = compact ? "text-xs" : "text-sm";
  const headText = compact ? "text-xs" : "text-sm";
  const cellPad = compact ? "px-3" : "";
  const cardTitleClass = compact ? "text-sm" : "text-base";
  const cardSubText = compact ? "text-xs" : "text-sm";
  // cardFields 미지정 시 columns에서 자동 생성
  function resolveCardFields(item: T): RDVCardField<T>[] {
    if (typeof cardFields === "function") return cardFields(item);
    if (Array.isArray(cardFields)) return cardFields;
    return columns
      .filter((col) => !col.hideOnMobile)
      .map((col) => ({
        label: col.label,
        render: (row: T) =>
          col.render
            ? col.render(getNestedValue(row, col.key), row, 0)
            : String(getNestedValue(row, col.key) ?? "-"),
      }));
  }

  // --- 로딩 스켈레톤 ---
  if (isLoading) {
    return (
      <div
        className={cn(
          "@container",
          scrollContainer && "flex min-h-0 flex-1 flex-col"
        )}
      >
        {/* 데스크톱 테이블 스켈레톤 */}
        <div
          className={cn(
            "hidden rounded-lg border bg-card shadow-sm @3xl:block",
            scrollContainer && "min-h-0 flex-1 overflow-y-auto",
            tableContainerClassName
          )}
        >
          <Table>
            <TableHeader>
              <TableRow className="border-b bg-muted/50 hover:bg-muted/50">
                {columns.map((col) => (
                  <TableHead
                    key={col.key}
                    style={col.width ? { width: col.width } : undefined}
                    className="h-12 text-sm font-semibold"
                  >
                    {col.label}
                  </TableHead>
                ))}
                {renderActions && (
                  <TableHead
                    style={{ width: actionsWidth || "120px" }}
                    className="h-12 text-sm font-semibold"
                  >
                    {actionsLabel || "작업"}
                  </TableHead>
                )}
              </TableRow>
            </TableHeader>
            <TableBody>
              {Array.from({ length: skeletonCount }).map((_, rowIdx) => (
                <TableRow key={rowIdx} className="border-b">
                  {columns.map((col) => (
                    <TableCell key={col.key} className="h-16">
                      <div className="h-4 animate-pulse rounded bg-muted" />
                    </TableCell>
                  ))}
                  {renderActions && (
                    <TableCell className="h-16">
                      <div className="flex gap-2">
                        <div className="h-8 w-8 animate-pulse rounded bg-muted" />
                        <div className="h-8 w-8 animate-pulse rounded bg-muted" />
                      </div>
                    </TableCell>
                  )}
                </TableRow>
              ))}
            </TableBody>
          </Table>
        </div>

        {/* 모바일 카드 스켈레톤 — container query 기반:
            컨테이너 < 32rem(512px) = 1열, 32~48rem = 2열, ≥ 48rem(768px) = 테이블 */}
        <div
          className={cn(
            "grid gap-4 @lg:grid-cols-2 @3xl:hidden",
            scrollContainer && "min-h-0 flex-1 overflow-y-auto",
            cardContainerClassName
          )}
        >
          {Array.from({ length: skeletonCount }).map((_, i) => (
            <div
              key={i}
              className="rounded-lg border bg-card p-4 shadow-sm"
            >
              <div className="mb-3 flex items-start justify-between">
                <div className="flex-1 space-y-2">
                  <div className="h-5 w-32 animate-pulse rounded bg-muted" />
                  <div className="h-4 w-24 animate-pulse rounded bg-muted" />
                </div>
                <div className="h-6 w-12 animate-pulse rounded bg-muted" />
              </div>
              <div className="space-y-2 border-t pt-3">
                {Array.from({ length: 3 }).map((_, j) => (
                  <div key={j} className="flex justify-between">
                    <div className="h-4 w-16 animate-pulse rounded bg-muted" />
                    <div className="h-4 w-24 animate-pulse rounded bg-muted" />
                  </div>
                ))}
              </div>
              {renderActions && (
                <div className="mt-3 flex gap-2 border-t pt-3">
                  <div className="h-9 flex-1 animate-pulse rounded bg-muted" />
                  <div className="h-9 flex-1 animate-pulse rounded bg-muted" />
                </div>
              )}
            </div>
          ))}
        </div>
      </div>
    );
  }

  // --- 빈 상태 ---
  if (data.length === 0) {
    return (
      <div className="flex h-32 items-center justify-center rounded-lg border bg-card text-sm text-muted-foreground">
        {emptyMessage || "데이터가 없습니다."}
      </div>
    );
  }

  // --- 실제 데이터 렌더링 ---
  // 부모 wrapper 가 @container — 자식들은 viewport 가 아닌 자기 컨테이너 width 기준으로 분기.
  // 사이드바 펼친 상태에서도 콘텐츠 영역 실제 width 에 맞게 자연스럽게 테이블↔카드 전환.
  return (
    <div
      className={cn(
        "@container",
        // scrollContainer 모드: 부모 flex-col 의 남는 공간을 차지 → 페이지네이션 등 형제는 자기 height 유지
        scrollContainer && "flex min-h-0 flex-1 flex-col"
      )}
    >
      {/* 데스크톱 테이블 (컨테이너 ≥ 48rem / 768px) */}
      <div
        className={cn(
          // scrollContainer 모드는 flex 컨테이너로, 아니면 block 으로 표시 (둘 다 < @3xl 에서는 hidden)
          scrollContainer
            ? "hidden flex-col rounded-lg border bg-card shadow-sm @3xl:flex"
            : "hidden rounded-lg border bg-card shadow-sm @3xl:block",
          // 부모 flex 안에서 가용 height 다 차지. 실제 스크롤은 Table wrapper 가 담당
          // (Table 컴포넌트가 만드는 내부 wrapper 에 flex-1 overflow-auto 를 주면 sticky header 가 그 wrapper 기준으로 작동).
          scrollContainer && "min-h-0 flex-1 overflow-hidden",
          tableContainerClassName
        )}
      >
        <Table divClassName={scrollContainer ? "flex-1 overflow-auto" : undefined}>
            <TableHeader
              className={cn(
                scrollContainer && "sticky top-0 z-10 bg-muted"
              )}
            >
              <TableRow className="border-b bg-muted/50 hover:bg-muted/50">
                {columns.map((col) => (
                  <TableHead
                    key={col.key}
                    style={col.width ? { width: col.width } : undefined}
                    className={cn(headHeight, cellPad, headText, "font-semibold")}
                  >
                    {col.label}
                  </TableHead>
                ))}
                {renderActions && (
                  <TableHead
                    style={{ width: actionsWidth || "120px" }}
                    className={cn(headHeight, cellPad, headText, "font-semibold")}
                  >
                    {actionsLabel || "작업"}
                  </TableHead>
                )}
              </TableRow>
            </TableHeader>
            <TableBody>
              {data.map((item, index) => (
                <TableRow
                  key={keyExtractor(item) ?? `row-${index}`}
                  className={cn(
                    "border-b transition-colors hover:bg-muted/50",
                    onRowClick && "cursor-pointer"
                  )}
                  onClick={() => onRowClick?.(item)}
                >
                  {columns.map((col) => (
                    <TableCell
                      key={col.key}
                      className={cn(rowHeight, cellPad, bodyText, col.className)}
                    >
                      {col.render
                        ? col.render(getNestedValue(item, col.key), item, index)
                        : String(getNestedValue(item, col.key) ?? "-")}
                    </TableCell>
                  ))}
                  {renderActions && (
                    <TableCell className={cn(rowHeight, cellPad, bodyText)}>
                      <div className="flex gap-2">{renderActions(item)}</div>
                    </TableCell>
                  )}
                </TableRow>
              ))}
            </TableBody>
          </Table>
      </div>

      {/* 모바일 카드 (컨테이너 < 48rem) — < 32rem 1열, 32~48rem 2열 */}
      <div
        className={cn(
          "grid gap-4 @lg:grid-cols-2 @3xl:hidden",
          // scrollContainer 모드: 부모 flex 안에서 남는 공간 다 차지 + 자체 세로 스크롤
          scrollContainer && "min-h-0 flex-1 overflow-y-auto",
          cardContainerClassName
        )}
      >
        {data.map((item, index) => {
          const fields = resolveCardFields(item);
          return (
            <div
              key={keyExtractor(item) ?? `card-${index}`}
              className={cn(
                "rounded-lg border bg-card p-4 shadow-sm transition-colors hover:bg-muted/50",
                onRowClick && "cursor-pointer"
              )}
              onClick={() => onRowClick?.(item)}
            >
              {/* 카드 헤더 */}
              <div className="mb-3 flex items-start justify-between">
                <div className="min-w-0 flex-1">
                  <h3 className={cn("truncate font-semibold", cardTitleClass)}>
                    {cardTitle(item)}
                  </h3>
                  {cardSubtitle && (
                    <p className={cn("mt-0.5 truncate text-muted-foreground", cardSubText)}>
                      {cardSubtitle(item)}
                    </p>
                  )}
                </div>
                {cardHeaderRight && (
                  <div className="ml-2 shrink-0">{cardHeaderRight(item)}</div>
                )}
              </div>

              {/* 카드 필드 */}
              {fields.length > 0 && (
                <div className="space-y-1.5 border-t pt-3">
                  {fields.map((field, i) => (
                    <div key={i} className={cn("flex justify-between", cardSubText)}>
                      <span className="text-muted-foreground">
                        {field.label}
                      </span>
                      <span className="font-medium">{field.render(item)}</span>
                    </div>
                  ))}
                </div>
              )}

              {/* 카드 액션 */}
              {renderActions && (
                <div className="mt-3 flex gap-2 border-t pt-3">
                  {renderActions(item)}
                </div>
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
}

