import path from 'path'
import fs from 'fs'
import lodash from 'lodash'
import { Telnet } from 'telnet-client'
import { getPgTableData } from './postgres'


// 在目标服务器上,获取 node 可用的端口
export async function getAvailableNodePort (ip: string, startPort = 30000) {
  const tryPortAvailable = async function (port: number): Promise<number> {
    let telnet = new Telnet()
    const params = {
      host: ip,
      port: port,
      negotiationMandatory: false,
      timeout: 1500
    }
    try {
      await telnet.connect(params)
      telnet.end()
      return tryPortAvailable(port + 1)
    } catch (err) {
      return port
    }
  }
  return tryPortAvailable(startPort)
}

export async function checkSshExists (username: string) {
  let gitEmail = username + '@greaconsulting.com'
  let docker = createDockerFactory(username)
  // 创建 node 容器
  let container = await docker.checkContainer(username + '.node')
  if (!container) {
    throw new Error('没有创建容器,请先初始化容器')
  }
  await docker.startContainer({ container })
  let sshKey = ''
  try {
    sshKey = await docker.getFile({ container, path: '/root/.ssh/id_rsa.pub' })
  } catch (err) {
    await docker.execContainerCommand({ container, cmd: 'rm -rf /root/.ssh' })
    await docker.execContainerCommand({ container, cmd: `ssh-keygen -f /root/.ssh/id_rsa -t ed25519 -C "${gitEmail}"` })
    sshKey = await docker.getFile({ container, path: '/root/.ssh/id_rsa.pub' })
  }
  return sshKey
}


export async function copyAndCreateServerPropertiesV2InDocker (username: string) {
  let docker = createDockerFactory(username)
  let container = await docker.checkContainer( username + '.node')
  if (!container) {
      throw new Error('没有创建容器,请先初始化容器')
  }

  let backendText = fs.readFileSync(path.resolve('./public/files/v2/application-server.properties'), { encoding: 'utf-8' })
  const userDefaultSettingStr = fs.readFileSync(path.resolve('./public/files/default-user-setting.json'), { encoding: 'utf-8'})
  const userConfigs = await getPgTableData('v2', username)
  const userDefaultSetting = JSON.parse(userDefaultSettingStr)

  const fn = (f: (obj: Record<string, any>) => string) => f(userConfigs!) || f(userDefaultSetting)

  // postgres config
  backendText = backendText.replace(/spring.datasource.url=(.*?)\r?\n/, `spring.datasource.url=jdbc:postgresql://${PgHost}:${PgPort}/${username}\n`)
  backendText = backendText.replace(/spring.datasource.username=(.*?)\r?\n/, `spring.datasource.username=${useRuntimeConfig().pgUser}\n`)
  backendText = backendText.replace(/spring.datasource.password=(.*?)\r?\n/, `spring.datasource.password=${useRuntimeConfig().pgPassword}\n`)

  // redis config
  backendText = backendText.replace(/spring.redis.host=(.*?)\r?\n/, `spring.redis.host=${HOST}\n`)

  // zookeeper config
  backendText = backendText.replace(/logwire.register-center-server-list=(.*?)\r?\n/, `logwire.register-center-server-list=${HOST}:2181\n`)

  // rocketmq config
  backendText = backendText.replace(/logwire.mq.name-srv-address=(.*?)\r?\n/, `logwire.mq.name-srv-address=${HOST}:9876\n`)

  // tenants config
  backendText = backendText.replace(/logwire.tenants\[0\].id=(.*?)\r?\n/, `logwire.tenants[0].id=${fn(o => o.tenants?.id)}\n`)
  backendText = backendText.replace(/logwire.tenants\[0\].host=(.*?)\r?\n/, `logwire.tenants[0].host=${fn(o => o.tenants?.host)}\n`)
  backendText = backendText.replace(/logwire.tenants\[0\].database-schema=(.*?)\r?\n/, `logwire.tenants[0].database-schema=${fn(o => o.tenants?.["database-schema"])}\n`)
  backendText = backendText.replace(/logwire.tenants\[0\].primary-namespace=(.*?)\r?\n/, `logwire.tenants[0].primary-namespace=${fn(o => o.tenants?.["primary-namespace"])}\n`)

  // 设计器配置
  backendText = backendText.replace(/logwire.tenants\[0\].designer.trust-ip=(.*?)\r?\n/, `logwire.tenants[0].designer.trust-ip=${HOST}\n`)

  // user personal config
  const customServerProperties: { key: string, value: string }[] = userConfigs!.serverProperties || []
  customServerProperties.forEach(item => {
    const RegExpKey = item.key.replaceAll('[', '\\[').replaceAll(']', '\\]').replace('.', '\\.')
    if (backendText.match(new RegExp(`#${RegExpKey}=(.*?)\n`))) {
      backendText = backendText.replace(new RegExp(`#${RegExpKey}=(.*?)\n`), `${item.key}=${item.value}\n`)
    } else if (backendText.match(new RegExp(`${RegExpKey}=(.*?)\n`))) {
      backendText = backendText.replace(new RegExp(`${RegExpKey}=(.*?)\n`), `${item.key}=${item.value}\n`)
    } else { // 如果完全没有匹配到内容,则直接追加到最后
      backendText += `\n${item.key}=${item.value}\n`
    }
  })
  
  await docker.writeFile({ container, path: '/var/logwire-backend/build-output/backend/config/application-server.properties', text: '\'' + backendText.replace(/'/g, '"') + '\'' })
}

export async function copyAndCreateGatewayPropertiesV2InDocker (username: string) {
  let docker = createDockerFactory(username)
  let container = await docker.checkContainer( username + '.node')
  if (!container) {
      throw new Error('没有创建容器,请先初始化容器')
  }
  let gatewayText = fs.readFileSync(path.resolve('./public/files/v2/application-gateway.properties'), { encoding: 'utf-8' })
  // zookeeper config
  gatewayText = gatewayText.replace(/gateway.register-center-server-list=(.*?)\r?\n/, `gateway.register-center-server-list=${HOST}:2181\n`)
  // rocketmq config
  gatewayText = gatewayText.replace(/gateway.mq.name-srv-address=(.*?)\r?\n/, `gateway.mq.name-srv-address=${HOST}:9876`)

   await docker.writeFile({ container, path: '/var/logwire-backend/build-output/gateway/config/application-gateway.properties', text: '\'' + gatewayText.replace(/'/g, '"') + '\'' })
}

export async function copyAndCreateServerPropertiesV1InDocker (username: string) {
  let docker = createDockerFactory(username)
  let container = await docker.checkContainer( username + '.node')
  if (!container) {
      throw new Error('没有创建容器,请先初始化容器')
  }
  let backendText = fs.readFileSync(path.resolve('./public/files/v1/application.properties'), { encoding: 'utf-8' })
  const userConfigs = await getPgTableData('v1', username)

  // postgres config
  backendText = backendText.replace(/spring.datasource.url=(.*?)\r?\n/, `spring.datasource.url=jdbc:postgresql://${PgHost}:${PgPort}/${username + '_v1'}\n`)
  backendText = backendText.replace(/spring.datasource.username=(.*?)\r?\n/, `spring.datasource.username=${useRuntimeConfig().pgUser}\n`)
  backendText = backendText.replace(/spring.datasource.password=(.*?)\r?\n/, `spring.datasource.password=${useRuntimeConfig().pgPassword}\n`)

  // redis config
  backendText = backendText.replace(/spring.redis.host=(.*?)\r?\n/, `spring.redis.host=${HOST}\n`)

  // user personal config
  const customServerProperties: { key: string, value: string }[] = userConfigs!.serverProperties || []
  customServerProperties.forEach(item => {
    const RegExpKey = item.key.replaceAll('[', '\\[').replaceAll(']', '\\]').replace('.', '\\.')
    if (backendText.match(new RegExp(`#${RegExpKey}=(.*?)\n`))) {
      backendText = backendText.replace(new RegExp(`#${RegExpKey}=(.*?)\n`), `${item.key}=${item.value}\n`)
    } else if (backendText.match(new RegExp(`${RegExpKey}=(.*?)\n`))) {
      backendText = backendText.replace(new RegExp(`${RegExpKey}=(.*?)\n`), `${item.key}=${item.value}\n`)
    } else { // 如果完全没有匹配到内容,则直接追加到最后
      backendText += `\n${item.key}=${item.value}\n`
    }
  })
  
  await docker.writeFile({ container, path: '/var/logwire-platform/dist/config/application.properties', text: '\'' + backendText.replace(/'/g, '"') + '\'' })
}

export async function copyAndCreateNginxConfInDocker (username: string) {
  let docker = createDockerFactory(username)
  let container = await docker.checkContainer( username + '.node')
  if (!container) {
      throw new Error('没有创建容器,请先初始化容器')
  }
  const userDefaultSettingStr = fs.readFileSync(path.resolve('./public/files/default-user-setting.json'), { encoding: 'utf-8'})
  const userDefaultSetting = JSON.parse(userDefaultSettingStr)
  const userConfigs = await getPgTableData('v2', username)
  const nginxConfigStr = fs.readFileSync(path.resolve('./public/files/nginx.conf'), { encoding: 'utf-8' })
  // 修改调试端口的 NGINX 配置
  const replacedNginxConfig = nginxConfigStr.replace(/192.168.1.94/, userConfigs?.debug?.host || userDefaultSetting.debug.host)

  await docker.writeFile({ container, path: '/etc/nginx/nginx.conf', text: '\'' + replacedNginxConfig + '\'' })
}

export function getPlatformRootFolder (platform: 'v1' | 'v2') {
  return platform === 'v1'
    ? '/var/logwire-platform'
    : '/var/logwire-backend'
}