/* eslint-disable import/no-mutable-exports */
/* eslint-disable @typescript-eslint/naming-convention */
/* eslint-disable no-restricted-syntax */
import { ERROR, SECRET_TYPE } from './constants'
import { checkIsInScf, getEnv } from './utils'
import type { IContextParam, ICompleteCloudbaseContext } from './types'
import { ICloudbaseConfig } from '@cloudbase/types'

/**
 * 解析并校验云函数入口的 Context 参数
 * 将下划线命名的字段转为驼峰格式，并解析环境变量
 *
 * @param context - 云函数入口传入的 context 对象
 * @returns 解析后的上下文对象，包含 environment（新架构）或 environ（老架构）
 * @throws INVALID_CONTEXT - context 不是对象或解析失败时
 */
export function parseContext(context: IContextParam) {
  if (typeof context !== 'object') {
    throw { ...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

    if (environment) {
      // 新架构：environment 为 JSON 字符串，直接解析
      parseResult.environment = JSON.parse(environment)
    } else {
      // TODO: 考虑移除老架构的兼容逻辑
      // 老架构：environ 为分号分隔的 key=value 字符串
      // 存在 bug：value 含特殊字符时可能影响解析
      const parseEnviron: any = environ?.split(';')
      const parseEnvironObj: any = {}

      // eslint-disable-next-line @typescript-eslint/no-for-in-array
      for (const i in parseEnviron) {
        if (parseEnviron[i].includes('=')) {
          // 只按第一个 = 切割，保留 value 中的 =
          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: any) {
    throw { ...ERROR.INVALID_CONTEXT }
  }

  return parseResult
}

/**
 * 获取当前云函数内的所有环境变量
 * 统一从 process.env 和 context 两个来源合并取值
 *
 * 取值优先级：context > process.env
 * 通过 TCB_CONTEXT_KEYS / WX_CONTEXT_KEYS 动态扩展需要读取的环境变量列表
 *
 * @param context - 可选，云函数入口的 context 参数
 * @returns 合并后的完整环境变量上下文
 */
export const getCloudbaseContext = (context?: IContextParam): ICompleteCloudbaseContext => {
  // 云函数环境下校验必要环境变量
  if (checkIsInScf()) {
    if (!getEnv('TENCENTCLOUD_REGION')) {
      console.error('[TCB][ERROR] missing `TENCENTCLOUD_REGION` environment')
    }
    if (!getEnv('SCF_NAMESPACE')) {
      console.error('[TCB][ERROR] missing `SCF_NAMESPACE` environment')
    }
  }

  // 第一步：从 process.env 读取基础环境变量
  const envObj = getEnv()
  const envFromProcessEnv: any = {
    TRIGGER_SRC: envObj.TRIGGER_SRC,
    _SCF_TCB_LOG: envObj._SCF_TCB_LOG,
    SCF_NAMESPACE: envObj.SCF_NAMESPACE,
    TENCENTCLOUD_RUNENV: envObj.TENCENTCLOUD_RUNENV,
    TENCENTCLOUD_SECRETID: envObj.TENCENTCLOUD_SECRETID,
    TENCENTCLOUD_SECRETKEY: envObj.TENCENTCLOUD_SECRETKEY,
    TENCENTCLOUD_SESSIONTOKEN: envObj.TENCENTCLOUD_SESSIONTOKEN,
    WX_CONTEXT_KEYS: envObj.WX_CONTEXT_KEYS,
    WX_TRIGGER_API_TOKEN_V0: envObj.WX_TRIGGER_API_TOKEN_V0,
    WX_CLIENTIP: envObj.WX_CLIENTIP,
    WX_CLIENTIPV6: envObj.WX_CLIENTIPV6,
    TCB_CONTEXT_KEYS: envObj.TCB_CONTEXT_KEYS,
    TCB_CONTEXT_CNFG: envObj.TCB_CONTEXT_CNFG,
    LOGINTYPE: envObj.LOGINTYPE,
  }

  // 第二步：从 context 中解析环境变量
  let envFromContext: any = {}
  if (context) {
    const { environment, environ } = parseContext(context)
    envFromContext = environment || environ || {}
  }

  // 第三步：根据 CONTEXT_KEYS 动态扩展变量列表（优先取 context 中的值）
  const tcbContextKeys = envFromContext.TCB_CONTEXT_KEYS || envObj.TCB_CONTEXT_KEYS
  const wxContextKeys = envFromContext.WX_CONTEXT_KEYS || envObj.WX_CONTEXT_KEYS

  if (tcbContextKeys) {
    try {
      const tcbKeysList = tcbContextKeys.split(',')
      for (const item of tcbKeysList) {
        envFromProcessEnv[item] = envFromContext[item] || getEnv(item)
      }
    } catch (_e) {
      //
    }
  }

  if (wxContextKeys) {
    try {
      const wxKeysList = wxContextKeys.split(',')
      for (const item of wxKeysList) {
        envFromProcessEnv[item] = envFromContext[item] || getEnv(item)
      }
    } catch (_e) {
      //
    }
  }

  // 第四步：合并所有来源，context 的值覆盖 process.env，过滤 undefined
  const allContext = { ...envFromProcessEnv, ...envFromContext }

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

  return finalContext
}

/** 缓存 extendedContext，供其他模块读取（如 tool.ts 中获取 userId） */
export let INIT_CONFIG: ICloudbaseConfig = {} as unknown as ICloudbaseConfig

/**
 * 从环境变量中获取腾讯云临时密钥信息
 * 用于 API 请求签名
 */
export const getSecretInfo = (config?: ICloudbaseConfig) => {
  INIT_CONFIG = JSON.parse(JSON.stringify(config || {}))

  const { TCB_ENV, SCF_NAMESPACE } = getCloudbaseContext()

  let env = config?.env || TCB_ENV || SCF_NAMESPACE || ''
  const defaultInfo = {
    env,
    secretId: '',
    secretKey: '',
    sessionToken: '',
    accessKey: '',
    secretType: '',
  }

  if (config?.accessKey) {
    return defaultInfo
  }

  if (config?.auth?.secretId && config?.auth?.secretKey) {
    return {
      ...defaultInfo,
      secretId: config.auth.secretId,
      secretKey: config.auth.secretKey,
      secretType: SECRET_TYPE.SECRET,
    }
  }

  const secretEnv = getEnv()
  const { TENCENTCLOUD_SECRETID } = secretEnv
  const { TENCENTCLOUD_SECRETKEY } = secretEnv
  const { TENCENTCLOUD_SESSIONTOKEN } = secretEnv
  const { CLOUDBASE_APIKEY } = secretEnv

  if (CLOUDBASE_APIKEY) {
    return {
      ...defaultInfo,
      accessKey: CLOUDBASE_APIKEY,
    }
  }

  if (TENCENTCLOUD_SECRETID && TENCENTCLOUD_SECRETKEY) {
    return {
      ...defaultInfo,
      secretId: TENCENTCLOUD_SECRETID,
      secretKey: TENCENTCLOUD_SECRETKEY,
      sessionToken: TENCENTCLOUD_SESSIONTOKEN || '',
      secretType: SECRET_TYPE.SESSION_SECRET,
    }
  }

  if (config?.context?.extendedContext) {
    const { extendedContext } = config.context
    if (!env) {
      env = extendedContext.envId || ''
    }

    return {
      ...defaultInfo,
      secretId: extendedContext?.tmpSecret?.secretId || '',
      secretKey: extendedContext?.tmpSecret?.secretKey || '',
      sessionToken: extendedContext?.tmpSecret?.token || '',
    }
  }

  return { ...defaultInfo }
}
