const { Server: ServerIO } = require('socket.io')
const { io: ClientIO, connect } = require('socket.io-client')
const { readHostList } = require('../utils')
const { clientPort } = require('../config')
const { verifyAuthSync } = require('../utils')

let clientsData = {}
async function getClientsInfo(clientSockets, clear = false) {
  clientSockets = []
  if (clear) clientsData = {}
  let hostList = await readHostList()
  hostList
    ?.map(({ host, name }) => {
      let clientSocket = ClientIO(`http://${ host }:${ clientPort }`, {
        path: '/client/os-info',
        forceNew: true,
        timeout: 5000,
        reconnectionDelay: 5000,
        reconnectionAttempts: 1000
      })
      // 将与客户端连接的socket实例保存起来，web端断开时关闭这些连接
      clientSockets.push(clientSocket)
      return {
        host,
        name,
        clientSocket
      }
    })
    .map(({ host, name, clientSocket }) => {
      clientsData[host] = { connect: false }
      clientSocket
        .on('connect', () => {
          consola.success('client connect success:', host, name)
          clientSocket.on('client_data', (osData) => {
            try {
              // clientsData[host] = { connect: true, osData: JSON.parse(osData) }
              clientsData[host] = { connect: true, ...osData }
            } catch (error) {
              console.warn('client_data, parse osData error: ', error.message)
            }
          })
          clientSocket.on('client_error', (error) => {
            clientsData[host] = { connect: true, error: `client_error: ${ error }` }
          })
        })
        .on('connect_error', (error) => { // 连接失败
          // consola.error('client connect fail:', host, name, error.message)
          try {
            clientsData[host] = { connect: false, error: `client_connect_error: ${ error }` }
          } catch (error) {
            console.warn('connect_error: ', error.message)
          }
        })
        .on('disconnect', (error) => { // 一方主动断开连接
          // consola.info('client connect disconnect:', host, name)
          try {
            clientsData[host] = { connect: false, error: `client_disconnect: ${ error }` }
          } catch (error) {
            console.warn('disconnect: ', error.message)
          }
        })
    })
}

module.exports = (httpServer) => {
  const serverIo = new ServerIO(httpServer, {
    path: '/clients',
    cors: {
      origin: '*' // 需配置跨域
    }
  })

  serverIo.on('connection', (socket) => {
    // 前者兼容nginx反代, 后者兼容nodejs自身服务
    let clientIp = socket.handshake.headers['x-forwarded-for'] || socket.handshake.address
    socket.on('init_clients_data', async ({ token }) => {
      const { code, msg } = await verifyAuthSync(token, clientIp)
      if (code !== 1) {
        socket.emit('token_verify_fail', msg || '鉴权失败')
        socket.disconnect()
        return
      }

      let clientSockets = []
      clientSockets.push(socket)

      getClientsInfo(clientSockets, true)
      socket.emit('clients_data', clientsData)

      socket.on('refresh_clients_data', async () => {
        consola.info('refresh clients-socket: ', clientSockets.length)
        getClientsInfo(clientSockets, false)
      })

      let timer = null
      timer = setInterval(() => {
        socket.emit('clients_data', clientsData)
      }, 1500)

      socket.on('disconnect', () => {
        if (timer) clearInterval(timer)
        clientSockets.forEach(socket => socket.close && socket.close())
        clientSockets = null
        clientsData = {}
        consola.info('clients-socket 连接断开: ', socket.id)
      })
    })
  })
}
