import { writable, derived } from 'svelte/store'
import type { StockPrice, OrderBook, AutoTradeLog } from '$lib/api/types'

export type WsMsg =
  | { type: 'price'; code: string; data: StockPrice }
  | { type: 'orderbook'; code: string; data: OrderBook }
  | { type: 'tradelog'; data: AutoTradeLog }
  | { type: 'market'; data: unknown }
  | { type: string; code?: string; data: unknown }

// 마지막으로 수신한 WebSocket 메시지
const { subscribe: msgSubscribe, set: setMsg } = writable<WsMsg | null>(null)

let socket: WebSocket | null = null
let reconnectTimer: ReturnType<typeof setTimeout> | null = null
let subscribedCodes = new Set<string>()

function connect() {
  if (socket && (socket.readyState === WebSocket.CONNECTING || socket.readyState === WebSocket.OPEN)) {
    return
  }

  const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:'
  socket = new WebSocket(`${protocol}//${location.host}/ws`)

  socket.onopen = () => {
    // 재연결 시 기존 구독 복원
    for (const code of subscribedCodes) {
      socket!.send(JSON.stringify({ type: 'subscribe', code }))
    }
  }

  socket.onmessage = (e) => {
    try {
      setMsg(JSON.parse(e.data))
    } catch {}
  }

  socket.onclose = () => {
    socket = null
    // 3초 후 자동 재연결
    reconnectTimer = setTimeout(connect, 3000)
  }

  socket.onerror = () => {
    socket?.close()
  }
}

// 종목 구독 추가
function subscribeCode(code: string) {
  subscribedCodes.add(code)
  if (socket?.readyState === WebSocket.OPEN) {
    socket.send(JSON.stringify({ type: 'subscribe', code }))
  } else {
    connect()
  }
}

// 종목 구독 해제
function unsubscribeCode(code: string) {
  subscribedCodes.delete(code)
  if (socket?.readyState === WebSocket.OPEN) {
    socket.send(JSON.stringify({ type: 'unsubscribe', code }))
  }
}

// 전체 구독 목록으로 일괄 구독
function subscribeCodes(codes: string[]) {
  for (const code of codes) {
    subscribeCode(code)
  }
}

// 연결 끊기
function disconnect() {
  if (reconnectTimer) clearTimeout(reconnectTimer)
  subscribedCodes.clear()
  socket?.close()
  socket = null
}

export const wsStore = {
  subscribe: msgSubscribe,
  connect,
  subscribeCode,
  unsubscribeCode,
  subscribeCodes,
  disconnect,
}

// 종목별 최신 시세 맵 (code → StockPrice)
export const priceMap = derived(
  { subscribe: msgSubscribe },
  ($msg, set, update) => {
    if ($msg?.type === 'price' && $msg.code) {
      update((m) => ({ ...m, [$msg.code!]: $msg.data as StockPrice }))
    }
  },
  {} as Record<string, StockPrice>
)

// 종목별 최신 호가창 맵 (code → OrderBook)
export const orderBookMap = derived(
  { subscribe: msgSubscribe },
  ($msg, set, update) => {
    if ($msg?.type === 'orderbook' && $msg.code) {
      update((m) => ({ ...m, [$msg.code!]: $msg.data as OrderBook }))
    }
  },
  {} as Record<string, OrderBook>
)

// 자동매매 로그 스트림
export const tradeLogStream = derived(
  { subscribe: msgSubscribe },
  ($msg) => {
    if ($msg?.type === 'tradelog') return $msg.data as AutoTradeLog
    return null
  }
)
