/**
 * load data from db
 */

import { dbNames, getData, fetchInitData } from '../common/db'
import parseInt10 from '../common/parse-int10'
import { infoTabs, statusMap, defaultEnvLang } from '../common/constants'
import generate from '../common/id-with-stamp'
import { refsStatic } from '../components/common/ref'
import defaultSettings from '../common/default-setting'
import encodes from '../components/bookmark-form/common/encodes'
import { initWsCommon } from '../common/fetch-from-server'
import safeParse from '../common/parse-json-safe'
import initWatch from './watch'
import { parseQuickConnect } from '../common/parse-quick-connect'

function getHost (argv, opts) {
  const arr = argv
  let i = arr.length - 1
  const reg = /^(?:([\w\d-_]+)@)?([\w\d-_]+\.[\w\d-_.]+)(?::([\d]+))?$/
  for (; i >= 0; i--) {
    const str = arr[i]
    const mt = str.match(reg)
    if (mt) {
      const port = mt[3]
      const user = mt[1]
      return {
        host: mt[2],
        username: user,
        port: port ? parseInt10(port) : 22
      }
    }
  }
  return {}
}

export async function addTabFromCommandLine (store, opts) {
  console.debug('command line params', opts)
  if (!opts) {
    return false
  }
  const {
    isHelp,
    helpInfo,
    options,
    argv
  } = opts
  if (helpInfo) {
    store.commandLineHelp = helpInfo
  }
  if (isHelp) {
    return store.openAbout(infoTabs.cmd)
  }
  // Check if argv contains a protocol URL (e.g., ssh://user@host)
  // and use parseQuickConnect for proper parsing
  if (argv && argv.length) {
    const protocolUrl = argv.find(arg =>
      /^(ssh|telnet|rdp|vnc|serial|spice|ftp|http|https|electerm):\/\//i.test(arg)
    )
    if (protocolUrl) {
      const parsed = parseQuickConnect(protocolUrl)
      if (parsed) {
        return store.ipcOpenTab(parsed)
      }
    }
  }

  const conf = getHost(argv, options)
  const update = {
    passphrase: options.passphrase,
    password: options.password,
    // port: options.port ? parseInt(options.port, 10) : 22,
    type: 'ssh',
    status: statusMap.processing,
    id: generate(),
    encode: encodes[0],
    envLang: defaultEnvLang,
    enableSsh: !options.sftpOnly,
    authType: 'password',
    pane: options.type || 'terminal',
    term: defaultSettings.terminalType,
    startDirectoryLocal: options.initFolder
  }
  if (options.setEnv) {
    update.setEnv = options.setEnv
  }
  if (options.title) {
    update.title = options.title
  }
  if (options.user) {
    update.username = options.user
  }
  if (options.port && parseInt10(options.port)) {
    update.port = parseInt10(options.port)
  }
  if (options.opts) {
    const opts = safeParse(options.opts)
    if (opts !== options.opts) {
      Object.assign(update, opts)
      update.fromCmdLine = true
    }
  }
  if (options.tp) {
    update.type = options.tp
    update.fromCmdLine = true
  }
  Object.assign(conf, update)
  if (options.privateKeyPath) {
    conf.privateKey = await window.fs.readFile(options.privateKeyPath)
  }
  console.debug('command line opts', conf)
  if (
    (conf.username && conf.host) ||
    conf.fromCmdLine
  ) {
    store.ipcOpenTab(conf)
  } else if (
    options.initFolder &&
    !(store.config.onStartSessions || []).length &&
    store.config.initDefaultTabOnStart
  ) {
    window.initFolder = options.initFolder
  }
  if (options.batchOp) {
    refsStatic.get('batch-op-runner')?.runBatchOpFromFile(options.batchOp)
  }
}

export default (Store) => {
  Store.prototype.openInitSessions = function () {
    const { store } = window
    const onStartSessions = store.config.onStartSessions

    // If onStartSessions is a string, it's a workspace ID
    if (typeof onStartSessions === 'string' && onStartSessions) {
      store.loadWorkspace(onStartSessions)
    } else {
      // Otherwise, it's an array of bookmark IDs
      const arr = Array.isArray(onStartSessions) ? onStartSessions : []
      for (const s of arr) {
        store.onSelectBookmark(s)
      }
      if (!arr.length && store.config.initDefaultTabOnStart) {
        store.initFirstTab()
      }
    }

    store.confirmLoad()
    const { initTime, loadTime } = window.pre.runSync('getLoadTime')
    if (loadTime) {
      store.loadTime = loadTime
    } else {
      const finishLoadTime = Date.now()
      store.loadTime = finishLoadTime - initTime
      window.pre.runSync('setLoadTime', store.loadTime)
    }
  }
  Store.prototype.fetchSshConfigItems = async function () {
    const arr = await window.pre.runGlobalAsync('loadSshConfig')
      .catch((err) => {
        console.log('fetchSshConfigItems error', err)
        return []
      })
    window.store.sshConfigs = arr
    return arr
  }
  Store.prototype.confirmLoad = function () {
    window.store.configLoaded = true
  }
  Store.prototype.initApp = async function () {
    const { store } = window
    const globs = window.et.globs || await window.pre.runGlobalAsync('init')
    window.langMap = globs.langMap
    store.installSrc = globs.installSrc
    store.appPath = globs.appPath
    store.exePath = globs.exePath
    store.isPortable = globs.isPortable
    store._config = globs.config
    window.et.langs = globs.langs
    store.zoom(store.config.zoom, false, true)
    await initWsCommon()
  }
  Store.prototype.initData = async function () {
    const { store } = window
    store.initLoadingData = true
    try {
      await store.initApp()
      const ext = {}
      const all = dbNames.map(async name => {
        const data = await fetchInitData(name)
        return {
          name,
          data
        }
      })
      await Promise.all(all)
        .then(arr => {
          for (const { name, data } of arr) {
            const dt = JSON.parse(data || '[]')
            refsStatic.add('oldState-' + name, dt)
            if (name === 'bookmarks') {
              ext.bookmarksMap = new Map(
                dt.map(d => [d.id, d])
              )
            }
            ext[name] = dt
          }
        })
      ext.lastDataUpdateTime = await getData('lastDataUpdateTime') || 0
      ext.initLoadingData = false
      Object.assign(store, ext)
      store.loadFontList()
      store.fetchItermThemes()
      store.openInitSessions()
      store.fetchSshConfigItems()
      store.initCommandLine().catch(store.onError)
      initWatch(store)
      setTimeout(
        () => {
          store.fixProfiles()
          store.fixBookmarkGroups()
        },
        1000
      )
      setTimeout(
        () => {
          store.autoSyncReady = true
        },
        2000
      )
      if (store.config.checkUpdateOnStart) {
        store.onCheckUpdate(false)
      }
      store.startAutoRunWidgets().catch(err => {
        console.error('Failed to start autorun widgets:', err)
      })
    } catch (err) {
      store.initLoadingData = false
      store.onError(err)
    }
  }
  Store.prototype.initCommandLine = async function () {
    const opts = await window.pre.runGlobalAsync('initCommandLine')
    addTabFromCommandLine(window.store, opts)
  }
  Store.prototype.addTabFromCommandLine = (event, opts) => {
    addTabFromCommandLine(window.store, opts)
  }
  Store.prototype.checkPendingDeepLink = async function () {
    const pending = await window.pre.runGlobalAsync('getPendingDeepLink')
    if (pending) {
      window.store.ipcOpenTab(pending)
    }
  }
  Store.prototype.parseQuickConnect = function (url) {
    return parseQuickConnect(url)
  }
}
