import fs from 'fs'

import { Db } from '@cloudbase/database'
import { OrmClient, OrmRawQueryClient } from '@cloudbase/wx-cloud-client-sdk'
import { AI } from '@cloudbase/ai'
import { IReqOpts } from './internal'

type IKeyValue = Record<string, any>

type IHeaderOpts = Record<string, string>

interface ICommonParam {
  action: string
  envName?: string | symbol
  timestamp?: number
  eventId?: string
  wxCloudApiToken?: string
  tcb_sessionToken?: string
  authorization?: string
  sessionToken?: string
  sdk_version?: string
}

/* eslint-disable-next-line */
interface ICustomParam extends ICommonParam {
  [propName: string]: any
}

/* ********************************** context ********************************** */

export interface IContextParam {
  memory_limit_in_mb: number
  time_limit_in_ms: number
  request_id: string
  environ?: string
  environment?: string
  function_version: string
  function_name: string
  namespace: string
}

export interface ISCFContext {
  memoryLimitInMb: number
  timeLimitIns: number
  requestId: string
  functionVersion: string
  namespace: string
  functionName: string
  environ?: IEnvironmentInfo
  environment?: IEnvironmentInfo
}

export interface IEnvironmentInfo {
  WX_CLIENTIP?: string
  WX_CLIENTIPV6?: string
  WX_APPID?: string
  WX_OPENID?: string
  WX_API_TOKEN?: string
  WX_CONTEXT_KEYS?: string[]
  TCB_ENV: string
  TCB_SEQID: string
  TRIGGER_SRC: string
  TCB_SESSIONTOKEN?: string
  TCB_SOURCE?: string
  TCB_CONTEXT_KEYS: string[]
  TENCENTCLOUD_SECRETID: string
  TENCENTCLOUD_SECRETKEY: string
  TENCENTCLOUD_SESSIONTOKEN: string
  SCF_NAMESPACE: string
}

// 最完整的环境变量类型汇总
export interface ICompleteCloudbaseContext {
  _SCF_TCB_LOG?: string
  LOGINTYPE?: string
  QQ_APPID?: string
  QQ_OPENID?: string
  SCF_NAMESPACE: string
  TCB_CONTEXT_CNFG?: string
  TCB_CONTEXT_KEYS: string[]
  TCB_CUSTOM_USER_ID?: string
  TCB_ENV: string
  TCB_HTTP_CONTEXT?: string
  TCB_ISANONYMOUS_USER?: string
  TCB_ROUTE_KEY?: string
  TCB_SEQID: string
  TCB_SESSIONTOKEN?: string
  TCB_SOURCE_IP?: string
  TCB_SOURCE?: string
  TCB_TRACELOG?: string
  TCB_UUID?: string
  TENCENTCLOUD_RUNENV: string
  TENCENTCLOUD_SECRETID: string
  TENCENTCLOUD_SECRETKEY: string
  TENCENTCLOUD_SESSIONTOKEN: string
  TRIGGER_SRC: string
  WX_API_TOKEN?: string
  WX_APPID?: string
  WX_CLIENTIP?: string
  WX_CLIENTIPV6?: string
  WX_CLOUDBASE_ACCESSTOKEN?: string
  WX_CONTEXT_KEYS: string[]
  WX_OPENID?: string
  WX_TRIGGER_API_TOKEN_V0?: string
  WX_UNIONID?: string
}

// 上报数据结构
export interface IAnalyticsDataItem {
  analytics_scene: string // 上报场景  如电商 mall，游戏 game
  analytics_data: { // 场景模板内容，以电商模板举例
    openid: string // 必填  用户openid
    wechat_mini_program_appid: string // 必填小程序appid
    action_time: number // 必填  行为发生时，客户端的时间点，单位s
    action_type: string // 必填 行为类型 如 访问 visit_store，分享 share，加入购物车 add_to_cart等
    click_id?: string // 非必填  广告平台会在URL增加click_id
    action_param?: { // 非必填
      value?: number // 非必填 行为所带的参数，转化行为价值（例如金额）
      leads_type?: string // 非必填 行为来源，目前支持PHONE（电话直呼），RESERVE（表单预约）
    }
    product_param?: { // 非必填
      product_yun_type?: string // 非必填  商品 goods ，优惠券 coupon, 搜索词 search_term
      product_yun_id?: string // 非必填 商品id
      product_yun_category?: string // 非必填 商品类目 自定义
      product_yun_keywords?: string // 非必填 商品关键词
      product_yun_price?: number // 非必填 商品原价
      product_yun_value?: number // 非必填 商品成交价
      product_yun_name?: string // 非必填 商品名
      product_yun_id_ad?: string // 非必填 广告商品库中商品id
      product_yun_category_ad?: string // 非必填 广告商品库中商品类目
    }
  }
}

// report 接口传参结构
export interface IReportData {
  report_type: string // 上报场景  如电商 mall，游戏 game
  report_data: {
    action_time?: number // 非必填  行为发生时，客户端的时间点，单位s
    action_type: string // 必填 行为类型 如 访问 visit_store，分享 share，加入购物车 add_to_cart等
    click_id?: string // 非必填  广告平台会在URL增加click_id
    action_param?: { // 非必填
      value?: number // 非必填 行为所带的参数，转化行为价值（例如金额）
      leads_type?: string // 非必填 行为来源，目前支持PHONE（电话直呼），RESERVE（表单预约）
    }
    product_param?: { // 非必填
      product_yun_type?: string // 非必填  商品 goods ，优惠券 coupon, 搜索词 search_term
      product_yun_id?: string // 非必填 商品id
      product_yun_category?: string // 非必填 商品类目 自定义
      product_yun_keywords?: string // 非必填 商品关键词
      product_yun_price?: number // 非必填 商品原价
      product_yun_value?: number // 非必填 商品成交价
      product_yun_name?: string // 非必填 商品名
      product_yun_id_ad?: string // 非必填 广告商品库中商品id
      product_yun_category_ad?: string // 非必填 广告商品库中商品类目
    }
  }
}

/* ********************************** config ********************************** */

export interface ICredentialsInfo {
  private_key_id: string
  private_key: string
  env_id: string
}

interface ICrossAccountInfo {
  /**
   * 帐号凭证
   */
  credential: {
    secretId: string
    secretKey: string
    token: string
  }
  /**
   * 认证信息加密
   */
  authorization: {
    mpToken?: string
  }
}

export interface ICloudBaseConfig extends IKeyValue {
  env?: string | symbol
  debug?: boolean
  timeout?: number
  keepalive?: boolean
  protocol?: 'http' | 'https'
  secretId?: string
  secretKey?: string
  sessionToken?: string
  serviceUrl?: string
  headers?: IHeaderOpts
  proxy?: string
  version?: string
  credentials?: ICredentialsInfo
  region?: string
  accessKey?: string

  // @cloudbase/functions-framework 函数上下文，只要求部分字段
  context?: Readonly<{
    eventID: string
    extendedContext?: {
      /* eslint-disable no-multi-spaces */
      envId: string           // 环境 ID
      // uin: string             // 请求的 UIN
      source: string          // 请求来源，如 wx
      accessToken?: string    // 调用请求时的 AccessToken
      userId?: string         // 请求的用户 ID
      tmpSecret?: {           // 临时凭证
        secretId: string      // secretId
        secretKey: string     // secretKey
        token: string         // token
      }
      /* eslint-enable no-multi-spaces */
    }
  }>

  /**
   * 获取跨帐号调用信息
   */
  getCrossAccountInfo?: () => Promise<ICrossAccountInfo>
}

export interface IRetryOptions {
  retries?: number
  factor?: number
  minTimeout?: number
  maxTimeout?: number
  randomize?: boolean
  timeouts?: number[]
  timeoutOps?: {
    timeout: number
    cb: function
  }
}

export interface ICustomReqOpts {
  timeout?: number
  retryOptions?: IRetryOptions
  /**
     * 获取跨帐号调用信息
     */
  getCrossAccountInfo?: () => Promise<ICrossAccountInfo>
  type?: IReqOpts['type']
}

export interface IBaseResult {
  requestId?: string
}

/* ********************************** database ********************************** */

export interface ICloudBaseDBConfig extends ICloudBaseConfig {
  /**
   * 数据库实例
   */
  instance?: string
  /**
   * 数据库名称
   */
  database?: string
}

/* ********************************** storage ********************************** */

export interface IUploadFileOptions {
  // 云端存储地址
  cloudPath: string
  // 文件内容 Buffer 或 文件可读流
  fileContent: Buffer | fs.ReadStream
}

export interface IUploadFileResult extends IBaseResult {
  fileID: string
}

export interface IDownloadFileOptions {
  fileID: string
  urlType?: 'COS_URL'
  tempFilePath?: string
}

export interface IDownloadFileResult {
  fileContent: string | Buffer | undefined
  message: string
}

export interface ICopyFileOptions {
  fileList: Array<{
    srcPath: string
    dstPath: string
    overwrite?: boolean
    removeOriginal?: boolean
  }>
}

export interface ICopyFileResult extends IBaseResult {
  fileList: Array<{
    fileId?: string
    code?: string
    message?: string
  }>
}

export interface IDeleteFileOptions {
  fileList: string[]
}

export interface IDeleteFileResult extends IBaseResult {
  fileList: Array<{
    code: string
    fileID: string
  }>
}

export interface IGetFileUrlOptions {
  fileList: Array<string | {
    fileID: string
    maxAge?: number
    urlType?: 'COS_URL'
  }>
}

export interface IFileUrlInfo {
  code: string
  fileID: string
  tempFileURL: string
}

export interface IGetFileUrlResult extends IBaseResult {
  fileList: IFileUrlInfo[]
}

export interface IGetFileInfoOptions {
  fileList: Array<string | {
    fileID: string
    maxAge?: number
    urlType?: 'COS_URL'
  }>
}

export interface IFileInfo extends IFileUrlInfo {
  cloudId?: string
  fileName?: string
  contentType?: string
  mime?: string
  size?: number
}

export interface IGetFileInfoResult extends IBaseResult {
  fileList: IFileInfo[]
}

export interface IGetUploadMetadataOptions {
  cloudPath: string
}

export interface IGetUploadMetadataResult extends IBaseResult {
  data: {
    url: string
    token: string
    authorization: string
    fileId: string
    cosFileId: string
    download_url: string
  }
}

export interface IGetFileAuthorityOptions {
  fileList: Array<{
    type: string
    path: string
  }>
}

export interface IGetFileAuthorityResult {
  data: Array<{
    path: string
    cosFileId: string
    read: boolean
  }>
}

/* ********************************** function ********************************** */

export interface ICallFunctionOptions<T> {
  name: string // 函数名
  data: T
  qualifier?: string
  // async?: boolean

  // Used for 云函数2.0 CallContainer
  type?: 'cloudrun'
  method?: 'POST'
  path?: string
  header?: IHeaderOpts & {
    // 'X-WX-SERVICE': string
  }
}

export interface CallFunctionResult<T> {
  result: T
  requestId: string
}

// 接口定义参考 wx.Cloud.callContainer 尽可能保持一致
// Cloud.callContainer(options: Object): Promise<Object>
// https://developers.weixin.qq.com/miniprogram/dev/wxcloudservice/wxcloud/reference-sdk-api/container/Cloud.callContainer.html
export interface ICallContainerOptions<T> {
  name: string
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS'
  path?: string
  header?: IHeaderOpts & {
    // 'X-WX-SERVICE': string
  }
  data?: T

  // timeout?: number
  // dataType?: string
  // responseType?: string
}

export interface CallContainerResult<T> {
  requestId: string
  statusCode: number
  header?: IHeaderOpts
  data?: T
}

/* ********************************** wx ********************************** */

interface ICallWxOpenApiOptions {
  apiName: string
  apiOptions?: any
  cgiName?: string
  requestData: any
}

export interface ICallWxOpenApiResult extends IBaseResult {
  result?: any
}

/* ********************************** auth ********************************** */

export interface IGetAuthContextResult {
  uid: string
  loginType: string
  appId?: string
  openId?: string
}

export interface IGetUserInfoResult {
  openId: string
  appId: string
  uid: string
  customUserId: string
  isAnonymous: boolean
}

export interface IGetEndUserInfoResult {
  userInfo?: {
    openId: string
    appId: string
    uid: string
    customUserId: string
    isAnonymous: boolean
  }
  requestId?: string
}

export interface IUserInfoQuery {
  platform?: string
  platformId?: string
  uid?: string
}

export interface ICreateTicketOpts {
  refresh?: number
  expire?: number
}

export declare class Auth {
  getAuthContext(context: IContextParam): Promise<IGetAuthContextResult>
  getClientIP(): string
  getUserInfo(): IGetUserInfoResult
  getEndUserInfo(uid?: string, opts?: ICustomReqOpts): Promise<any> | IGetEndUserInfoResult
  queryUserInfo(query: IUserInfoQuery, opts?: ICustomReqOpts): Promise<any>
  createTicket: (uid: string, options?: ICreateTicketOpts) => string
}

/* ********************************** extension ********************************** */

export declare class Extension {
  public name: string

  invoke<T>(options: T, cloudbase: CloudBase)
}

/* ********************************** CloudBase ********************************** */

declare class Logger {
  log(logMsg: any): void
  info(logMsg: any): void
  error(logMsg: any): void
  warn(logMsg: any): void
}

export declare class CloudBase {
  static parseContext(context: IContextParam): ISCFContext
  static getCloudbaseContext(context?: IContextParam): ICompleteCloudbaseContext

  constructor(config?: ICloudBaseConfig)

  /**
   * init - 初始化 CloudBase 实例
   */
  init(config?: ICloudBaseConfig): void

  /**
   * logger - 获取 高级日志 Logger 实例
   */
  logger(): Logger

  /**
   * auth - 获取 Auth 实例
   */
  auth(): Auth

  /**
   * 数据模型
   */
  models: OrmClient & OrmRawQueryClient

  /**
   * database - 获取云数据库实例
   */
  database(dbConfig: ICloudBaseDBConfig = {}): Db

  /**
   * callFunction - 调用云函数
   */
  callFunction<ParaT, ResultT>(callFunctionOptions: ICallFunctionOptions<ParaT>, opts?: ICustomReqOpts): Promise<CallFunctionResult<ResultT>>

  /**
   * callContainer - 调用云托管
   */
  callContainer<ParaT, ResultT>(callContainerOptions: ICallContainerOptions<ParaT>, opts?: ICustomReqOpts): Promise<CallContainerResult<ResultT>>

  /**
   * uploadFile - 上传文件
   */
  uploadFile({ cloudPath, fileContent }: IUploadFileOptions, opts?: ICustomReqOpts): Promise<IUploadFileResult>
  /**
   * downloadFile - 下载文件
   */
  downloadFile({ fileID, tempFilePath }: IDownloadFileOptions, opts?: ICustomReqOpts): Promise<IDownloadFileResult>
  /**
   * copyFile - 复制文件
   */
  copyFile({ fileList }: ICopyFileOptions, opts?: ICustomReqOpts): Promise<ICopyFileResult>
  /**
   * deleteFile - 删除文件
   */
  deleteFile({ fileList }: IDeleteFileOptions, opts?: ICustomReqOpts): Promise<IDeleteFileResult>
  /**
   * getTempFileURL - 获取文件临时访问地址
   */
  getTempFileURL({ fileList }: IGetFileUrlOptions, opts?: ICustomReqOpts): Promise<IGetFileUrlResult>
  /**
   * getFileInfo - 获取文件信息
   */
  getFileInfo({ fileList }: IGetFileInfoOptions, opts?: ICustomReqOpts): Promise<IGetFileInfoResult>
  /**
   * getUploadMetadata - 获取文件上传元数据信息
   */
  getUploadMetadata({ cloudPath }: IGetUploadMetadataOptions, opts?: ICustomReqOpts): Promise<IGetUploadMetadataResult>
  /**
   * getFileAuthority - 获取文件权限信息
   */
  getFileAuthority({ fileList }: IGetFileAuthorityOptions, opts?: ICustomReqOpts): Promise<IGetFileAuthorityResult>

  callWxOpenApi(wxOpenApiOptions: ICallWxOpenApiOptions, opts?: ICustomReqOpts): Promise<ICallWxOpenApiResult>
  callWxPayApi(wxOpenApiOptions: ICallWxOpenApiOptions, opts?: ICustomReqOpts): Promise<any>
  wxCallContainerApi(wxOpenApiOptions: ICallWxOpenApiOptions, opts?: ICustomReqOpts): Promise<any>
  callCompatibleWxOpenApi(wxOpenApiOptions: ICallWxOpenApiOptions, opts?: ICustomReqOpts): Promise<any>

  /**
   * ai - 获取 AI 实例
   */
  ai(): AI

  registerExtension(ext: Extension): void
  invokeExtension<T>(name: string, opts: T)
}

export const version: string
export const SYMBOL_CURRENT_ENV: symbol // 当前环境
export const SYMBOL_DEFAULT_ENV: symbol // 默认环境
export const init: (config?: ICloudBaseConfig) => CloudBase
export const parseContext: (context: IContextParam) => ISCFContext
export const getCloudbaseContext: (context?: IContextParam) => ICompleteCloudbaseContext

export interface ICallApisOptions<T> {
  name: string
  method?: 'POST'
  path?: string
  header?: IHeaderOpts
  body?: T
  config?: any
  token?: string
}
