import fs from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import DevSidecar from '@docmirror/dev-sidecar'
import { app, ipcMain, shell } from 'electron'
import lodash from 'lodash'
import jsonApi from '@docmirror/mitmproxy/src/json.js'
import { createRequire } from 'node:module'
const require = createRequire(import.meta.url)
const pk = require('../../../package.json')
import coreDefaultConfig from '@docmirror/dev-sidecar/src/config/index.js'
import configLoader from '@docmirror/dev-sidecar/src/config/local-config-loader.js'
import log from '../../utils/util.log.gui.js'
import dateUtil from '@docmirror/dev-sidecar/src/utils/util.date.js'

const { configFromFiles } = coreDefaultConfig

const __dirname = path.dirname(fileURLToPath(import.meta.url))
const mitmproxyPath = path.join(__dirname, '../mitmproxy.js')
process.env.DS_EXTRA_PATH = path.join(app.getAppPath(), 'extra')
let currentWin

const getDefaultConfigBasePath = function () {
  return DevSidecar.api.config.get().server.setting.userBasePath
}

function getMetaInfo (config, fallbackId) {
  const metaInfo = lodash.get(config, 'app.metaInfo') || lodash.get(config, 'metaInfo') || {}
  return {
    id: metaInfo.id || fallbackId,
    version: metaInfo.version || 0,
    updateLog: metaInfo.updateLog || '',
    showLabel: metaInfo.showLabel !== false && metaInfo.showLabel !== 'false', // 个人配置可以使用此配置隐藏footer中的 '当前配置：' 字样
  }
}

function emitConfigChanged () {
  if (currentWin) {
    currentWin.webContents.send('config.changed')
  }
}

const localApi = {
  /**
   * 返回所有api列表，供vue来ipc调用
   * @returns {[]} api列表
   */
  getApiList () {
    const core = lodash.cloneDeep(DevSidecar.api)
    const local = lodash.cloneDeep(localApi)
    lodash.merge(core, local)
    const list = []
    _deepFindFunction(list, core, '')
    // log.info('api list:', list)
    return list
  },
  info: {
    get () {
      const runtimeConfig = DevSidecar.api.config.get()
      const remoteConfig = lodash.get(runtimeConfig, 'app.remoteConfig') || {}

      const internal = getMetaInfo(coreDefaultConfig, '')
      const sharedRemote = getMetaInfo(configLoader.getRemoteConfig(), '')
      const personalRemote = getMetaInfo(configLoader.getRemoteConfig('_personal'), '')

      return {
        version: pk.version,
        configProfiles: {
          internal,
          sharedRemote: {
            ...sharedRemote,
            url: remoteConfig.url || '',
            enabled: remoteConfig.enabled === true && Boolean(remoteConfig.url),
          },
          personalRemote: {
            ...personalRemote,
            url: remoteConfig.personalUrl || '',
            enabled: remoteConfig.enabled === true && Boolean(remoteConfig.personalUrl),
          },
        },
      }
    },
    getConfigDir () {
      return getDefaultConfigBasePath()
    },
    getLogDir () {
      return configFromFiles.app.logFileSavePath || path.join(getDefaultConfigBasePath(), '/logs/')
    },
    getSystemPlatform (throwIfUnknown = false) {
      return DevSidecar.api.shell.getSystemPlatform(throwIfUnknown)
    },
  },
  /**
   * 软件设置
   */
  setting: {
    load () {
      const settingPath = _getSettingsPath()
      let setting = {}
      if (fs.existsSync(settingPath)) {
        const file = fs.readFileSync(settingPath)
        try {
          setting = jsonApi.parse(file.toString())
          log.info('读取 setting.json 成功:', settingPath)
        } catch (e) {
          log.error('读取 setting.json 失败:', settingPath, ', error:', e)
        }
        if (setting == null) {
          setting = {}
        }
      }
      if (setting.overwall == null) {
        setting.overwall = false
      }

      if (setting.installTime == null) {
        // 设置安装时间
        setting.installTime = dateUtil.now()

        // 初始化 rootCa.setuped
        if (setting.rootCa == null) {
          setting.rootCa = {
            setuped: false,
            desc: '根证书未安装',
          }
        }

        // 保存 setting.json
        localApi.setting.save(setting)
      }
      return setting
    },
    save (setting = {}) {
      const settingPath = _getSettingsPath()
      try {
        fs.writeFileSync(settingPath, jsonApi.stringify(setting))
        log.info('保存 setting.json 配置文件成功:', settingPath)
      } catch (e) {
        log.error('保存 setting.json 配置文件失败:', settingPath, ', error:', e)
      }
    },
  },
  config: {
    get () {
      return DevSidecar.api.config.get()
    },
    save (newConfig) {
      const result = DevSidecar.api.config.save(newConfig)
      emitConfigChanged()
      return result
    },
    reload () {
      const result = DevSidecar.api.config.reload()
      emitConfigChanged()
      return result
    },
    update (partConfig) {
      const result = DevSidecar.api.config.update(partConfig)
      emitConfigChanged()
      return result
    },
    resetDefault (key) {
      const result = DevSidecar.api.config.resetDefault(key)
      emitConfigChanged()
      return result
    },
    async removeUserConfig () {
      const result = await DevSidecar.api.config.removeUserConfig()
      emitConfigChanged()
      return result
    },
  },
  /**
   * 启动所有
   * @returns {Promise<void>}
   */
  startup () {
    return DevSidecar.api.startup({ mitmproxyPath })
  },
  server: {
    /**
     * 启动代理服务
     * @returns {Promise<{port: *}>}
     */
    start () {
      return DevSidecar.api.server.start({ mitmproxyPath })
    },
    /**
     * 重启代理服务
     * @returns {Promise<void>}
     */
    restart () {
      return DevSidecar.api.server.restart({ mitmproxyPath })
    },
  },
  shell: {
    /**
     * 使用 Electron 主进程原生 API 打开文件（避免 cmd.exe start 权限问题）
     */
    openPath (filePath) {
      return shell.openPath(path.resolve(filePath))
    },
  },
}

function _deepFindFunction (list, parent, parentKey) {
  for (const key in parent) {
    const item = parent[key]
    if (item instanceof Function) {
      list.push(parentKey + key)
    } else if (item instanceof Object) {
      _deepFindFunction(list, item, `${parentKey + key}.`)
    }
  }
}

function _getSettingsPath () {
  const dir = getDefaultConfigBasePath()
  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir)
  } else {
    // 兼容1.7.3及以下版本的配置文件处理逻辑
    const newFilePath = path.join(dir, '/setting.json')
    const oldFilePath = path.join(dir, '/setting.json5')
    if (!fs.existsSync(newFilePath) && fs.existsSync(oldFilePath)) {
      return oldFilePath // 如果新文件不存在，且旧文件存在，则返回旧文件路径
    }
    return newFilePath
  }
  return path.join(dir, '/setting.json')
}

function invoke (api, param) {
  let target = lodash.get(localApi, api)
  if (target == null) {
    target = lodash.get(DevSidecar.api, api)
  }
  if (target == null) {
    log.info('找不到此接口方法：', api)
  }
  const ret = target(param)
  // log.info('api:', api, 'ret:', ret)
  return ret
}

async function doStart () {
  // 开启自动下载远程配置
  await DevSidecar.api.config.startAutoDownloadRemoteConfig()
  emitConfigChanged()
  // 启动所有
  localApi.startup()
}

export default {
  install ({ win }) {
    currentWin = win
    // 接收view的方法调用
    ipcMain.handle('apiInvoke', async (event, args) => {
      const api = args[0]
      let param
      if (args.length >= 2) {
        param = args[1]
      }
      return invoke(api, param)
    })
    // 注册从core里来的事件，并转发给view
    DevSidecar.api.event.register('status', (event) => {
      log.info('bridge on status, event:', event)
      if (win) {
        win.webContents.send('status', { ...event })
      }
    })
    DevSidecar.api.event.register('error', (event) => {
      log.error('bridge on error, event:', event)
      if (win) {
        win.webContents.send('error.core', event)
      }
    })
    DevSidecar.api.event.register('speed', (event) => {
      if (win) {
        win.webContents.send('speed', event)
      }
    })

    // 合并用户配置
    DevSidecar.api.config.reload()
    doStart()
  },
  devSidecar: DevSidecar,
  invoke,
}
