"use client";

import React, { useEffect, useState } from "react";
import { FlowComponent } from "@/types/screen-management";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { AlertCircle, Loader2, ChevronUp, History } from "lucide-react";
import {
  getFlowById,
  getAllStepCounts,
  getStepDataList,
  getFlowAuditLogs,
  getFlowSteps,
  getFlowConnections,
} from "@/lib/api/flow";
import type { FlowDefinition, FlowStep, FlowAuditLog } from "@/types/flow";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Checkbox } from "@/components/ui/checkbox";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { toast } from "sonner";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import {
  Pagination,
  PaginationContent,
  PaginationItem,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
} from "@/components/ui/pagination";
import { useFlowStepStore } from "@/stores/flowStepStore";

interface FlowWidgetProps {
  component: FlowComponent;
  onStepClick?: (stepId: number, stepName: string) => void;
  onSelectedDataChange?: (selectedData: any[], stepId: number | null) => void;
  flowRefreshKey?: number; // 새로고침 키
  onFlowRefresh?: () => void; // 새로고침 완료 콜백
}

export function FlowWidget({
  component,
  onStepClick,
  onSelectedDataChange,
  flowRefreshKey,
  onFlowRefresh,
}: FlowWidgetProps) {
  // 🆕 전역 상태 관리
  const setSelectedStep = useFlowStepStore((state) => state.setSelectedStep);
  const resetFlow = useFlowStepStore((state) => state.resetFlow);

  const [flowData, setFlowData] = useState<FlowDefinition | null>(null);
  const [steps, setSteps] = useState<FlowStep[]>([]);
  const [stepCounts, setStepCounts] = useState<Record<number, number>>({});
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [connections, setConnections] = useState<any[]>([]); // 플로우 연결 정보

  // 선택된 스텝의 데이터 리스트 상태
  const [selectedStepId, setSelectedStepId] = useState<number | null>(null);
  const [stepData, setStepData] = useState<any[]>([]);
  const [stepDataColumns, setStepDataColumns] = useState<string[]>([]);
  const [stepDataLoading, setStepDataLoading] = useState(false);
  const [selectedRows, setSelectedRows] = useState<Set<number>>(new Set());

  // 🆕 스텝 데이터 페이지네이션 상태
  const [stepDataPage, setStepDataPage] = useState(1);
  const [stepDataPageSize, setStepDataPageSize] = useState(10);

  // 오딧 로그 상태
  const [auditLogs, setAuditLogs] = useState<FlowAuditLog[]>([]);
  const [auditLogsLoading, setAuditLogsLoading] = useState(false);
  const [showAuditLogs, setShowAuditLogs] = useState(false);
  const [auditPage, setAuditPage] = useState(1);
  const [auditPageSize] = useState(10);

  // componentConfig에서 플로우 설정 추출 (DynamicComponentRenderer에서 전달됨)
  const config = (component as any).componentConfig || (component as any).config || {};
  const flowId = config.flowId || component.flowId;
  const flowName = config.flowName || component.flowName;
  const displayMode = config.displayMode || component.displayMode || "horizontal";
  const showStepCount = config.showStepCount !== false && component.showStepCount !== false; // 기본값 true
  const allowDataMove = config.allowDataMove || component.allowDataMove || false;

  // 🆕 플로우 컴포넌트 ID (버튼이 이 플로우를 참조할 때 사용)
  const flowComponentId = component.id;

  // 선택된 스텝의 데이터를 다시 로드하는 함수
  const refreshStepData = async () => {
    if (!flowId) return;

    try {
      // 스텝 카운트는 항상 업데이트 (선택된 스텝 유무와 관계없이)
      const countsResponse = await getAllStepCounts(flowId);
      console.log("📊 스텝 카운트 API 응답:", countsResponse);

      if (countsResponse.success && countsResponse.data) {
        // Record 형태로 변환
        const countsMap: Record<number, number> = {};
        if (Array.isArray(countsResponse.data)) {
          countsResponse.data.forEach((item: any) => {
            countsMap[item.stepId] = item.count;
          });
        } else if (typeof countsResponse.data === "object") {
          Object.assign(countsMap, countsResponse.data);
        }

        console.log("✅ 스텝 카운트 업데이트:", countsMap);
        setStepCounts(countsMap);
      }

      // 선택된 스텝이 있으면 해당 스텝의 데이터도 새로고침
      if (selectedStepId) {
        setStepDataLoading(true);

        const response = await getStepDataList(flowId, selectedStepId, 1, 100);

        if (!response.success) {
          throw new Error(response.message || "데이터를 불러올 수 없습니다");
        }

        const rows = response.data?.records || [];
        setStepData(rows);

        // 컬럼 추출
        if (rows.length > 0) {
          setStepDataColumns(Object.keys(rows[0]));
        } else {
          setStepDataColumns([]);
        }

        // 선택 초기화
        setSelectedRows(new Set());
        onSelectedDataChange?.([], selectedStepId);
      }
    } catch (err: any) {
      console.error("❌ 플로우 새로고침 실패:", err);
      toast.error(err.message || "데이터를 새로고치는데 실패했습니다");
    } finally {
      if (selectedStepId) {
        setStepDataLoading(false);
      }
    }
  };

  useEffect(() => {
    if (!flowId) {
      setLoading(false);
      return;
    }

    const loadFlowData = async () => {
      try {
        setLoading(true);
        setError(null);

        // 플로우 정보 조회
        const flowResponse = await getFlowById(flowId!);
        if (!flowResponse.success || !flowResponse.data) {
          throw new Error("플로우를 찾을 수 없습니다");
        }

        setFlowData(flowResponse.data);

        // 스텝 목록 조회
        const stepsResponse = await getFlowSteps(flowId);
        if (!stepsResponse.success) {
          throw new Error("스텝 목록을 불러올 수 없습니다");
        }
        if (stepsResponse.data) {
          const sortedSteps = stepsResponse.data.sort((a: FlowStep, b: FlowStep) => a.stepOrder - b.stepOrder);
          setSteps(sortedSteps);

          // 연결 정보 조회
          const connectionsResponse = await getFlowConnections(flowId);
          if (connectionsResponse.success && connectionsResponse.data) {
            setConnections(connectionsResponse.data);
          }

          // 스텝별 데이터 건수 조회
          if (showStepCount) {
            const countsResponse = await getAllStepCounts(flowId!);
            if (countsResponse.success && countsResponse.data) {
              // 배열을 Record<number, number>로 변환
              const countsMap: Record<number, number> = {};
              countsResponse.data.forEach((item: any) => {
                countsMap[item.stepId] = item.count;
              });
              setStepCounts(countsMap);
            }
          }

          // 🆕 플로우 로드 후 첫 번째 스텝 자동 선택
          if (sortedSteps.length > 0) {
            const firstStep = sortedSteps[0];
            setSelectedStepId(firstStep.id);
            setSelectedStep(flowComponentId, firstStep.id);
            console.log("✅ [FlowWidget] 첫 번째 단계 자동 선택:", {
              flowComponentId,
              stepId: firstStep.id,
              stepName: firstStep.stepName,
            });

            // 첫 번째 스텝의 데이터 로드
            try {
              const response = await getStepDataList(flowId!, firstStep.id, 1, 100);
              if (response.success) {
                const rows = response.data?.records || [];
                setStepData(rows);
                if (rows.length > 0) {
                  setStepDataColumns(Object.keys(rows[0]));
                }
              }
            } catch (err) {
              console.error("첫 번째 스텝 데이터 로드 실패:", err);
            }
          }
        }
      } catch (err: any) {
        console.error("Failed to load flow data:", err);
        setError(err.message || "플로우 데이터를 불러오는데 실패했습니다");
      } finally {
        setLoading(false);
      }
    };

    loadFlowData();
  }, [flowId, showStepCount]);

  // flowRefreshKey가 변경될 때마다 스텝 데이터 새로고침
  useEffect(() => {
    if (flowRefreshKey !== undefined && flowRefreshKey > 0 && flowId) {
      console.log("🔄 플로우 새로고침 실행, flowRefreshKey:", flowRefreshKey);
      refreshStepData();
    }
  }, [flowRefreshKey]);

  // 🆕 언마운트 시 전역 상태 초기화
  useEffect(() => {
    return () => {
      console.log("🧹 [FlowWidget] 언마운트 - 전역 상태 초기화:", flowComponentId);
      resetFlow(flowComponentId);
    };
  }, [flowComponentId, resetFlow]);

  // 🆕 스텝 클릭 핸들러 (전역 상태 업데이트 추가)
  const handleStepClick = async (stepId: number, stepName: string) => {
    // 외부 콜백 실행
    if (onStepClick) {
      onStepClick(stepId, stepName);
    }

    // 같은 스텝을 다시 클릭하면 접기
    if (selectedStepId === stepId) {
      setSelectedStepId(null);
      setSelectedStep(flowComponentId, null); // 🆕 전역 상태 업데이트
      setStepData([]);
      setStepDataColumns([]);
      setSelectedRows(new Set());
      setStepDataPage(1); // 🆕 페이지 리셋
      onSelectedDataChange?.([], null);

      console.log("🔄 [FlowWidget] 단계 선택 해제:", { flowComponentId, stepId });
      return;
    }

    // 새로운 스텝 선택 - 데이터 로드
    setSelectedStepId(stepId);
    setSelectedStep(flowComponentId, stepId); // 🆕 전역 상태 업데이트
    setStepDataLoading(true);
    setSelectedRows(new Set());
    setStepDataPage(1); // 🆕 페이지 리셋
    onSelectedDataChange?.([], stepId);

    console.log("✅ [FlowWidget] 단계 선택:", { flowComponentId, stepId, stepName });

    try {
      const response = await getStepDataList(flowId!, stepId, 1, 100);

      if (!response.success) {
        throw new Error(response.message || "데이터를 불러올 수 없습니다");
      }

      const rows = response.data?.records || [];
      setStepData(rows);

      // 컬럼 추출
      if (rows.length > 0) {
        setStepDataColumns(Object.keys(rows[0]));
      } else {
        setStepDataColumns([]);
      }
    } catch (err: any) {
      console.error("Failed to load step data:", err);
      toast.error(err.message || "데이터를 불러오는데 실패했습니다");
    } finally {
      setStepDataLoading(false);
    }
  };

  // 체크박스 토글
  const toggleRowSelection = (rowIndex: number) => {
    const newSelected = new Set(selectedRows);
    if (newSelected.has(rowIndex)) {
      newSelected.delete(rowIndex);
    } else {
      newSelected.add(rowIndex);
    }
    setSelectedRows(newSelected);

    // 선택된 데이터를 상위로 전달
    const selectedData = Array.from(newSelected).map((index) => stepData[index]);
    console.log("🌊 FlowWidget - 체크박스 토글, 상위로 전달:", {
      rowIndex,
      newSelectedSize: newSelected.size,
      selectedData,
      selectedStepId,
      hasCallback: !!onSelectedDataChange,
    });
    onSelectedDataChange?.(selectedData, selectedStepId);
  };

  // 전체 선택/해제
  const toggleAllRows = () => {
    let newSelected: Set<number>;
    if (selectedRows.size === stepData.length) {
      newSelected = new Set();
    } else {
      newSelected = new Set(stepData.map((_, index) => index));
    }
    setSelectedRows(newSelected);

    // 선택된 데이터를 상위로 전달
    const selectedData = Array.from(newSelected).map((index) => stepData[index]);
    onSelectedDataChange?.(selectedData, selectedStepId);
  };

  // 오딧 로그 로드
  const loadAuditLogs = async () => {
    if (!flowId) return;

    try {
      setAuditLogsLoading(true);
      const response = await getFlowAuditLogs(flowId, 100); // 최근 100개
      if (response.success && response.data) {
        setAuditLogs(response.data);
      }
    } catch (err: any) {
      console.error("Failed to load audit logs:", err);
      toast.error("이력 조회 중 오류가 발생했습니다");
    } finally {
      setAuditLogsLoading(false);
    }
  };

  // 오딧 로그 모달 열기
  const handleOpenAuditLogs = () => {
    setShowAuditLogs(true);
    setAuditPage(1); // 페이지 초기화
    loadAuditLogs();
  };

  // 페이지네이션된 오딧 로그
  const paginatedAuditLogs = auditLogs.slice((auditPage - 1) * auditPageSize, auditPage * auditPageSize);
  const totalAuditPages = Math.ceil(auditLogs.length / auditPageSize);

  // 🆕 페이지네이션된 스텝 데이터
  const paginatedStepData = stepData.slice((stepDataPage - 1) * stepDataPageSize, stepDataPage * stepDataPageSize);
  const totalStepDataPages = Math.ceil(stepData.length / stepDataPageSize);

  if (loading) {
    return (
      <div className="flex items-center justify-center p-8">
        <Loader2 className="text-muted-foreground h-6 w-6 animate-spin" />
        <span className="text-muted-foreground ml-2 text-sm">플로우 로딩 중...</span>
      </div>
    );
  }

  if (error) {
    return (
      <div className="border-destructive/50 bg-destructive/10 flex items-center gap-2 rounded-lg border p-4">
        <AlertCircle className="text-destructive h-5 w-5" />
        <span className="text-destructive text-sm">{error}</span>
      </div>
    );
  }

  if (!flowId || !flowData) {
    return (
      <div className="border-muted-foreground/25 flex items-center justify-center rounded-lg border-2 border-dashed p-8">
        <span className="text-muted-foreground text-sm">플로우를 선택해주세요</span>
      </div>
    );
  }

  if (steps.length === 0) {
    return (
      <div className="border-muted flex items-center justify-center rounded-lg border p-8">
        <span className="text-muted-foreground text-sm">플로우에 스텝이 없습니다</span>
      </div>
    );
  }

  // 반응형 컨테이너 클래스
  const containerClass =
    displayMode === "horizontal"
      ? "flex flex-col sm:flex-row sm:flex-wrap items-center justify-center gap-3 sm:gap-4"
      : "flex flex-col items-center gap-4";

  return (
    <div className="@container flex w-full flex-col p-2 sm:p-4 lg:p-6">
      {/* 플로우 제목 */}
      <div className="mb-3 flex-shrink-0 sm:mb-4">
        <div className="flex items-center justify-center gap-2">
          <h3 className="text-foreground text-base font-semibold sm:text-lg lg:text-xl">{flowData.name}</h3>

          {/* 오딧 로그 버튼 */}
          <Dialog open={showAuditLogs} onOpenChange={setShowAuditLogs}>
            <DialogTrigger asChild>
              <Button variant="outline" size="sm" onClick={handleOpenAuditLogs} className="gap-1.5">
                <History className="h-4 w-4" />
                <span className="hidden sm:inline">변경 이력</span>
              </Button>
            </DialogTrigger>
            <DialogContent className="max-h-[85vh] max-w-[95vw] sm:max-w-[1000px]">
              <DialogHeader>
                <DialogTitle>플로우 변경 이력</DialogTitle>
                <DialogDescription>데이터 이동 및 상태 변경 기록 (총 {auditLogs.length}건)</DialogDescription>
              </DialogHeader>

              {auditLogsLoading ? (
                <div className="flex items-center justify-center p-8">
                  <Loader2 className="text-muted-foreground h-6 w-6 animate-spin" />
                  <span className="text-muted-foreground ml-2 text-sm">이력 로딩 중...</span>
                </div>
              ) : auditLogs.length === 0 ? (
                <div className="text-muted-foreground py-8 text-center text-sm">변경 이력이 없습니다</div>
              ) : (
                <div className="space-y-4">
                  {/* 테이블 */}
                  <div className="bg-card overflow-hidden rounded-lg border">
                    <div className="overflow-x-auto">
                      <Table>
                        <TableHeader>
                          <TableRow className="bg-muted/50">
                            <TableHead className="w-[140px]">변경일시</TableHead>
                            <TableHead className="w-[80px]">타입</TableHead>
                            <TableHead className="w-[120px]">출발 단계</TableHead>
                            <TableHead className="w-[120px]">도착 단계</TableHead>
                            <TableHead className="w-[100px]">데이터 ID</TableHead>
                            <TableHead className="w-[140px]">상태 변경</TableHead>
                            <TableHead className="w-[100px]">변경자</TableHead>
                            <TableHead className="w-[150px]">DB 연결</TableHead>
                            <TableHead>테이블</TableHead>
                          </TableRow>
                        </TableHeader>
                        <TableBody>
                          {paginatedAuditLogs.map((log) => {
                            const fromStep = steps.find((s) => s.id === log.fromStepId);
                            const toStep = steps.find((s) => s.id === log.toStepId);

                            return (
                              <TableRow key={log.id} className="hover:bg-muted/50">
                                <TableCell className="font-mono text-xs">
                                  {new Date(log.changedAt).toLocaleString("ko-KR", {
                                    year: "numeric",
                                    month: "2-digit",
                                    day: "2-digit",
                                    hour: "2-digit",
                                    minute: "2-digit",
                                  })}
                                </TableCell>
                                <TableCell>
                                  <Badge variant="outline" className="text-xs">
                                    {log.moveType === "status"
                                      ? "상태"
                                      : log.moveType === "table"
                                        ? "테이블"
                                        : "하이브리드"}
                                  </Badge>
                                </TableCell>
                                <TableCell className="font-medium">
                                  {fromStep?.stepName || `Step ${log.fromStepId}`}
                                </TableCell>
                                <TableCell className="font-medium">
                                  {toStep?.stepName || `Step ${log.toStepId}`}
                                </TableCell>
                                <TableCell className="font-mono text-xs">
                                  {log.sourceDataId || "-"}
                                  {log.targetDataId && log.targetDataId !== log.sourceDataId && (
                                    <>
                                      <br />→ {log.targetDataId}
                                    </>
                                  )}
                                </TableCell>
                                <TableCell className="text-xs">
                                  {log.statusFrom && log.statusTo ? (
                                    <span className="font-mono">
                                      {log.statusFrom}
                                      <br />→ {log.statusTo}
                                    </span>
                                  ) : (
                                    <span className="text-muted-foreground">-</span>
                                  )}
                                </TableCell>
                                <TableCell className="text-xs">{log.changedBy}</TableCell>
                                <TableCell className="text-xs">
                                  {log.dbConnectionName ? (
                                    <span
                                      className={
                                        log.dbConnectionName === "내부 데이터베이스"
                                          ? "text-blue-600"
                                          : "text-green-600"
                                      }
                                    >
                                      {log.dbConnectionName}
                                    </span>
                                  ) : (
                                    <span className="text-muted-foreground">-</span>
                                  )}
                                </TableCell>
                                <TableCell className="text-xs">
                                  {log.sourceTable || "-"}
                                  {log.targetTable && log.targetTable !== log.sourceTable && (
                                    <>
                                      <br />→ {log.targetTable}
                                    </>
                                  )}
                                </TableCell>
                              </TableRow>
                            );
                          })}
                        </TableBody>
                      </Table>
                    </div>
                  </div>

                  {/* 페이지네이션 */}
                  {totalAuditPages > 1 && (
                    <div className="flex items-center justify-between">
                      <div className="text-muted-foreground text-sm">
                        {(auditPage - 1) * auditPageSize + 1}-{Math.min(auditPage * auditPageSize, auditLogs.length)} /{" "}
                        {auditLogs.length}건
                      </div>
                      <Pagination>
                        <PaginationContent>
                          <PaginationItem>
                            <PaginationPrevious
                              onClick={() => setAuditPage((p) => Math.max(1, p - 1))}
                              className={auditPage === 1 ? "pointer-events-none opacity-50" : "cursor-pointer"}
                            />
                          </PaginationItem>

                          {Array.from({ length: totalAuditPages }, (_, i) => i + 1)
                            .filter((page) => {
                              // 현재 페이지 주변만 표시
                              return (
                                page === 1 ||
                                page === totalAuditPages ||
                                (page >= auditPage - 1 && page <= auditPage + 1)
                              );
                            })
                            .map((page, idx, arr) => (
                              <React.Fragment key={page}>
                                {idx > 0 && arr[idx - 1] !== page - 1 && (
                                  <PaginationItem>
                                    <span className="text-muted-foreground px-2">...</span>
                                  </PaginationItem>
                                )}
                                <PaginationItem>
                                  <PaginationLink
                                    onClick={() => setAuditPage(page)}
                                    isActive={auditPage === page}
                                    className="cursor-pointer"
                                  >
                                    {page}
                                  </PaginationLink>
                                </PaginationItem>
                              </React.Fragment>
                            ))}

                          <PaginationItem>
                            <PaginationNext
                              onClick={() => setAuditPage((p) => Math.min(totalAuditPages, p + 1))}
                              className={
                                auditPage === totalAuditPages ? "pointer-events-none opacity-50" : "cursor-pointer"
                              }
                            />
                          </PaginationItem>
                        </PaginationContent>
                      </Pagination>
                    </div>
                  )}
                </div>
              )}
            </DialogContent>
          </Dialog>
        </div>

        {flowData.description && (
          <p className="text-muted-foreground mt-1 text-center text-xs sm:text-sm">{flowData.description}</p>
        )}
      </div>

      {/* 플로우 스텝 목록 */}
      <div className={`${containerClass} flex-shrink-0`}>
        {steps.map((step, index) => (
          <React.Fragment key={step.id}>
            {/* 스텝 카드 */}
            <div
              className={`group bg-card relative w-full cursor-pointer rounded-lg border-2 p-4 shadow-sm transition-all duration-200 sm:w-auto sm:min-w-[180px] sm:rounded-xl sm:p-5 lg:min-w-[220px] lg:p-6 ${
                selectedStepId === step.id
                  ? "border-primary bg-primary/5 shadow-md"
                  : "border-border hover:border-primary/50 hover:shadow-md"
              }`}
              onClick={() => handleStepClick(step.id, step.stepName)}
            >
              {/* 단계 번호 배지 */}
              <div className="bg-primary/10 text-primary mb-2 inline-flex items-center rounded-full px-2 py-1 text-xs font-medium sm:mb-3 sm:px-3">
                Step {step.stepOrder}
              </div>

              {/* 스텝 이름 */}
              <h4 className="text-foreground mb-2 pr-8 text-base leading-tight font-semibold sm:text-lg">
                {step.stepName}
              </h4>

              {/* 데이터 건수 */}
              {showStepCount && (
                <div className="text-muted-foreground mt-2 flex items-center gap-2 text-xs sm:mt-3 sm:text-sm">
                  <div className="bg-muted flex h-7 items-center rounded-md px-2 sm:h-8 sm:px-3">
                    <span className="text-foreground text-sm font-semibold sm:text-base">
                      {stepCounts[step.id] || 0}
                    </span>
                    <span className="ml-1">건</span>
                  </div>
                </div>
              )}

              {/* 선택 인디케이터 */}
              {selectedStepId === step.id && (
                <div className="absolute top-3 right-3 sm:top-4 sm:right-4">
                  <ChevronUp className="text-primary h-4 w-4 sm:h-5 sm:w-5" />
                </div>
              )}
            </div>

            {/* 화살표 (마지막 스텝 제외) */}
            {index < steps.length - 1 && (
              <div className="text-muted-foreground/40 flex shrink-0 items-center justify-center py-2 sm:py-0">
                {displayMode === "horizontal" ? (
                  <svg
                    className="h-5 w-5 rotate-90 sm:h-6 sm:w-6 sm:rotate-0"
                    fill="none"
                    viewBox="0 0 24 24"
                    stroke="currentColor"
                  >
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
                  </svg>
                ) : (
                  <svg className="h-5 w-5 sm:h-6 sm:w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
                  </svg>
                )}
              </div>
            )}
          </React.Fragment>
        ))}
      </div>

      {/* 선택된 스텝의 데이터 리스트 */}
      {selectedStepId !== null && (
        <div className="bg-muted/30 mt-4 flex w-full flex-col rounded-lg border sm:mt-6 lg:mt-8">
          {/* 헤더 - 자동 높이 */}
          <div className="bg-background flex-shrink-0 border-b px-4 py-3 sm:px-6 sm:py-4">
            <h4 className="text-foreground text-base font-semibold sm:text-lg">
              {steps.find((s) => s.id === selectedStepId)?.stepName}
            </h4>
            <p className="text-muted-foreground mt-1 text-xs sm:text-sm">
              총 {stepData.length}건의 데이터
              {selectedRows.size > 0 && (
                <span className="text-primary ml-2 font-medium">({selectedRows.size}건 선택됨)</span>
              )}
            </p>
          </div>

          {/* 데이터 영역 - 고정 높이 + 스크롤 */}
          {stepDataLoading ? (
            <div className="flex h-64 items-center justify-center">
              <Loader2 className="text-primary h-6 w-6 animate-spin sm:h-8 sm:w-8" />
              <span className="text-muted-foreground ml-2 text-sm">데이터 로딩 중...</span>
            </div>
          ) : stepData.length === 0 ? (
            <div className="flex h-64 flex-col items-center justify-center">
              <svg
                className="text-muted-foreground/50 mb-3 h-12 w-12"
                fill="none"
                viewBox="0 0 24 24"
                stroke="currentColor"
              >
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  strokeWidth={1.5}
                  d="M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4"
                />
              </svg>
              <span className="text-muted-foreground text-sm">데이터가 없습니다</span>
            </div>
          ) : (
            <>
              {/* 모바일: 카드 뷰 - 고정 높이 + 스크롤 */}
              <div className="overflow-y-auto @sm:hidden" style={{ height: "450px" }}>
                <div className="space-y-2 p-3">
                  {paginatedStepData.map((row, pageIndex) => {
                    const actualIndex = (stepDataPage - 1) * stepDataPageSize + pageIndex;
                    return (
                      <div
                        key={actualIndex}
                        className={`bg-card rounded-md border p-3 transition-colors ${
                          selectedRows.has(actualIndex) ? "bg-primary/5 border-primary/30" : ""
                        }`}
                      >
                        {allowDataMove && (
                          <div className="mb-2 flex items-center justify-between border-b pb-2">
                            <span className="text-muted-foreground text-xs font-medium">선택</span>
                            <Checkbox
                              checked={selectedRows.has(actualIndex)}
                              onCheckedChange={() => toggleRowSelection(actualIndex)}
                            />
                          </div>
                        )}
                        <div className="space-y-1.5">
                          {stepDataColumns.map((col) => (
                            <div key={col} className="flex justify-between gap-2 text-xs">
                              <span className="text-muted-foreground font-medium">{col}:</span>
                              <span className="text-foreground truncate">
                                {row[col] !== null && row[col] !== undefined ? (
                                  String(row[col])
                                ) : (
                                  <span className="text-muted-foreground">-</span>
                                )}
                              </span>
                            </div>
                          ))}
                        </div>
                      </div>
                    );
                  })}
                </div>
              </div>

              {/* 데스크톱: 테이블 뷰 - 고정 높이 + 스크롤 */}
              <div className="relative hidden overflow-auto @sm:block" style={{ height: "450px" }}>
                <Table noWrapper>
                  <TableHeader>
                    <TableRow className="hover:bg-muted/50">
                      {allowDataMove && (
                        <TableHead className="bg-background sticky top-0 left-0 z-20 w-12 border-b px-3 py-2 text-center shadow-[0_1px_0_0_rgb(0,0,0,0.1)]">
                          <Checkbox
                            checked={selectedRows.size === stepData.length && stepData.length > 0}
                            onCheckedChange={toggleAllRows}
                          />
                        </TableHead>
                      )}
                      {stepDataColumns.map((col) => (
                        <TableHead
                          key={col}
                          className="bg-background sticky top-0 z-10 border-b px-3 py-2 text-xs font-semibold whitespace-nowrap shadow-[0_1px_0_0_rgb(0,0,0,0.1)] sm:text-sm"
                        >
                          {col}
                        </TableHead>
                      ))}
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {paginatedStepData.map((row, pageIndex) => {
                      const actualIndex = (stepDataPage - 1) * stepDataPageSize + pageIndex;
                      return (
                        <TableRow
                          key={actualIndex}
                          className={`hover:bg-muted/50 ${selectedRows.has(actualIndex) ? "bg-primary/5" : ""}`}
                        >
                          {allowDataMove && (
                            <TableCell className="bg-background sticky left-0 z-10 border-b px-3 py-2 text-center">
                              <Checkbox
                                checked={selectedRows.has(actualIndex)}
                                onCheckedChange={() => toggleRowSelection(actualIndex)}
                              />
                            </TableCell>
                          )}
                          {stepDataColumns.map((col) => (
                            <TableCell key={col} className="border-b px-3 py-2 text-xs whitespace-nowrap sm:text-sm">
                              {row[col] !== null && row[col] !== undefined ? (
                                String(row[col])
                              ) : (
                                <span className="text-muted-foreground">-</span>
                              )}
                            </TableCell>
                          ))}
                        </TableRow>
                      );
                    })}
                  </TableBody>
                </Table>
              </div>
            </>
          )}

          {/* 페이지네이션 - 항상 하단에 고정 */}
          {!stepDataLoading && stepData.length > 0 && (
            <div className="bg-background flex-shrink-0 border-t px-4 py-3 sm:px-6">
              <div className="flex flex-col items-center justify-between gap-3 sm:flex-row">
                {/* 왼쪽: 페이지 정보 + 페이지 크기 선택 */}
                <div className="flex flex-col items-center gap-2 sm:flex-row sm:gap-4">
                  <div className="text-muted-foreground text-xs sm:text-sm">
                    페이지 {stepDataPage} / {totalStepDataPages} (총 {stepData.length}건)
                  </div>
                  <div className="flex items-center gap-2">
                    <span className="text-muted-foreground text-xs">표시 개수:</span>
                    <Select
                      value={stepDataPageSize.toString()}
                      onValueChange={(value) => {
                        setStepDataPageSize(Number(value));
                        setStepDataPage(1); // 페이지 크기 변경 시 첫 페이지로
                      }}
                    >
                      <SelectTrigger className="h-8 w-20 text-xs">
                        <SelectValue />
                      </SelectTrigger>
                      <SelectContent>
                        <SelectItem value="10">10개</SelectItem>
                        <SelectItem value="20">20개</SelectItem>
                        <SelectItem value="50">50개</SelectItem>
                        <SelectItem value="100">100개</SelectItem>
                      </SelectContent>
                    </Select>
                  </div>
                </div>

                {/* 오른쪽: 페이지네이션 */}
                {totalStepDataPages > 1 && (
                  <Pagination>
                    <PaginationContent>
                      <PaginationItem>
                        <PaginationPrevious
                          onClick={() => setStepDataPage((p) => Math.max(1, p - 1))}
                          className={stepDataPage === 1 ? "pointer-events-none opacity-50" : "cursor-pointer"}
                        />
                      </PaginationItem>
                      {totalStepDataPages <= 7 ? (
                        Array.from({ length: totalStepDataPages }, (_, i) => i + 1).map((page) => (
                          <PaginationItem key={page}>
                            <PaginationLink
                              onClick={() => setStepDataPage(page)}
                              isActive={stepDataPage === page}
                              className="cursor-pointer"
                            >
                              {page}
                            </PaginationLink>
                          </PaginationItem>
                        ))
                      ) : (
                        <>
                          {Array.from({ length: totalStepDataPages }, (_, i) => i + 1)
                            .filter((page) => {
                              return (
                                page === 1 ||
                                page === totalStepDataPages ||
                                (page >= stepDataPage - 2 && page <= stepDataPage + 2)
                              );
                            })
                            .map((page, idx, arr) => (
                              <React.Fragment key={page}>
                                {idx > 0 && arr[idx - 1] !== page - 1 && (
                                  <PaginationItem>
                                    <span className="text-muted-foreground px-2">...</span>
                                  </PaginationItem>
                                )}
                                <PaginationItem>
                                  <PaginationLink
                                    onClick={() => setStepDataPage(page)}
                                    isActive={stepDataPage === page}
                                    className="cursor-pointer"
                                  >
                                    {page}
                                  </PaginationLink>
                                </PaginationItem>
                              </React.Fragment>
                            ))}
                        </>
                      )}
                      <PaginationItem>
                        <PaginationNext
                          onClick={() => setStepDataPage((p) => Math.min(totalStepDataPages, p + 1))}
                          className={
                            stepDataPage === totalStepDataPages ? "pointer-events-none opacity-50" : "cursor-pointer"
                          }
                        />
                      </PaginationItem>
                    </PaginationContent>
                  </Pagination>
                )}
              </div>
            </div>
          )}
        </div>
      )}
    </div>
  );
}
