import { useMemo } from "react";
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";
import type { BookRow } from "./orderbook-utils";
import {
  fmt,
  fmtPct,
  fmtSignedChange,
  fmtTime,
  getChangeToneClass,
  pctChange,
  resolveTickExecutionSide,
} from "./orderbook-utils";

/**
 * @description 호가창 중앙의 현재가/등락률/총잔량 바를 렌더링합니다.
 * @summary UI 흐름: OrderBook -> CurrentPriceBar -> 매도/매수 구간 사이 현재 체결 상태를 강조 표시
 * @see features/trade/components/orderbook/OrderBook.tsx 일반호가 탭의 모바일/데스크톱 공통 현재가 행
 */
export function CurrentPriceBar({
  latestPrice,
  basePrice,
  bestAsk,
  totalAsk,
  totalBid,
}: {
  latestPrice: number;
  basePrice: number;
  bestAsk: number;
  totalAsk: number;
  totalBid: number;
}) {
  return (
    <div className="grid h-10 grid-cols-3 items-center border-y-2 border-amber-400 bg-linear-to-r from-blue-50/60 via-amber-50/90 to-red-50/60 shadow-[0_0_10px_rgba(251,191,36,0.25)] dark:from-blue-950/30 dark:via-amber-900/30 dark:to-red-950/30 xl:h-10">
      <div className="px-2 text-right text-[10px] font-semibold text-blue-600 dark:text-blue-400">
        {totalAsk > 0 ? fmt(totalAsk) : ""}
      </div>
      <div className="flex flex-col items-center justify-center">
        <span
          className={cn(
            "text-base leading-none font-bold tabular-nums",
            latestPrice > 0 && basePrice > 0
              ? latestPrice >= basePrice
                ? "text-red-600"
                : "text-blue-600 dark:text-blue-400"
              : "text-foreground dark:text-brand-50",
          )}
        >
          {latestPrice > 0 ? fmt(latestPrice) : bestAsk > 0 ? fmt(bestAsk) : "-"}
        </span>
        {latestPrice > 0 && basePrice > 0 && (
          <span
            className={cn(
              "text-[11px] font-semibold leading-none",
              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-semibold text-red-600 dark:text-red-400">
        {totalBid > 0 ? fmt(totalBid) : ""}
      </div>
    </div>
  );
}

/** 호가 표 헤더 */
export function BookHeader() {
  return (
    <div className="grid h-8 grid-cols-3 border-b bg-linear-to-r from-blue-50/40 via-muted/20 to-red-50/40 text-[11px] font-semibold text-muted-foreground dark:border-brand-800/50 dark:from-blue-950/30 dark:via-brand-900/40 dark:to-red-950/30 dark:text-brand-100/80">
      <div className="flex items-center justify-end px-2 text-blue-600/80 dark:text-blue-400/80">
        매도잔량
      </div>
      <div className="flex items-center justify-center border-x border-border/50 dark:border-brand-800/40">
        호가
      </div>
      <div className="flex items-center justify-start px-2 text-red-600/80 dark:text-red-400/80">
        매수잔량
      </div>
    </div>
  );
}

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

  return (
    <div
      className={cn(
        isAsk
          ? "bg-linear-to-r from-blue-50/40 via-blue-50/10 to-transparent dark:from-blue-950/35 dark:via-blue-950/10 dark:to-transparent"
          : "bg-linear-to-r from-transparent via-red-50/10 to-red-50/45 dark:from-transparent dark:via-red-950/10 dark:to-red-950/35",
      )}
    >
      {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-[29px] grid-cols-3 border-b border-border/30 text-[11px] transition-colors hover:bg-muted/15 xl:h-[29px] xl:text-xs dark:border-brand-800/25 dark:hover:bg-brand-900/20",
              row.isHighlighted &&
                "ring-1 ring-inset ring-amber-400 bg-amber-100/60 dark:bg-amber-800/35",
            )}
          >
            <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={cn(
                  "text-[12px] xl:text-[13px]",
                  isAsk ? "text-blue-600 dark:text-blue-400" : "text-red-600",
                )}
              >
                {row.price > 0 ? fmt(row.price) : "-"}
              </span>
              <span
                className={cn(
                  "w-[48px] shrink-0 text-right text-[10px] tabular-nums xl:w-[56px]",
                  getChangeToneClass(row.changeValue),
                )}
              >
                {row.changeValue === null
                  ? "-"
                  : fmtSignedChange(row.changeValue)}
              </span>
              <span
                className={cn(
                  "w-[52px] shrink-0 text-right text-[10px] tabular-nums xl:w-[58px]",
                  getChangeToneClass(row.changeRate),
                )}
              >
                {row.changeRate === null ? "-" : fmtPct(row.changeRate)}
              </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>
  );
}

/** 우측 요약 패널 */
export function SummaryPanel({
  orderBook,
  latestTick,
  spread,
  imbalance,
  totalAsk,
  totalBid,
}: {
  orderBook: DashboardStockOrderBookResponse | null;
  latestTick: DashboardRealtimeTradeTick | null;
  spread: number;
  imbalance: number;
  totalAsk: number;
  totalBid: number;
}) {
  const displayTradeVolume =
    latestTick?.isExpected && (orderBook?.anticipatedVolume ?? 0) > 0
      ? (orderBook?.anticipatedVolume ?? 0)
      : (latestTick?.tradeVolume ?? orderBook?.anticipatedVolume ?? 0);
  const summaryItems: SummaryMetric[] = [
    {
      label: "실시간",
      value: orderBook || latestTick ? "연결됨" : "끊김",
      tone: orderBook || latestTick ? "ask" : undefined,
    },
    { label: "거래량", value: fmt(displayTradeVolume) },
    {
      label: "누적거래량",
      value: fmt(
        latestTick?.accumulatedVolume ?? orderBook?.accumulatedVolume ?? 0,
      ),
    },
    {
      label: "체결강도",
      value: latestTick
        ? `${latestTick.tradeStrength.toFixed(2)}%`
        : orderBook?.anticipatedChangeRate !== undefined
          ? `${orderBook.anticipatedChangeRate.toFixed(2)}%`
          : "-",
    },
    { label: "예상체결가", value: fmt(orderBook?.anticipatedPrice ?? 0) },
    {
      label: "매도1호가",
      value: latestTick ? fmt(latestTick.askPrice1) : "-",
      tone: "ask",
    },
    {
      label: "매수1호가",
      value: latestTick ? fmt(latestTick.bidPrice1) : "-",
      tone: "bid",
    },
    {
      label: "순매수체결",
      value: latestTick ? fmt(latestTick.netBuyExecutionCount) : "-",
    },
    { label: "총 매도잔량", value: fmt(totalAsk), tone: "ask" },
    { label: "총 매수잔량", value: fmt(totalBid), tone: "bid" },
    { label: "스프레드", value: fmt(spread) },
    {
      label: "수급 불균형",
      value: `${imbalance >= 0 ? "+" : ""}${imbalance.toFixed(2)}%`,
      tone: imbalance >= 0 ? "bid" : "ask",
    },
  ];

  return (
    <div className="h-full min-w-0 bg-muted/10 p-2 text-xs dark:bg-brand-900/30">
      <div className="grid grid-cols-2 gap-1 xl:h-full xl:grid-cols-1 xl:grid-rows-12">
        {summaryItems.map((item) => (
          <SummaryMetricCell
            key={item.label}
            label={item.label}
            value={item.value}
            tone={item.tone}
          />
        ))}
      </div>
    </div>
  );
}

/** 체결 목록 (Trade Tape) */
export function TradeTape({
  ticks,
  maxRows,
}: {
  ticks: DashboardRealtimeTradeTick[];
  maxRows?: number;
}) {
  const visibleTicks =
    typeof maxRows === "number" ? ticks.slice(0, maxRows) : ticks;
  const shouldUseScrollableList = typeof maxRows !== "number";

  const tapeRows = (
    <div>
      {visibleTicks.length === 0 && (
        <div className="flex min-h-[96px] items-center justify-center text-xs text-muted-foreground dark:text-brand-100/70 xl:min-h-[140px]">
          체결 데이터가 아직 없습니다.
        </div>
      )}
      {visibleTicks.map((t, i) => {
        const olderTick = visibleTicks[i + 1];
        const executionSide = resolveTickExecutionSide(t, olderTick);
        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-7 grid-cols-3 border-b border-border/40 px-2 text-[13px] dark:border-brand-800/35"
          >
            <div className="flex items-center tabular-nums">
              {fmtTime(t.tickTime)}
            </div>
            <div
              className={cn(
                "flex items-center justify-end tabular-nums",
                getChangeToneClass(
                  t.change,
                  "text-foreground dark:text-brand-50",
                ),
              )}
            >
              {fmt(t.price)}
            </div>
            <div
              className={cn(
                "flex items-center justify-end tabular-nums",
                volumeToneClass,
              )}
            >
              {fmt(t.tradeVolume)}
            </div>
          </div>
        );
      })}
    </div>
  );

  return (
    <div className="flex min-h-0 flex-col bg-background dark:bg-brand-900/20">
      <div className="grid h-8 grid-cols-3 border-b bg-muted/20 px-2 text-xs 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>
      {shouldUseScrollableList ? (
        <ScrollArea className="min-h-0 flex-1">{tapeRows}</ScrollArea>
      ) : (
        tapeRows
      )}
    </div>
  );
}

/** 누적호가 행 */
export 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 += 1) {
      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-blue-600 dark:text-blue-400">
            {fmt(r.askAcc)}
          </span>
          <span className="text-center font-medium tabular-nums">
            {fmt(r.price)}
          </span>
          <span className="text-right tabular-nums text-red-600 dark:text-red-400">
            {fmt(r.bidAcc)}
          </span>
        </div>
      ))}
    </div>
  );
}

/** 로딩 스켈레톤 */
export 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>
  );
}

interface SummaryMetric {
  label: string;
  value: string;
  tone?: "ask" | "bid";
}

/**
 * @description 실시간 요약 패널의 2열 메트릭 셀을 렌더링합니다.
 * @summary UI 흐름: SummaryPanel -> SummaryMetricCell -> 체결량 하단 정보 패널을 압축해 스크롤 없이 표시
 * @see features/trade/components/orderbook/orderbook-sections.tsx SummaryPanel summaryItems
 */
function SummaryMetricCell({
  label,
  value,
  tone,
}: {
  label: string;
  value: string;
  tone?: "ask" | "bid";
}) {
  return (
    <div className="flex h-full min-w-0 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="truncate text-[11px] text-muted-foreground dark:text-brand-100/70">
        {label}
      </span>
      <span
        className={cn(
          "shrink-0 text-xs font-semibold tabular-nums",
          tone === "ask" && "text-blue-600 dark:text-blue-400",
          tone === "bid" && "text-red-600",
        )}
      >
        {value}
      </span>
    </div>
  );
}

/** 잔량 깊이 바 */
function DepthBar({ ratio, side }: { ratio: number; side: "ask" | "bid" }) {
  if (ratio <= 0) return null;
  return (
    <div
      className={cn(
        "absolute inset-y-0.5 z-0 rounded-sm transition-[width] duration-150",
        side === "ask"
          ? "right-0.5 bg-blue-300/55 dark:bg-blue-700/50"
          : "left-0.5 bg-red-300/60 dark:bg-red-600/45",
      )}
      style={{ width: `${ratio}%` }}
    />
  );
}
