import type { CallbackWithResult } from '@react-native-async-storage/async-storage/lib/typescript/types'
import { NativeModules, Platform } from 'react-native'
const ReadyWallet = NativeModules.ReadyWallet

type ErrorLike = {
  message: string
  key?: string
}

class SupperAsyncStorage {
  public readonly AS_READY_WALLET = '@readyio_ready_wallet'

  private checkValidInput(...input: unknown[]) {
    const [key, value] = input

    if (typeof key !== 'string') {
      // eslint-disable-next-line no-console
      console.warn(
        `[AsyncStorage] Using ${typeof key} type for key is not supported. This can lead to unexpected behavior/errors. Use string instead.\nKey passed: ${key}\n`
      )
    }

    if (input.length > 1 && typeof value !== 'string') {
      if (value == null) {
        throw new Error(
          `[AsyncStorage] Passing null/undefined as value is not supported. If you want to remove value, Use .removeItem method instead.\nPassed value: ${value}\nPassed key: ${key}\n`
        )
      } else {
        // eslint-disable-next-line no-console
        console.warn(
          `[AsyncStorage] The value for key "${key}" is not a string. This can lead to unexpected behavior/errors. Consider stringifying it.\nPassed value: ${value}\nPassed key: ${key}\n`
        )
      }
    }
  }

  private ensureArray(e?: ErrorLike | ErrorLike[]): ErrorLike[] | null {
    if (Array.isArray(e)) {
      return e.length === 0 ? null : e
    } else if (e) {
      return [e]
    } else {
      return null
    }
  }
  private convertError(error?: ErrorLike): Error | null {
    if (!error) {
      return null
    }

    const out = new Error(error.message) as Error & ErrorLike
    out.key = error.key
    return out
  }

  private convertErrors(errs?: ErrorLike[]): ReadonlyArray<Error | null> | null {
    const errors = this.ensureArray(errs)
    return errors ? errors.map((e) => this.convertError(e)) : null
  }

  public async getItem(key: string, callback?: CallbackWithResult<string>): Promise<string | null> {
    return new Promise((resolve, reject) => {
      this.checkValidInput(key)
      if (Platform.OS === 'android') {
        ReadyWallet.multiGet([key], (errors?: ErrorLike[], result?: string[][]) => {
          // Unpack result to get value from [[key,value]]
          const value = result?.[0]?.[1] ? result[0][1] : null
          const errs = this.convertErrors(errors)
          callback?.(errs?.[0], value)
          if (errs) {
            reject(errs[0])
          } else {
            resolve(value)
          }
        })
      }
      if (Platform.OS === 'ios') {
        ReadyWallet.getItem(key).then((value: any) => {
          resolve(value)
        })
      }
    })
  }
}

export default new SupperAsyncStorage()
