import { useMemo } from "react";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Skeleton } from "@/components/ui/skeleton";
import type {
  DashboardRealtimeTradeTick,
  DashboardStockOrderBookResponse,
} from "@/features/trade/types/trade.types";
import { cn } from "@/lib/utils";
import { AnimatedQuantity } from "./AnimatedQuantity";

// ─── 타입 ───────────────────────────────────────────────

interface OrderBookProps {
  symbol?: string;
  referencePrice?: number;
  currentPrice?: number;
  latestTick: DashboardRealtimeTradeTick | null;
  recentTicks: DashboardRealtimeTradeTick[];
  orderBook: DashboardStockOrderBookResponse | null;
  isLoading?: boolean;
}

interface BookRow {
  price: number;
  size: number;
  changePercent: number | null;
  isHighlighted: boolean;
}

/**
 * @description 실시간 호가 레벨 데이터가 실제 값을 포함하는지 검사합니다.
 * @see features/trade/components/orderbook/OrderBook.tsx levels 계산에서 WS 호가 유효성 판단에 사용합니다.
 */
function hasOrderBookLevelData(levels: DashboardStockOrderBookResponse["levels"]) {
  return levels.some(
    (level) =>
      level.askPrice > 0 ||
      level.bidPrice > 0 ||
      level.askSize > 0 ||
      level.bidSize > 0,
  );
}

/**
 * @description H0STOAA0 미수신 상황에서 체결(H0UNCNT0) 데이터로 최소 1호가를 구성합니다.
 * @see features/trade/utils/kisRealtimeUtils.ts parseKisRealtimeTickBatch 체결 데이터에서 1호가/잔량/총잔량을 파싱합니다.
 */
function buildFallbackLevelsFromTick(latestTick: DashboardRealtimeTradeTick | null) {
  if (!latestTick) return [] as DashboardStockOrderBookResponse["levels"];
  if (latestTick.askPrice1 <= 0 && latestTick.bidPrice1 <= 0) {
    return [] as DashboardStockOrderBookResponse["levels"];
  }

  return [
    {
      askPrice: latestTick.askPrice1,
      bidPrice: latestTick.bidPrice1,
      askSize: Math.max(latestTick.askSize1, 0),
      bidSize: Math.max(latestTick.bidSize1, 0),
    },
  ];
}

// ─── 유틸리티 함수 ──────────────────────────────────────

/** 천단위 구분 포맷 */
function fmt(v: number) {
  return Number.isFinite(v) ? v.toLocaleString("ko-KR") : "0";
}

/** 부호 포함 퍼센트 */
function fmtPct(v: number) {
  return `${v > 0 ? "+" : ""}${v.toFixed(2)}%`;
}

/** 등락률 계산 */
function pctChange(price: number, base: number) {
  return base > 0 ? ((price - base) / base) * 100 : 0;
}

/** 체결 시각 포맷 */
function fmtTime(hms: string) {
  if (!hms || hms.length !== 6) return "--:--:--";
  return `${hms.slice(0, 2)}:${hms.slice(2, 4)}:${hms.slice(4, 6)}`;
}

/**
 * @description 체결 틱 데이터에서 체결 주도 방향(매수/매도/중립)을 계산합니다.
 * @see features/trade/components/orderbook/OrderBook.tsx TradeTape 체결량 글자색 결정에 사용합니다.
 */
function resolveTickExecutionSide(
  tick: DashboardRealtimeTradeTick,
  olderTick?: DashboardRealtimeTradeTick,
) {
  // 실시간 체결구분 코드(CNTG_CLS_CODE) 우선 해석
  const executionClassCode = (tick.executionClassCode ?? "").trim();
  if (executionClassCode === "1" || executionClassCode === "2") {
    return "buy" as const;
  }
  if (executionClassCode === "4" || executionClassCode === "5") {
    return "sell" as const;
  }

  // 누적 건수 기반 데이터는 절대값이 아니라 "증분"으로 판단해야 편향을 줄일 수 있습니다.
  if (olderTick) {
    const netBuyDelta =
      tick.netBuyExecutionCount - olderTick.netBuyExecutionCount;
    if (netBuyDelta > 0) return "buy" as const;
    if (netBuyDelta < 0) return "sell" as const;

    const buyCountDelta = tick.buyExecutionCount - olderTick.buyExecutionCount;
    const sellCountDelta =
      tick.sellExecutionCount - olderTick.sellExecutionCount;
    if (buyCountDelta > sellCountDelta) return "buy" as const;
    if (buyCountDelta < sellCountDelta) return "sell" as const;
  }

  if (tick.askPrice1 > 0 && tick.bidPrice1 > 0) {
    if (tick.price >= tick.askPrice1 && tick.price > tick.bidPrice1) {
      return "buy" as const;
    }
    if (tick.price <= tick.bidPrice1 && tick.price < tick.askPrice1) {
      return "sell" as const;
    }
  }

  if (tick.tradeStrength > 100) return "buy" as const;
  if (tick.tradeStrength < 100) return "sell" as const;

  return "neutral" as const;
}

// ─── 메인 컴포넌트 ──────────────────────────────────────

/**
 * 호가창 — 실시간 매도·매수 10호가와 체결 목록을 표시합니다.
 */
export function OrderBook({
  symbol,
  referencePrice,
  currentPrice,
  latestTick,
  recentTicks,
  orderBook,
  isLoading,
}: OrderBookProps) {
  const realtimeLevels = useMemo(() => orderBook?.levels ?? [], [orderBook]);
  const fallbackLevelsFromTick = useMemo(
    () => buildFallbackLevelsFromTick(latestTick),
    [latestTick],
  );
  const levels = useMemo(() => {
    if (hasOrderBookLevelData(realtimeLevels)) return realtimeLevels;
    return fallbackLevelsFromTick;
  }, [fallbackLevelsFromTick, realtimeLevels]);
  const isTickFallbackActive =
    !hasOrderBookLevelData(realtimeLevels) && fallbackLevelsFromTick.length > 0;

  // 체결가: tick에서 우선, 없으면 0
  const latestPrice =
    latestTick?.price && latestTick.price > 0 ? latestTick.price : 0;

  // 등락률 기준가
  const basePrice =
    (referencePrice ?? 0) > 0
      ? referencePrice!
      : (currentPrice ?? 0) > 0
        ? currentPrice!
        : latestPrice > 0
          ? latestPrice
          : 0;

  // 매도호가 (역순: 10호가 → 1호가)
  const askRows: BookRow[] = useMemo(
    () =>
      [...levels].reverse().map((l) => ({
        price: l.askPrice,
        size: Math.max(l.askSize, 0),
        changePercent:
          l.askPrice > 0 && basePrice > 0
            ? pctChange(l.askPrice, basePrice)
            : null,
        isHighlighted: latestPrice > 0 && l.askPrice === latestPrice,
      })),
    [levels, basePrice, latestPrice],
  );

  // 매수호가 (1호가 → 10호가)
  const bidRows: BookRow[] = useMemo(
    () =>
      levels.map((l) => ({
        price: l.bidPrice,
        size: Math.max(l.bidSize, 0),
        changePercent:
          l.bidPrice > 0 && basePrice > 0
            ? pctChange(l.bidPrice, basePrice)
            : null,
        isHighlighted: latestPrice > 0 && l.bidPrice === latestPrice,
      })),
    [levels, basePrice, latestPrice],
  );

  const askMax = Math.max(1, ...askRows.map((r) => r.size));
  const bidMax = Math.max(1, ...bidRows.map((r) => r.size));

  // 스프레드·수급 불균형
  const bestAsk = levels.find((l) => l.askPrice > 0)?.askPrice ?? 0;
  const bestBid = levels.find((l) => l.bidPrice > 0)?.bidPrice ?? 0;
  const spread = bestAsk > 0 && bestBid > 0 ? bestAsk - bestBid : 0;
  const totalAsk =
    orderBook?.totalAskSize && orderBook.totalAskSize > 0
      ? orderBook.totalAskSize
      : (latestTick?.totalAskSize ?? 0);
  const totalBid =
    orderBook?.totalBidSize && orderBook.totalBidSize > 0
      ? orderBook.totalBidSize
      : (latestTick?.totalBidSize ?? 0);
  const imbalance =
    totalAsk + totalBid > 0
      ? ((totalBid - totalAsk) / (totalAsk + totalBid)) * 100
      : 0;

  // 체결가 행 중앙 스크롤

  // ─── 빈/로딩 상태 ───
  if (!symbol) {
    return (
      <div className="flex h-full items-center justify-center text-sm text-muted-foreground">
        종목을 선택해주세요.
      </div>
    );
  }
  if (isLoading && !orderBook && fallbackLevelsFromTick.length === 0) {
    return <OrderBookSkeleton />;
  }
  if (!orderBook && fallbackLevelsFromTick.length === 0) {
    return (
      <div className="flex h-full items-center justify-center text-sm text-muted-foreground">
        호가 정보를 가져오지 못했습니다.
      </div>
    );
  }

  return (
    <div className="flex h-full min-h-0 flex-col bg-white dark:bg-brand-900/10">
      <Tabs defaultValue="normal" className="h-full min-h-0">
        {/* 탭 헤더 */}
        <div className="border-b px-2 pt-2 dark:border-brand-800/45 dark:bg-brand-900/28">
          <TabsList variant="line" className="w-full justify-start">
            <TabsTrigger value="normal" className="px-3">
              일반호가
            </TabsTrigger>
            <TabsTrigger value="cumulative" className="px-3">
              누적호가
            </TabsTrigger>
            <TabsTrigger value="order" className="px-3">
              호가주문
            </TabsTrigger>
          </TabsList>
        </div>

        {/* ── 일반호가 탭 ── */}
        <TabsContent value="normal" className="min-h-0 flex-1">
          <div className="flex h-full min-h-0 flex-col border-t dark:border-brand-800/45 xl:grid xl:grid-cols-[minmax(0,1fr)_320px_168px] xl:overflow-hidden">
            {/* 호가 테이블 */}
            <div className="flex min-h-0 flex-col xl:border-r dark:border-brand-800/45">
              {isTickFallbackActive && (
                <div className="border-b border-amber-200 bg-amber-50 px-2 py-1 text-[11px] text-amber-700 dark:border-amber-700/40 dark:bg-amber-900/20 dark:text-amber-200">
                  시간외 전용 호가(`H0STOAA0`) 미수신 상태입니다. 체결(`H0UNCNT0`)
                  1호가 기준으로 표시 중입니다.
                </div>
              )}
              <BookHeader />
              <ScrollArea className="min-h-0 flex-1 [&>[data-slot=scroll-area-scrollbar]]:hidden xl:[&>[data-slot=scroll-area-scrollbar]]:flex">
                {/* 매도호가 */}
                <BookSideRows rows={askRows} side="ask" maxSize={askMax} />

                {/* 중앙 바: 현재 체결가 */}
                <div className="grid h-8 grid-cols-3 items-center border-y-2 border-amber-400 bg-amber-50/80 dark:bg-amber-900/30 xl:h-9">
                  <div className="px-2 text-right text-[10px] font-medium text-muted-foreground dark:text-brand-100/72">
                    {totalAsk > 0 ? fmt(totalAsk) : ""}
                  </div>
                  <div className="flex items-center justify-center gap-1">
                    <span className="text-xs font-bold tabular-nums">
                      {latestPrice > 0
                        ? fmt(latestPrice)
                        : bestAsk > 0
                          ? fmt(bestAsk)
                          : "-"}
                    </span>
                    {latestPrice > 0 && basePrice > 0 && (
                      <span
                        className={cn(
                          "text-[10px] font-medium",
                          latestPrice >= basePrice
                            ? "text-red-500"
                            : "text-blue-600 dark:text-blue-400",
                        )}
                      >
                        {fmtPct(pctChange(latestPrice, basePrice))}
                      </span>
                    )}
                  </div>
                  <div className="px-2 text-left text-[10px] font-medium text-muted-foreground dark:text-brand-100/72">
                    {totalBid > 0 ? fmt(totalBid) : ""}
                  </div>
                </div>

                {/* 매수호가 */}
                <BookSideRows rows={bidRows} side="bid" maxSize={bidMax} />
              </ScrollArea>
            </div>

            {/* 체결 목록: 데스크톱에서는 호가 오른쪽, 모바일에서는 아래 */}
            <div className="min-h-[220px] border-t border-border/60 dark:border-brand-800/45 xl:min-h-0 xl:border-t-0 xl:border-r">
              <TradeTape ticks={recentTicks} />
            </div>

            {/* 우측 요약 패널 */}
            <div className="hidden xl:block min-h-0">
              <SummaryPanel
                orderBook={orderBook}
                latestTick={latestTick}
                spread={spread}
                imbalance={imbalance}
                totalAsk={totalAsk}
                totalBid={totalBid}
              />
            </div>
          </div>
        </TabsContent>

        {/* ── 누적호가 탭 ── */}
        <TabsContent value="cumulative" className="min-h-0 flex-1">
          <ScrollArea className="h-full border-t dark:border-brand-800/45">
            <div className="p-3">
              <div className="mb-2 grid grid-cols-3 text-[11px] font-medium text-muted-foreground">
                <span>매도누적</span>
                <span className="text-center">호가</span>
                <span className="text-right">매수누적</span>
              </div>
              <CumulativeRows asks={askRows} bids={bidRows} />
            </div>
          </ScrollArea>
        </TabsContent>

        {/* ── 호가주문 탭 ── */}
        <TabsContent value="order" className="min-h-0 flex-1">
          <div className="flex h-full items-center justify-center border-t px-4 text-sm text-muted-foreground dark:border-brand-800/45 dark:text-brand-100/75">
            호가주문 탭은 주문 입력 패널과 연동해 확장할 수 있습니다.
          </div>
        </TabsContent>
      </Tabs>
    </div>
  );
}

// ─── 하위 컴포넌트 ──────────────────────────────────────

/** 호가 표 헤더 */
function BookHeader() {
  return (
    <div className="grid h-8 grid-cols-3 border-b bg-muted/20 text-[11px] font-medium text-muted-foreground dark:border-brand-800/45 dark:bg-brand-900/35 dark:text-brand-100/78">
      <div className="flex items-center justify-end px-2">매도잔량</div>
      <div className="flex items-center justify-center border-x">호가</div>
      <div className="flex items-center justify-start px-2">매수잔량</div>
    </div>
  );
}

/** 매도 또는 매수 호가 행 목록 */
function BookSideRows({
  rows,
  side,
  maxSize,
}: {
  rows: BookRow[];
  side: "ask" | "bid";
  maxSize: number;
}) {
  const isAsk = side === "ask";

  return (
    <div
      className={cn(
        isAsk
          ? "bg-red-50/20 dark:bg-red-950/18"
          : "bg-blue-50/55 dark:bg-blue-950/22",
      )}
    >
      {rows.map((row, i) => {
        const ratio =
          maxSize > 0 ? Math.min((row.size / maxSize) * 100, 100) : 0;

        return (
          <div
            key={`${side}-${row.price}-${i}`}
            className={cn(
              "grid h-7 grid-cols-3 border-b border-border/40 text-[11px] xl:h-8 xl:text-xs dark:border-brand-800/35",
              row.isHighlighted &&
                "ring-1 ring-inset ring-amber-400 bg-amber-100/50 dark:bg-amber-800/30",
            )}
          >
            {/* 매도잔량 (좌측) */}
            <div className="relative flex items-center justify-end overflow-hidden px-2">
              {isAsk && (
                <>
                  <DepthBar ratio={ratio} side="ask" />
                  {row.size > 0 ? (
                    <AnimatedQuantity
                      value={row.size}
                      format={fmt}
                      useColor
                      side="ask"
                      className="relative z-10"
                    />
                  ) : (
                    <span className="relative z-10 text-transparent">0</span>
                  )}
                </>
              )}
            </div>

            {/* 호가 (중앙) */}
            <div
              className={cn(
                "flex items-center justify-center border-x font-medium tabular-nums gap-1",
                row.isHighlighted &&
                  "border-x-amber-400 bg-amber-50/70 dark:bg-amber-800/20",
              )}
            >
              <span
                className={
                  isAsk ? "text-red-600" : "text-blue-600 dark:text-blue-400"
                }
              >
                {row.price > 0 ? fmt(row.price) : "-"}
              </span>
              <span
                className={cn(
                  "text-[10px]",
                  row.changePercent !== null
                    ? row.changePercent >= 0
                      ? "text-red-500"
                      : "text-blue-600 dark:text-blue-400"
                    : "text-muted-foreground",
                )}
              >
                {row.changePercent === null ? "-" : fmtPct(row.changePercent)}
              </span>
            </div>

            {/* 매수잔량 (우측) */}
            <div className="relative flex items-center justify-start overflow-hidden px-1">
              {!isAsk && (
                <>
                  <DepthBar ratio={ratio} side="bid" />
                  {row.size > 0 ? (
                    <AnimatedQuantity
                      value={row.size}
                      format={fmt}
                      useColor
                      side="bid"
                      className="relative z-10"
                    />
                  ) : (
                    <span className="relative z-10 text-transparent">0</span>
                  )}
                </>
              )}
            </div>
          </div>
        );
      })}
    </div>
  );
}

/** 우측 요약 패널 */
function SummaryPanel({
  orderBook,
  latestTick,
  spread,
  imbalance,
  totalAsk,
  totalBid,
}: {
  orderBook: DashboardStockOrderBookResponse | null;
  latestTick: DashboardRealtimeTradeTick | null;
  spread: number;
  imbalance: number;
  totalAsk: number;
  totalBid: number;
}) {
  return (
    <div className="min-w-0 border-l bg-muted/10 p-2 text-[11px] dark:border-brand-800/45 dark:bg-brand-900/30">
      <Row
        label="실시간"
        value={orderBook || latestTick ? "연결됨" : "끊김"}
        tone={orderBook || latestTick ? "bid" : undefined}
      />
      <Row
        label="거래량"
        value={fmt(latestTick?.tradeVolume ?? orderBook?.anticipatedVolume ?? 0)}
      />
      <Row
        label="누적거래량"
        value={fmt(
          latestTick?.accumulatedVolume ?? orderBook?.accumulatedVolume ?? 0,
        )}
      />
      <Row
        label="체결강도"
        value={
          latestTick
            ? `${latestTick.tradeStrength.toFixed(2)}%`
            : orderBook?.anticipatedChangeRate !== undefined
              ? `${orderBook.anticipatedChangeRate.toFixed(2)}%`
              : "-"
        }
      />
      <Row label="예상체결가" value={fmt(orderBook?.anticipatedPrice ?? 0)} />
      <Row
        label="매도1호가"
        value={latestTick ? fmt(latestTick.askPrice1) : "-"}
        tone="ask"
      />
      <Row
        label="매수1호가"
        value={latestTick ? fmt(latestTick.bidPrice1) : "-"}
        tone="bid"
      />
      <Row
        label="매수체결"
        value={latestTick ? fmt(latestTick.buyExecutionCount) : "-"}
      />
      <Row
        label="매도체결"
        value={latestTick ? fmt(latestTick.sellExecutionCount) : "-"}
      />
      <Row
        label="순매수체결"
        value={latestTick ? fmt(latestTick.netBuyExecutionCount) : "-"}
      />
      <Row label="총 매도잔량" value={fmt(totalAsk)} tone="ask" />
      <Row label="총 매수잔량" value={fmt(totalBid)} tone="bid" />
      <Row label="스프레드" value={fmt(spread)} />
      <Row
        label="수급 불균형"
        value={`${imbalance >= 0 ? "+" : ""}${imbalance.toFixed(2)}%`}
        tone={imbalance >= 0 ? "bid" : "ask"}
      />
    </div>
  );
}

/** 요약 패널 단일 행 */
function Row({
  label,
  value,
  tone,
}: {
  label: string;
  value: string;
  tone?: "ask" | "bid";
}) {
  return (
    <div className="mb-1.5 flex items-center justify-between gap-2 rounded border bg-background px-2 py-1 dark:border-brand-800/45 dark:bg-black/20">
      <span className="min-w-0 truncate text-muted-foreground dark:text-brand-100/70">
        {label}
      </span>
      <span
        className={cn(
          "shrink-0 font-medium tabular-nums",
          tone === "ask" && "text-red-600",
          tone === "bid" && "text-blue-600 dark:text-blue-400",
        )}
      >
        {value}
      </span>
    </div>
  );
}

/** 잔량 깊이 바 */
function DepthBar({ ratio, side }: { ratio: number; side: "ask" | "bid" }) {
  if (ratio <= 0) return null;
  return (
    <div
      className={cn(
        "absolute inset-y-1 z-0 rounded-sm",
        side === "ask"
          ? "right-1 bg-red-200/50 dark:bg-red-800/40"
          : "left-1 bg-blue-200/55 dark:bg-blue-500/35",
      )}
      style={{ width: `${ratio}%` }}
    />
  );
}

/** 체결 목록 (Trade Tape) */
function TradeTape({ ticks }: { ticks: DashboardRealtimeTradeTick[] }) {
  return (
    <div className="flex h-full min-h-0 flex-col bg-background dark:bg-brand-900/20">
      <div className="grid h-7 grid-cols-4 border-b bg-muted/20 px-2 text-[11px] font-medium text-muted-foreground dark:border-brand-800/45 dark:bg-brand-900/35 dark:text-brand-100/78">
        <div className="flex items-center">체결시각</div>
        <div className="flex items-center justify-end">체결가</div>
        <div className="flex items-center justify-end">체결량</div>
        <div className="flex items-center justify-end">체결강도</div>
      </div>
      <ScrollArea className="min-h-0 flex-1">
        <div>
          {ticks.length === 0 && (
            <div className="flex min-h-[160px] items-center justify-center text-xs text-muted-foreground dark:text-brand-100/70">
              체결 데이터가 아직 없습니다.
            </div>
          )}
          {ticks.map((t, i) => {
            const olderTick = ticks[i + 1];
            const executionSide = resolveTickExecutionSide(t, olderTick);
            // UI 흐름: 체결목록 UI -> resolveTickExecutionSide(현재/이전 틱) -> 색상 class 결정 -> 체결량 렌더 반영
            const volumeToneClass =
              executionSide === "buy"
                ? "text-red-600"
                : executionSide === "sell"
                  ? "text-blue-600 dark:text-blue-400"
                  : "text-muted-foreground dark:text-brand-100/70";

            return (
              <div
                key={`${t.tickTime}-${t.price}-${i}`}
                className="grid h-8 grid-cols-4 border-b border-border/40 px-2 text-xs dark:border-brand-800/35"
              >
                <div className="flex items-center tabular-nums">
                  {fmtTime(t.tickTime)}
                </div>
                <div className="flex items-center justify-end tabular-nums text-red-600">
                  {fmt(t.price)}
                </div>
                <div
                  className={cn(
                    "flex items-center justify-end tabular-nums",
                    volumeToneClass,
                  )}
                >
                  {fmt(t.tradeVolume)}
                </div>
                <div className="flex items-center justify-end tabular-nums">
                  {t.tradeStrength.toFixed(2)}%
                </div>
              </div>
            );
          })}
        </div>
      </ScrollArea>
    </div>
  );
}

/** 누적호가 행 */
function CumulativeRows({ asks, bids }: { asks: BookRow[]; bids: BookRow[] }) {
  const rows = useMemo(() => {
    const len = Math.max(asks.length, bids.length);
    const result: { askAcc: number; bidAcc: number; price: number }[] = [];
    for (let i = 0; i < len; i++) {
      const prevAsk = result[i - 1]?.askAcc ?? 0;
      const prevBid = result[i - 1]?.bidAcc ?? 0;
      result.push({
        askAcc: prevAsk + (asks[i]?.size ?? 0),
        bidAcc: prevBid + (bids[i]?.size ?? 0),
        price: asks[i]?.price || bids[i]?.price || 0,
      });
    }
    return result;
  }, [asks, bids]);

  return (
    <div className="space-y-1">
      {rows.map((r, i) => (
        <div
          key={i}
          className="grid h-7 grid-cols-3 items-center rounded border bg-background px-2 text-xs dark:border-brand-800/45 dark:bg-black/20"
        >
          <span className="tabular-nums text-red-600">{fmt(r.askAcc)}</span>
          <span className="text-center font-medium tabular-nums">
            {fmt(r.price)}
          </span>
          <span className="text-right tabular-nums text-blue-600 dark:text-blue-400">
            {fmt(r.bidAcc)}
          </span>
        </div>
      ))}
    </div>
  );
}

/** 로딩 스켈레톤 */
function OrderBookSkeleton() {
  return (
    <div className="flex h-full flex-col p-3">
      <div className="mb-3 grid grid-cols-3 gap-2">
        <Skeleton className="h-8 w-full" />
        <Skeleton className="h-8 w-full" />
        <Skeleton className="h-8 w-full" />
      </div>
      <div className="space-y-2">
        {Array.from({ length: 16 }).map((_, i) => (
          <Skeleton key={i} className="h-7 w-full" />
        ))}
      </div>
    </div>
  );
}
