import { Products, StoreWritePostResponse } from '@komi-app/assets-sdk'
import {
  DigitalProductUploadBody,
  DigitalProductUploadTokenResponse,
  Profiles
} from '@komi-app/profiles-sdk'
import { getSDKConfig } from 'config'
import { SdkConfig } from '@komi-app/sales-sdk'
import { Maybe } from 'utils/types'
import { Response } from './../redux/Common/types'
import { FLAGS, isOn } from '@komi-app/flags-sdk'
import contentDisposition from 'content-disposition'

export type UploadFilePayload = {
  profileId: string
  token: string
  file: File
}

export interface IDigitalProductService {
  uploadFile(payload: UploadFilePayload): Promise<Maybe<StoreWritePostResponse>>
}

export default class DigitalProductService implements IDigitalProductService {
  private digitalProduct: Products
  private profileService: Profiles
  constructor() {
    const useGateway = isOn(FLAGS.USE_API_GATEWAY_ASSETS_SERVICE)
    const digitalProductConfig: SdkConfig = getSDKConfig(
      'assetsService',
      useGateway
    )
    const profileConfig: SdkConfig = getSDKConfig('profiles', useGateway)
    this.digitalProduct = new Products(digitalProductConfig)
    this.profileService = new Profiles(profileConfig)
  }

  init(profileId: string) {
    this.digitalProduct.init(profileId)
    this.profileService.init(profileId)
  }

  getUploadTokens = async (
    payload: DigitalProductUploadBody
  ): Promise<Response<DigitalProductUploadTokenResponse>> => {
    try {
      const res = await this.profileService.getUploadTokens(payload)
      return {
        ok: true,
        response: res
      }
    } catch (err) {
      return { kind: 'server', status: 500 }
    }
  }

  uploadFile = async (
    payload: UploadFilePayload
  ): Promise<Maybe<StoreWritePostResponse>> => {
    const useGateway = isOn(FLAGS.USE_API_GATEWAY_ASSETS_SERVICE)

    // Gateway has to upload via S3
    if (useGateway) {
      return this.uploadFileS3(payload)
    }

    return this.uploadFileDirect(payload)
  }

  /**
   * Upload file directly to assets service
   * Won't work with API gateway due to 10mb payload limit
   */
  uploadFileDirect = async (
    payload: UploadFilePayload
  ): Promise<Maybe<StoreWritePostResponse>> => {
    try {
      const { profileId, token, file } = payload
      const bodyFormData = new FormData()
      bodyFormData.append('file', file)

      return this.digitalProduct.uploadFile(profileId, token, file)
    } catch (err) {
      console.error(err)
      return void 0
    }
  }

  /**
   * New upload method, fetch a presigned url from assets service and upload the file to S3
   */
  uploadFileS3 = async (
    payload: UploadFilePayload
  ): Promise<Maybe<StoreWritePostResponse>> => {
    try {
      const { profileId, token, file } = payload

      const { url: presignedUrl } =
        await this.digitalProduct.getPresignedUploadUrl(profileId, token)

      const res = await fetch(presignedUrl, {
        method: 'PUT',
        body: file,
        headers: {
          'Content-Disposition': contentDisposition(file.name)
        }
      })

      if (!res.ok) {
        console.error('Failed to upload', res.status, res.statusText)

        throw new Error('Failed to upload file')
      }

      console.log(presignedUrl)

      // Remove the query string to get the real url
      const publicUrl = presignedUrl.split('?')[0]

      console.log(publicUrl)

      return {
        url: publicUrl
      }
    } catch (err) {
      console.error(err)
      return void 0
    }
  }
}
