/**
 * 업비트 최근 체결 (호가창 좌측 체결 목록용)
 */
import { useState, useEffect, useRef, useCallback } from 'react';

export interface RecentTrade {
  price:  number;
  volume: number;
  side:   'ask' | 'bid';  // ask=매도체결, bid=매수체결
  time:   number;
}

const MAX_TRADES = 12;

interface UpbitTradeRaw {
  market:       string;
  trade_price:  number;
  trade_volume: number;
  ask_bid:      'ASK' | 'BID';
  timestamp:    number;
}

interface UpbitTradeWs {
  type:          string;
  code:          string;
  trade_price:   number;
  trade_volume:  number;
  ask_bid:       'ASK' | 'BID';
  timestamp:     number;
}

export function useUpbitRecentTrades(market: string) {
  const [trades, setTrades] = useState<RecentTrade[]>([]);
  const [strength, setStrength] = useState<number | null>(null);

  const wsRef = useRef<WebSocket | null>(null);
  const mountedRef = useRef(true);

  const pushTrade = useCallback((t: RecentTrade) => {
    setTrades(prev => {
      const next = [t, ...prev].slice(0, MAX_TRADES);
      const buyVol = next.filter(x => x.side === 'bid').reduce((s, x) => s + x.volume, 0);
      const sellVol = next.filter(x => x.side === 'ask').reduce((s, x) => s + x.volume, 0);
      if (sellVol > 0) setStrength((buyVol / sellVol) * 100);
      else if (buyVol > 0) setStrength(100);
      return next;
    });
  }, []);

  const fetchSnapshot = useCallback(async () => {
    try {
      const res = await fetch(`/upbit-api/v1/trades/ticks?market=${market}&count=${MAX_TRADES}`);
      if (!res.ok) return;
      const data: UpbitTradeRaw[] = await res.json();
      const list: RecentTrade[] = data.map(d => ({
        price:  d.trade_price,
        volume: d.trade_volume,
        side:   d.ask_bid === 'ASK' ? 'ask' : 'bid',
        time:   d.timestamp,
      }));
      setTrades(list);
      const buyVol = list.filter(x => x.side === 'bid').reduce((s, x) => s + x.volume, 0);
      const sellVol = list.filter(x => x.side === 'ask').reduce((s, x) => s + x.volume, 0);
      if (sellVol > 0) setStrength((buyVol / sellVol) * 100);
    } catch { /* ignore */ }
  }, [market]);

  useEffect(() => {
    mountedRef.current = true;
    setTrades([]);
    setStrength(null);
    fetchSnapshot();

    const proto = window.location.protocol === 'https:' ? 'wss' : 'ws';
    const ws = new WebSocket(`${proto}://${window.location.host}/upbit-ws`);
    ws.binaryType = 'arraybuffer';
    wsRef.current = ws;

    ws.onopen = () => {
      ws.send(JSON.stringify([
        { ticket: `tr-${market}-${Date.now()}` },
        { type: 'trade', codes: [market] },
      ]));
    };

    ws.onmessage = async (e: MessageEvent) => {
      if (!mountedRef.current) return;
      try {
        let text: string;
        if (typeof e.data === 'string') text = e.data;
        else if (e.data instanceof ArrayBuffer) text = new TextDecoder().decode(e.data);
        else if (e.data instanceof Blob) text = await e.data.text();
        else return;
        const msg: UpbitTradeWs = JSON.parse(text);
        if (msg.type === 'trade' && msg.code === market) {
          pushTrade({
            price:  msg.trade_price,
            volume: msg.trade_volume,
            side:   msg.ask_bid === 'ASK' ? 'ask' : 'bid',
            time:   msg.timestamp,
          });
        }
      } catch { /* ignore */ }
    };

    return () => {
      mountedRef.current = false;
      if (wsRef.current) {
        wsRef.current.onopen = null;
        wsRef.current.onmessage = null;
        wsRef.current.onclose = null;
        wsRef.current.close();
        wsRef.current = null;
      }
    };
  }, [market, fetchSnapshot, pushTrade]);

  return { trades, strength };
}
