"use client";

import { useCallback, useEffect, useRef, useState } from "react";
import { ChevronDown, ChevronUp } from "lucide-react";
import { useShallow } from "zustand/react/shallow";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { useKisRuntimeStore } from "@/features/dashboard/store/use-kis-runtime-store";
import { KisAuthForm } from "@/features/dashboard/components/auth/KisAuthForm";
import { StockSearchForm } from "@/features/dashboard/components/search/StockSearchForm";
import { StockSearchHistory } from "@/features/dashboard/components/search/StockSearchHistory";
import { StockSearchResults } from "@/features/dashboard/components/search/StockSearchResults";
import { useStockSearch } from "@/features/dashboard/hooks/useStockSearch";
import { useOrderBook } from "@/features/dashboard/hooks/useOrderBook";
import { useKisTradeWebSocket } from "@/features/dashboard/hooks/useKisTradeWebSocket";
import { useStockOverview } from "@/features/dashboard/hooks/useStockOverview";
import { useCurrentPrice } from "@/features/dashboard/hooks/useCurrentPrice";
import { DashboardLayout } from "@/features/dashboard/components/layout/DashboardLayout";
import { StockHeader } from "@/features/dashboard/components/header/StockHeader";
import { OrderBook } from "@/features/dashboard/components/orderbook/OrderBook";
import { OrderForm } from "@/features/dashboard/components/order/OrderForm";
import { StockLineChart } from "@/features/dashboard/components/chart/StockLineChart";
import type {
  DashboardStockOrderBookResponse,
  DashboardStockSearchItem,
} from "@/features/dashboard/types/dashboard.types";

/**
 * @description 대시보드 메인 컨테이너
 * @see app/(main)/dashboard/page.tsx 로그인 완료 후 이 컴포넌트를 렌더링합니다.
 * @see features/dashboard/hooks/useStockSearch.ts 검색 입력/요청/히스토리 상태를 관리합니다.
 * @see features/dashboard/hooks/useStockOverview.ts 선택 종목 상세 상태를 관리합니다.
 */
export function DashboardContainer() {
  const skipNextAutoSearchRef = useRef(false);
  const hasInitializedAuthPanelRef = useRef(false);
  const searchShellRef = useRef<HTMLDivElement | null>(null);

  // 모바일에서는 초기 진입 시 API 패널을 접어 본문(차트/호가)을 먼저 보이게 합니다.
  const [isMobileViewport, setIsMobileViewport] = useState(false);
  const [isAuthPanelExpanded, setIsAuthPanelExpanded] = useState(true);
  const [isSearchPanelOpen, setIsSearchPanelOpen] = useState(false);

  const { verifiedCredentials, isKisVerified } = useKisRuntimeStore(
    useShallow((state) => ({
      verifiedCredentials: state.verifiedCredentials,
      isKisVerified: state.isKisVerified,
    })),
  );

  const {
    keyword,
    setKeyword,
    searchResults,
    setSearchError,
    isSearching,
    search,
    clearSearch,
    searchHistory,
    appendSearchHistory,
    removeSearchHistory,
    clearSearchHistory,
  } = useStockSearch();

  const { selectedStock, loadOverview, updateRealtimeTradeTick } =
    useStockOverview();

  // 호가 실시간 데이터 (체결 WS에서 동일 소켓으로 수신)
  const [realtimeOrderBook, setRealtimeOrderBook] =
    useState<DashboardStockOrderBookResponse | null>(null);

  const handleOrderBookMessage = useCallback(
    (data: DashboardStockOrderBookResponse) => {
      setRealtimeOrderBook(data);
    },
    [],
  );

  // 1. Trade WebSocket (체결 + 호가 통합)
  const { latestTick, recentTradeTicks } = useKisTradeWebSocket(
    selectedStock?.symbol,
    verifiedCredentials,
    isKisVerified,
    updateRealtimeTradeTick,
    {
      orderBookSymbol: selectedStock?.symbol,
      onOrderBookMessage: handleOrderBookMessage,
    },
  );

  // 2. OrderBook (REST 초기 조회 + WS 실시간 병합)
  const { orderBook, isLoading: isOrderBookLoading } = useOrderBook(
    selectedStock?.symbol,
    selectedStock?.market,
    verifiedCredentials,
    isKisVerified,
    {
      enabled: !!selectedStock && !!verifiedCredentials && isKisVerified,
      externalRealtimeOrderBook: realtimeOrderBook,
    },
  );

  // 3. Price Calculation Logic (Hook)
  const {
    currentPrice,
    change,
    changeRate,
    prevClose: referencePrice,
  } = useCurrentPrice({
    stock: selectedStock,
    latestTick,
    orderBook,
  });

  const canSearch = isKisVerified && !!verifiedCredentials;

  /**
   * @description 검색 전 API 인증 여부를 확인합니다.
   * @see features/dashboard/components/search/StockSearchForm.tsx 검색 제출 전 공통 가드로 사용합니다.
   */
  const ensureSearchReady = useCallback(() => {
    if (canSearch) return true;
    setSearchError("API 키 검증을 먼저 완료해 주세요.");
    return false;
  }, [canSearch, setSearchError]);

  const closeSearchPanel = useCallback(() => {
    setIsSearchPanelOpen(false);
  }, []);

  const openSearchPanel = useCallback(() => {
    if (!canSearch) return;
    setIsSearchPanelOpen(true);
  }, [canSearch]);

  /**
   * @description 검색 영역 포커스가 완전히 빠지면 드롭다운(검색결과/히스토리)을 닫습니다.
   * @see features/dashboard/components/search/StockSearchForm.tsx 입력 포커스 이벤트에서 열림 제어를 함께 사용합니다.
   */
  const handleSearchShellBlur = useCallback(
    (event: React.FocusEvent<HTMLDivElement>) => {
      const nextTarget = event.relatedTarget as Node | null;
      if (nextTarget && searchShellRef.current?.contains(nextTarget)) return;
      closeSearchPanel();
    },
    [closeSearchPanel],
  );

  const handleSearchShellKeyDown = useCallback(
    (event: React.KeyboardEvent<HTMLDivElement>) => {
      if (event.key !== "Escape") return;
      closeSearchPanel();
      (event.target as HTMLElement | null)?.blur?.();
    },
    [closeSearchPanel],
  );

  useEffect(() => {
    const mediaQuery = window.matchMedia("(max-width: 767px)");

    const applyViewportMode = (matches: boolean) => {
      setIsMobileViewport(matches);

      // 최초 1회: 모바일이면 접힘, 데스크탑이면 펼침.
      if (!hasInitializedAuthPanelRef.current) {
        setIsAuthPanelExpanded(!matches);
        hasInitializedAuthPanelRef.current = true;
        return;
      }

      // 데스크탑으로 돌아오면 항상 펼쳐 사용성을 유지합니다.
      if (!matches) {
        setIsAuthPanelExpanded(true);
      }
    };

    applyViewportMode(mediaQuery.matches);

    const onViewportChange = (event: MediaQueryListEvent) => {
      applyViewportMode(event.matches);
    };
    mediaQuery.addEventListener("change", onViewportChange);

    return () => mediaQuery.removeEventListener("change", onViewportChange);
  }, []);

  useEffect(() => {
    if (skipNextAutoSearchRef.current) {
      skipNextAutoSearchRef.current = false;
      return;
    }

    if (!canSearch) {
      clearSearch();
      return;
    }

    const trimmed = keyword.trim();
    if (!trimmed) {
      clearSearch();
      return;
    }

    const timer = window.setTimeout(() => {
      search(trimmed, verifiedCredentials);
    }, 220);

    return () => window.clearTimeout(timer);
  }, [canSearch, keyword, verifiedCredentials, search, clearSearch]);

  /**
   * @description 수동 검색 버튼(엔터 포함) 제출 이벤트를 처리합니다.
   * @see features/dashboard/components/search/StockSearchForm.tsx onSubmit 이벤트로 호출됩니다.
   */
  const handleSearchSubmit = useCallback(
    (event: React.FormEvent) => {
      event.preventDefault();
      if (!ensureSearchReady() || !verifiedCredentials) return;
      search(keyword, verifiedCredentials);
    },
    [ensureSearchReady, keyword, search, verifiedCredentials],
  );

  /**
   * @description 검색 결과/히스토리에서 종목을 선택하면 종목 상세를 로드하고 히스토리를 갱신합니다.
   * @see features/dashboard/components/search/StockSearchResults.tsx onSelect 이벤트
   * @see features/dashboard/components/search/StockSearchHistory.tsx onSelect 이벤트
   */
  const handleSelectStock = useCallback(
    (item: DashboardStockSearchItem) => {
      if (!ensureSearchReady() || !verifiedCredentials) return;

      // 같은 종목 재선택 시 중복 overview 요청을 막고 검색 목록만 닫습니다.
      if (selectedStock?.symbol === item.symbol) {
        clearSearch();
        closeSearchPanel();
        return;
      }

      // 카드 선택으로 keyword가 바뀔 때 자동 검색이 다시 실행되지 않게 한 번 건너뜁니다.
      skipNextAutoSearchRef.current = true;
      setKeyword(item.name);
      clearSearch();
      closeSearchPanel();
      appendSearchHistory(item);
      loadOverview(item.symbol, verifiedCredentials, item.market);
    },
    [
      ensureSearchReady,
      verifiedCredentials,
      selectedStock?.symbol,
      clearSearch,
      closeSearchPanel,
      setKeyword,
      appendSearchHistory,
      loadOverview,
    ],
  );

  return (
    <div className="relative h-full flex flex-col">
      {/* ========== AUTH STATUS ========== */}
      <div className="flex-none border-b bg-muted/40 transition-all duration-300 ease-in-out dark:border-brand-800/45 dark:bg-brand-900/28">
        <div className="flex items-center justify-between gap-2 px-3 py-2 text-xs sm:px-4">
          <div className="flex items-center gap-2">
            <span className="font-semibold">KIS API 연결 상태:</span>
            {isKisVerified ? (
              <span className="flex items-center font-medium text-brand-700 dark:text-brand-200">
                <span className="mr-1.5 h-2 w-2 rounded-full bg-brand-500 ring-2 ring-brand-100 dark:ring-brand-900" />
                연결됨 ({verifiedCredentials?.tradingEnv === "real" ? "실전" : "모의"})
              </span>
            ) : (
              <span className="text-muted-foreground flex items-center">
                <span className="mr-1.5 h-2 w-2 rounded-full bg-brand-200 dark:bg-brand-500/60" />
                미연결
              </span>
            )}
          </div>

          <Button
            type="button"
            size="sm"
            variant="outline"
            onClick={() => setIsAuthPanelExpanded((prev) => !prev)}
            className={cn(
              "h-8 shrink-0 gap-1.5 px-2.5 text-[11px] font-semibold",
              "border-brand-200 bg-brand-50 text-brand-700 hover:bg-brand-100 dark:border-brand-700/60 dark:bg-brand-900/30 dark:text-brand-200 dark:hover:bg-brand-900/45",
              !isAuthPanelExpanded &&
                isMobileViewport &&
                "ring-2 ring-brand-200 dark:ring-brand-600/60",
            )}
          >
            {isAuthPanelExpanded ? (
              <>
                <ChevronUp className="h-3.5 w-3.5" />
                API 설정 접기
              </>
            ) : (
              <>
                <ChevronDown className="h-3.5 w-3.5" />
                API 설정 펼치기
              </>
            )}
          </Button>
        </div>

        <div
          className={cn(
            "overflow-hidden transition-[max-height,opacity] duration-300 ease-in-out",
            isAuthPanelExpanded ? "max-h-[560px] opacity-100" : "max-h-0 opacity-0",
          )}
        >
          <div className="border-t bg-background p-4 dark:border-brand-800/45 dark:bg-brand-900/14">
            <KisAuthForm />
          </div>
        </div>
      </div>

      {/* ========== SEARCH ========== */}
      <div className="z-30 flex-none border-b bg-background/95 p-4 backdrop-blur-sm dark:border-brand-800/45 dark:bg-brand-900/22">
        <div
          ref={searchShellRef}
          onBlurCapture={handleSearchShellBlur}
          onKeyDownCapture={handleSearchShellKeyDown}
          className="relative mx-auto max-w-2xl"
        >
          <StockSearchForm
            keyword={keyword}
            onKeywordChange={setKeyword}
            onSubmit={handleSearchSubmit}
            onInputFocus={openSearchPanel}
            disabled={!canSearch}
            isLoading={isSearching}
          />

          {isSearchPanelOpen && canSearch && (
            <div className="absolute left-0 right-0 top-full z-50 mt-1 max-h-80 overflow-x-hidden overflow-y-auto rounded-md border bg-background shadow-lg dark:border-brand-800/45 dark:bg-brand-950/95">
              {searchResults.length > 0 ? (
                <StockSearchResults
                  items={searchResults}
                  onSelect={handleSelectStock}
                  selectedSymbol={selectedStock?.symbol}
                />
              ) : keyword.trim() ? (
                <div className="px-3 py-2 text-sm text-muted-foreground">
                  {isSearching ? "검색 중..." : "검색 결과가 없습니다."}
                </div>
              ) : searchHistory.length > 0 ? (
                <StockSearchHistory
                  items={searchHistory}
                  onSelect={handleSelectStock}
                  onRemove={removeSearchHistory}
                  onClear={clearSearchHistory}
                  selectedSymbol={selectedStock?.symbol}
                />
              ) : (
                <div className="px-3 py-2 text-sm text-muted-foreground">
                  최근 검색 종목이 없습니다.
                </div>
              )}
            </div>
          )}
        </div>
      </div>

      {/* ========== MAIN CONTENT ========== */}
      <div
        className={cn(
          "transition-opacity duration-200 h-full flex-1 min-h-0 overflow-x-hidden",
          !selectedStock && "opacity-20 pointer-events-none",
        )}
      >
        <DashboardLayout
          header={
            selectedStock ? (
              <StockHeader
                stock={selectedStock}
                price={currentPrice?.toLocaleString() ?? "0"}
                change={change?.toLocaleString() ?? "0"}
                changeRate={changeRate?.toFixed(2) ?? "0.00"}
                high={latestTick ? latestTick.high.toLocaleString() : undefined}
                low={latestTick ? latestTick.low.toLocaleString() : undefined}
                volume={
                  latestTick
                    ? latestTick.accumulatedVolume.toLocaleString()
                    : undefined
                }
              />
            ) : null
          }
          chart={
            selectedStock ? (
              <div className="p-0 h-full flex flex-col">
                <StockLineChart
                  symbol={selectedStock.symbol}
                  candles={selectedStock.candles}
                  credentials={verifiedCredentials}
                  latestTick={latestTick}
                />
              </div>
            ) : (
              <div className="h-full flex items-center justify-center text-muted-foreground">
                차트 영역
              </div>
            )
          }
          orderBook={
            <OrderBook
              symbol={selectedStock?.symbol}
              referencePrice={referencePrice}
              currentPrice={currentPrice}
              latestTick={latestTick}
              recentTicks={recentTradeTicks}
              orderBook={orderBook}
              isLoading={isOrderBookLoading}
            />
          }
          orderForm={<OrderForm stock={selectedStock ?? undefined} />}
        />
      </div>
    </div>
  );
}
