import { Client as AutoGeneratedClient, User } from './gen/client'

export type { Message, Conversation, User, Event } from './gen/client'

type AsyncFunction = (...args: any[]) => Promise<any>

type Simplify<T> = T extends (...args: infer A) => infer R
  ? (...args: Simplify<A>) => Simplify<R>
  : T extends Buffer
    ? Buffer
    : T extends Promise<infer R>
      ? Promise<Simplify<R>>
      : T extends object
        ? T extends infer O
          ? { [K in keyof O]: Simplify<O[K]> }
          : never
        : T

export type Headers = Record<string, string>

type CommonClientProps = {
  timeout?: number
  headers?: Headers
  debug?: boolean
}

type ApiUrlClientProps = CommonClientProps & { apiUrl: string }
type WebhookIdClientProps = CommonClientProps & { webhookId: string; baseApiUrl?: string }

export type ClientProps = ApiUrlClientProps | WebhookIdClientProps

export type ConnectProps = ClientProps & {
  encryptionKey?: string
  userKey?: string
  userId?: string
}

export type ClientOperation = Simplify<
  keyof {
    [K in keyof AutoGeneratedClient as AutoGeneratedClient[K] extends AsyncFunction ? K : never]: null
  }
>

export type ClientRequests = {
  [K in ClientOperation]: Parameters<AutoGeneratedClient[K]>[0]
}

export type ClientResponses = {
  [K in ClientOperation]: Simplify<Awaited<ReturnType<AutoGeneratedClient[K]>>>
}

export type AuthenticatedOperation = Exclude<ClientOperation, 'createUser' | 'getOrCreateUser'>
export type AuthenticatedClientRequests = Simplify<{
  [K in AuthenticatedOperation]: Omit<ClientRequests[K], 'x-user-key'>
}>

export type AuthenticatedUser = Simplify<
  User & {
    key: string
  }
>
