/* eslint-disable @typescript-eslint/naming-convention */

import { IContextParam, ICompleteCloudbaseContext, ISCFContext } from '../../types'
import { ERROR } from '../const/code'
import { E } from './utils'
import { checkIsInScf } from './cloudplatform'

/**
 * parseContext 解析并校验 Context 格式
 * @param context {IContextParam}
 * @returns
 */
export function parseContext(context: IContextParam): ISCFContext {
  if (typeof context !== 'object') {
    throw E({ ...ERROR.INVALID_CONTEXT, message: 'context 必须为对象类型' })
  }

  const parseResult: any = {}

  const {
    memory_limit_in_mb,
    time_limit_in_ms,
    request_id,
    function_version,
    namespace,
    function_name,

    environ,
    environment
  } = context

  try {
    parseResult.memoryLimitInMb = memory_limit_in_mb
    parseResult.timeLimitIns = time_limit_in_ms
    parseResult.requestId = request_id
    parseResult.functionVersion = function_version
    parseResult.namespace = namespace
    parseResult.functionName = function_name

    // 存在 environment 为新架构上新字段，可直接JSON.parse字符串，否则为老架构，需特殊处理
    if (environment) {
      parseResult.environment = JSON.parse(environment)
    } else {
      // TODO: 考虑移除老架构的兼容逻辑
      // 老架构上存在bug，无法识别value含特殊字符(若允许特殊字符，影响解析，这里特殊处理)
      const parseEnviron = environ.split(';')
      const parseEnvironObj = {}

      // eslint-disable-next-line @typescript-eslint/no-for-in-array
      for (const i in parseEnviron) {
        // value含分号影响切割，未找到=均忽略
        if (parseEnviron[i].includes('=')) {
          const equalIndex = parseEnviron[i].indexOf('=')
          const key = parseEnviron[i].slice(0, equalIndex)
          let value: any = parseEnviron[i].slice(equalIndex + 1)

          // value 含, 为数组
          if (value.indexOf(',') >= 0) {
            value = value.split(',')
          }
          parseEnvironObj[key] = value
        }
      }

      parseResult.environ = parseEnvironObj
    }
  } catch (err) {
    throw E({ ...ERROR.INVALID_CONTEXT })
  }

  return parseResult
}

/**
 * getCloudbaseContext
 * 获取当前函数内的所有环境变量(作为获取变量的统一方法，取值来源 process.env 和 context)
 */
export function getCloudbaseContext(context?: IContextParam): ICompleteCloudbaseContext {
  // console.log('context', context)
  if (checkIsInScf()) {
    // 云函数环境下，应该包含以下环境变量，如果没有，后续逻辑可能会有问题
    if (!process.env.TENCENTCLOUD_REGION) {
      console.error('[TCB][ERROR] missing `TENCENTCLOUD_REGION` environment')
    }
    if (!process.env.SCF_NAMESPACE) {
      console.error('[TCB][ERROR] missing `SCF_NAMESPACE` environment')
    }
  }

  const {
    TRIGGER_SRC,
    _SCF_TCB_LOG,
    SCF_NAMESPACE,
    TENCENTCLOUD_RUNENV,
    TENCENTCLOUD_SECRETID,
    TENCENTCLOUD_SECRETKEY,
    TENCENTCLOUD_SESSIONTOKEN,
    WX_CONTEXT_KEYS,
    WX_TRIGGER_API_TOKEN_V0,
    WX_CLIENTIP,
    WX_CLIENTIPV6,
    TCB_CONTEXT_KEYS,
    TCB_CONTEXT_CNFG,
    LOGINTYPE
  } = process.env

  const envFromProcessEnv = {
    TRIGGER_SRC,
    _SCF_TCB_LOG,
    SCF_NAMESPACE,
    TENCENTCLOUD_RUNENV,
    TENCENTCLOUD_SECRETID,
    TENCENTCLOUD_SECRETKEY,
    TENCENTCLOUD_SESSIONTOKEN,
    WX_CONTEXT_KEYS,
    WX_TRIGGER_API_TOKEN_V0,
    WX_CLIENTIP,
    WX_CLIENTIPV6,
    TCB_CONTEXT_KEYS,
    TCB_CONTEXT_CNFG,
    LOGINTYPE
  }

  let envFromContext: any = {}
  if (context) {
    const { environment, environ } = parseContext(context)
    envFromContext = environment || environ || {}
  }

  // 从TCB_CONTEXT_KEYS 和 WX_CONTEXT_KEYS中解析环境变量 取值优先级为 context > process.env
  const tcbContextKeys = envFromContext.TCB_CONTEXT_KEYS || TCB_CONTEXT_KEYS
  const wxContextKeys = envFromContext.WX_CONTEXT_KEYS || WX_CONTEXT_KEYS

  if (tcbContextKeys) {
    try {
      const tcbKeysList = tcbContextKeys.split(',')
      for (const item of tcbKeysList) {
        envFromProcessEnv[item] = envFromContext[item] || process.env[item]
      }
    } catch (e) { }
  }

  if (wxContextKeys) {
    try {
      const wxKeysList = wxContextKeys.split(',')
      for (const item of wxKeysList) {
        envFromProcessEnv[item] = envFromContext[item] || process.env[item]
      }
    } catch (e) { }
  }

  const allContext = { ...envFromProcessEnv, ...envFromContext }

  const finalContext: any = {}
  for (const key in allContext) {
    if (allContext[key] !== undefined) {
      finalContext[key] = allContext[key]
    }
  }

  return finalContext
}

export function getTcbContextConfig(): any {
  try {
    const { TCB_CONTEXT_CNFG } = getCloudbaseContext()

    if (TCB_CONTEXT_CNFG) {
      // 检查约定环境变量字段是否存在
      return JSON.parse(TCB_CONTEXT_CNFG)
    }
    return {}
  } catch (e) {
    /* istanbul ignore next */
    console.error('[TCB][ERROR] parse context error: ', e)
    /* istanbul ignore next */
    return {}
  }
}

export function getServerInjectUrl(): string {
  const tcbContextConfig = getTcbContextConfig()
  return tcbContextConfig.URL || ''
}
