const storageAccessService = require('../storage-access/service.js')
const settingsService = require('../../store/settings-store.js')
const {
  bytesToHex,
  bytesToUtf8Text,
  stringToUtf8Bytes
} = require('../../utils/binary-utils.js')
const {
  parseHexBytes,
  validateHexText
} = require('../../utils/validation.js')

const LOG_MODE_OPTIONS = [
  { key: 'hex', label: 'HEX' },
  { key: 'text', label: '文本' }
]

function getStorageAccessSpecialCommands() {
  return storageAccessService.getControlCommands()
}

function getStorageAccessAreaOptions() {
  return storageAccessService.getMemoryAreaOptions()
}

function getBinaryModeLabel(mode) {
  return mode === 'text' ? '文本' : 'HEX'
}

function getNextBinaryMode(mode) {
  return mode === 'hex' ? 'text' : 'hex'
}

function getBinaryModeToggleText(mode) {
  return getBinaryModeLabel(getNextBinaryMode(mode))
}

function normalizeSerialState(current = {}, changed = {}) {
  const next = {
    serialInputText: current.serialInputText || '',
    serialMode: current.serialMode || 'hex',
    ...changed
  }
  const mode = next.serialMode === 'text' ? 'text' : 'hex'
  const inputText = String(next.serialInputText || '')
  let errorText = ''
  let bytes = []
  let previewHex = ''

  if (inputText.trim()) {
    if (mode === 'hex') {
      errorText = validateHexText(inputText)
      if (!errorText) {
        bytes = parseHexBytes(inputText)
        previewHex = bytesToHex(bytes, ' ')
      }
    } else {
      bytes = stringToUtf8Bytes(inputText)
      previewHex = bytesToHex(bytes, ' ')
    }
  }

  return {
    serialErrorText: errorText,
    serialInputText: inputText,
    serialMode: mode,
    serialModeLabel: getBinaryModeLabel(mode),
    serialModeToggleText: getBinaryModeToggleText(mode),
    serialPreviewHex: previewHex,
    serialPreviewLengthText: bytes.length ? `${bytes.length} bytes` : '--'
  }
}

function normalizeStorageAccessState(current = {}, changed = {}) {
  return storageAccessService.normalizeMemoryCommandState(current, changed)
}

function normalizeStorageAccessSpecialState(current = {}, changed = {}) {
  const controlState = storageAccessService.normalizeControlState(current, changed)

  return {
    storageAccessSpecialCommands: getStorageAccessSpecialCommands(),
    ...controlState
  }
}

function getLogPayloadText(log, mode) {
  if (!log) return '--'

  if (mode === 'text') {
    const payloadText = String(log.payloadText || '').trim()
    if (payloadText) return payloadText

    const bytes = Array.isArray(log.payloadBytes) ? log.payloadBytes : []
    return bytesToUtf8Text(bytes) || String(log.payload || '').trim() || '--'
  }

  if (typeof log.payload === 'string' && log.payload) {
    return log.payload
  }

  const bytes = Array.isArray(log.payloadBytes) ? log.payloadBytes : []
  return bytes.length ? bytesToHex(bytes, ' ') : '--'
}

function decorateLogs(logs, mode) {
  return (logs || []).map((item) => ({
    ...item,
    displayText: getLogPayloadText(item, mode)
  }))
}

function getProtocolModeState(settingsState = {}) {
  const isNoProtocol = settingsService.isNoProtocol(settingsState.protocolMode)
  const isModbusProtocol = settingsService.isModbusProtocol(settingsState.protocolMode)
  const isStorageAccessProtocol = settingsService.isStorageAccessProtocol(settingsState.protocolMode)

  return {
    isNoProtocol,
    isModbusProtocol,
    isStorageAccessProtocol
  }
}

function getManualStatePayload(manualState = {}) {
  const commands = Array.isArray(manualState.protocolCommands) ? manualState.protocolCommands : []
  const command = commands[Number(manualState.commandIndex) || 0] || commands[0] || {}

  return {
    ...manualState,
    protocolCommandLabel: command.label || '指令',
    protocolResponseText: manualState.protocolResponseText || '',
    protocolSendLabel: '发送',
    showProtocolMultipleButton: command.inputMode === 'multiple',
    protocolTitleText: '标准 Modbus'
  }
}

module.exports = {
  LOG_MODE_OPTIONS,
  decorateLogs,
  getStorageAccessAreaOptions,
  getLogModeToggleText: getBinaryModeToggleText,
  getManualStatePayload,
  getNextLogMode: getNextBinaryMode,
  getNextSerialMode: getNextBinaryMode,
  getProtocolModeState,
  normalizeSerialState,
  normalizeStorageAccessSpecialState,
  normalizeStorageAccessState
}
