/**
 * 업비트 실시간 시세 WebSocket (브라우저 직접 연결)
 * @see https://global-docs.upbit.com/reference/websocket-candle
 */

export const UPBIT_KR_WS_URL = 'wss://api.upbit.com/websocket/v1';

/** 투자분석 timeInterval(1m, 1h, …) → 업비트 candle 타입 */
export function intervalToUpbitCandleType(interval: string): string {
  const map: Record<string, string> = {
    '1m': 'candle.1m',
    '3m': 'candle.3m',
    '5m': 'candle.5m',
    '10m': 'candle.10m',
    '15m': 'candle.15m',
    '30m': 'candle.30m',
    '1h': 'candle.60m',
    '4h': 'candle.240m',
    '1d': 'candle.1d',
    '1w': 'candle.1w',
    '1M': 'candle.1mon',
  };
  return map[interval] || 'candle.1m';
}

/** 업비트 candle 타입 문자열 → 앱 timeInterval (수신 메시지 라우팅용) */
export function candleTypeToInterval(upbitType: string): string | null {
  const map: Record<string, string> = {
    'candle.1m': '1m',
    'candle.3m': '3m',
    'candle.5m': '5m',
    'candle.10m': '10m',
    'candle.15m': '15m',
    'candle.30m': '30m',
    'candle.60m': '1h',
    'candle.240m': '4h',
    'candle.1d': '1d',
    'candle.1w': '1w',
    'candle.1mon': '1M',
  };
  return map[upbitType] ?? null;
}

export type UpbitCandleFrame = {
  /** KRW-BTC 등 — 멀티 마켓 구독 시 라우팅용 */
  code?: string;
  timestamp: number;
  open: number;
  high: number;
  low: number;
  close: number;
  volume: number;
};

/** 업비트 캔들 스트림 JSON → 차트용 (timestamp: ms) */
export function parseUpbitCandleMessage(raw: unknown): UpbitCandleFrame | null {
  if (raw == null || typeof raw !== 'object') return null;
  const o = raw as Record<string, unknown>;
  const type = o.type;
  if (typeof type !== 'string' || !type.startsWith('candle.')) return null;

  const code = typeof o.code === 'string' && o.code.trim() !== '' ? o.code.trim() : undefined;

  const open = num(o.opening_price);
  const high = num(o.high_price);
  const low = num(o.low_price);
  const close = num(o.trade_price);
  const vol = num(o.candle_acc_trade_volume);
  const ts = num(o.timestamp);
  if (open == null || high == null || low == null || close == null) return null;

  const timestamp = ts != null && ts > 0 ? (ts > 1e12 ? ts : ts * 1000) : Date.now();

  return {
    ...(code ? { code } : {}),
    timestamp,
    open,
    high,
    low,
    close,
    volume: vol ?? 0,
  };
}

function num(v: unknown): number | null {
  if (typeof v === 'number' && Number.isFinite(v)) return v;
  if (typeof v === 'string' && v.trim() !== '') {
    const n = parseFloat(v);
    return Number.isFinite(n) ? n : null;
  }
  return null;
}
