"use client";

import { type FormEvent, useCallback, useEffect, useState } from "react";
import { useSearchParams } from "next/navigation";
import { useShallow } from "zustand/react/shallow";
import { LoadingSpinner } from "@/components/ui/loading-spinner";
import { useKisRuntimeStore } from "@/features/settings/store/use-kis-runtime-store";
import { TradeAccessGate } from "@/features/trade/components/guards/TradeAccessGate";
import { TradeDashboardContent } from "@/features/trade/components/layout/TradeDashboardContent";
import { TradeSearchSection } from "@/features/trade/components/search/TradeSearchSection";
import { useStockSearch } from "@/features/trade/hooks/useStockSearch";
import { useOrderBook } from "@/features/trade/hooks/useOrderBook";
import { useKisTradeWebSocket } from "@/features/trade/hooks/useKisTradeWebSocket";
import { useStockOverview } from "@/features/trade/hooks/useStockOverview";
import { useCurrentPrice } from "@/features/trade/hooks/useCurrentPrice";
import { useTradeSearchPanel } from "@/features/trade/hooks/useTradeSearchPanel";
import type {
  DashboardStockOrderBookResponse,
  DashboardStockSearchItem,
} from "@/features/trade/types/trade.types";

/**
 * @description 트레이딩 페이지 메인 컨테이너입니다.
 * @see app/(main)/trade/page.tsx 로그인 완료 후 이 컴포넌트를 렌더링합니다.
 * @see app/(main)/settings/page.tsx 미인증 상태일 때 설정 페이지로 이동하도록 안내합니다.
 * @see features/trade/hooks/useStockSearch.ts 검색 입력/요청/히스토리 상태를 관리합니다.
 * @see features/trade/hooks/useStockOverview.ts 선택 종목 상세 상태를 관리합니다.
 */
export function TradeContainer() {
  const searchParams = useSearchParams();
  const symbolParam = searchParams.get("symbol");
  const nameParam = searchParams.get("name");

  // [State] 호가 실시간 데이터 (체결 WS와 동일 소켓에서 수신)
  const [realtimeOrderBook, setRealtimeOrderBook] =
    useState<DashboardStockOrderBookResponse | null>(null);
  const { verifiedCredentials, isKisVerified, _hasHydrated } =
    useKisRuntimeStore(
      useShallow((state) => ({
        verifiedCredentials: state.verifiedCredentials,
        isKisVerified: state.isKisVerified,
        _hasHydrated: state._hasHydrated,
      })),
    );

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

  /**
   * [Effect] URL 파라미터(symbol) 감지 시 자동 종목 로드
   * 대시보드 등 외부에서 종목 코드를 넘겨받아 트레이딩 페이지로 진입할 때 사용합니다.
   */
  useEffect(() => {
    if (symbolParam && isKisVerified && verifiedCredentials && _hasHydrated) {
      // 현재 선택된 종목과 파라미터가 다를 경우에만 자동 로드 수행
      if (selectedStock?.symbol !== symbolParam) {
        setKeyword(nameParam || symbolParam);
        appendSearchHistory({
          symbol: symbolParam,
          name: nameParam || symbolParam,
          market: "KOSPI", // 기본값 설정, loadOverview 이후 실제 데이터로 보완됨
        });
        loadOverview(symbolParam, verifiedCredentials);
      }
    }
  }, [
    symbolParam,
    nameParam,
    isKisVerified,
    verifiedCredentials,
    _hasHydrated,
    selectedStock?.symbol,
    loadOverview,
    setKeyword,
    appendSearchHistory,
  ]);

  const canTrade = isKisVerified && !!verifiedCredentials;
  const canSearch = canTrade;

  const {
    searchShellRef,
    isSearchPanelOpen,
    markSkipNextAutoSearch,
    openSearchPanel,
    closeSearchPanel,
    handleSearchShellBlur,
    handleSearchShellKeyDown,
  } = useTradeSearchPanel({
    canSearch,
    keyword,
    verifiedCredentials,
    search,
    clearSearch,
  });

  /**
   * @description 체결 WS에서 전달받은 실시간 호가를 상태에 저장합니다.
   * @see features/trade/hooks/useKisTradeWebSocket.ts onOrderBookMessage 콜백
   * @see features/trade/hooks/useOrderBook.ts externalRealtimeOrderBook 주입
   */
  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,
  });

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

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

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

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

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

  if (!_hasHydrated) {
    return (
      <div className="flex h-full items-center justify-center p-6">
        <LoadingSpinner />
      </div>
    );
  }

  if (!canTrade) {
    return <TradeAccessGate canTrade={canTrade} />;
  }

  return (
    <div className="relative h-full flex flex-col">
      {/* ========== SEARCH SECTION ========== */}
      <TradeSearchSection
        canSearch={canSearch}
        isSearchPanelOpen={isSearchPanelOpen}
        isSearching={isSearching}
        keyword={keyword}
        selectedSymbol={selectedStock?.symbol}
        searchResults={searchResults}
        searchHistory={searchHistory}
        searchShellRef={searchShellRef}
        onKeywordChange={setKeyword}
        onSearchSubmit={handleSearchSubmit}
        onSearchFocus={openSearchPanel}
        onSearchShellBlur={handleSearchShellBlur}
        onSearchShellKeyDown={handleSearchShellKeyDown}
        onSelectStock={handleSelectStock}
        onRemoveHistory={removeSearchHistory}
        onClearHistory={clearSearchHistory}
      />

      {/* ========== DASHBOARD SECTION ========== */}
      <TradeDashboardContent
        selectedStock={selectedStock}
        verifiedCredentials={verifiedCredentials}
        latestTick={latestTick}
        recentTradeTicks={recentTradeTicks}
        orderBook={orderBook}
        isOrderBookLoading={isOrderBookLoading}
        referencePrice={referencePrice}
        currentPrice={currentPrice}
        change={change}
        changeRate={changeRate}
      />
    </div>
  );
}
