import { ref } from 'vue'
import { isSessionReady, type TermSessionData } from './types'

const K_HIST = 'nexus_term_history'

function loadGlobalHistory(): string[] {
  try {
    return JSON.parse(localStorage.getItem(K_HIST) || '[]')
  } catch {
    return []
  }
}

export function useTerminalCmdBar(
  getActiveSession: () => TermSessionData | null,
  sendWsData: (sessionId: string, data: string) => boolean,
  onNotConnected?: () => void,
) {
  const cmdInput = ref('')

  function sendCmd() {
    const s = getActiveSession()
    if (!s) return
    if (!isSessionReady(s)) {
      onNotConnected?.()
      return
    }
    const cmd = cmdInput.value
    if (!cmd) return
    s.cmdHistory.push(cmd)
    s.cmdIdx = -1
    if (!sendWsData(s.id, cmd + '\r')) return
    cmdInput.value = ''
    let hist: string[] = loadGlobalHistory()
    if (hist.length >= 200) hist.shift()
    hist.push(cmd)
    localStorage.setItem(K_HIST, JSON.stringify(hist))
  }

  function onCmdKeydown(e: KeyboardEvent) {
    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault()
      sendCmd()
      return
    }
    if (e.key === 'ArrowUp') {
      e.preventDefault()
      cmdHistoryUp()
      return
    }
    if (e.key === 'ArrowDown') {
      e.preventDefault()
      cmdHistoryDown()
    }
  }

  function cmdHistoryUp() {
    const s = getActiveSession()
    if (!s) return
    if (s.cmdIdx < s.cmdHistory.length - 1) {
      s.cmdIdx++
      cmdInput.value = s.cmdHistory[s.cmdHistory.length - 1 - s.cmdIdx]
    }
  }

  function cmdHistoryDown() {
    const s = getActiveSession()
    if (!s) return
    if (s.cmdIdx > 0) {
      s.cmdIdx--
      cmdInput.value = s.cmdHistory[s.cmdHistory.length - 1 - s.cmdIdx]
    } else {
      s.cmdIdx = -1
      cmdInput.value = ''
    }
  }

  function loadHistoryForNewSession(): string[] {
    return [...loadGlobalHistory()]
  }

  return {
    cmdInput,
    sendCmd,
    onCmdKeydown,
    cmdHistoryUp,
    cmdHistoryDown,
    loadHistoryForNewSession,
  }
}

export type CmdInputExpose = {
  getInputEl: () => HTMLTextAreaElement | HTMLInputElement | null
  focusInput: () => void
  insertAtSelection: (text: string) => void
  getSelectionText: () => string
  selectAllInput: () => void
}
