import { IRouter, NextFunction, Request as ExpressRequest, Response as ExpressResponse } from 'express'
export { Request, Response } from 'express'

interface Router extends IRouter {
  invoke: (body?: any, options?: any) => Promise<{ body: any; status: number; headers: any }>
}

export type StaticOptions = {
  path: string
}

export interface API {
  get: Router['get']
  post: Router['post']
  put: Router['put']
  delete: Router['delete']
  patch: Router['patch']
  options: Router['options']
  head: Router['head']
  all: Router['all']
  use: Router['use']
  static?: (directory: string, options: StaticOptions) => void
  upload?: (path: string, handler: (req: ExpressRequest, res: ExpressResponse, error?: Error) => void) => void
  rawBody: (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => any
}

declare global {
  namespace Express {
    namespace Cloud {
      interface File {
        fieldname?: string
        originalname?: string
        encoding?: string
        mimetype?: string
        buffer: Buffer
        size: number
      }
    }

    interface Request {
      rawBody?: any
      files?:
        | {
            [fieldname: string]: Cloud.File[]
          }
        | Cloud.File[]
        | undefined
    }

    interface Response {
      sendFile: (path: string, options?: any) => Promise<void>
    }
  }
}

declare const api: API
export default api
