import { Response } from './../redux/Common/types'
import ShopifyService from './ShopifyService'
import RyeApi from './api/rye.api'
import {
  ReorderShopifyStoreRequest,
  ShopifyProductItem
} from 'models/talent/talent-profile-module.model'

interface RyeShopifyStore {
  connected: boolean
  name: string
  shop: string
}

const normalizeProducts = (
  product: any,
  shopDomain?: string,
  collectionId?: string
) => {
  const images = product.images as any[]
  const variants = product.variants as any[]
  return {
    id: product.id,
    shop: shopDomain,
    collectionId: collectionId,
    images: images.map(image => ({ src: image.url })) || [],
    title: product.title,
    variants:
      variants.map(variant => ({
        price: product.price.displayValue,
        priceV2: {
          currencyCode: product.price.currency,
          amount: String(Number(product.price.value) / 100)
        }
      })) || []
  } as ShopifyProductItem
}

export type PageInfo = {
  endCursor: string
  hasNextPage: boolean
}

export type NormalizedCollection = {
  id: string
  title: string
}

export default class RyeShopifyServices {
  constructor(
    private readonly api: RyeApi,
    private readonly shopifyService: ShopifyService
  ) {}

  fetchCollections = async (
    shopDomain: string,
    after: string | null = null
  ): Promise<{ collections: NormalizedCollection[]; pageInfo: PageInfo }> => {
    const apiResponse = await this.api.getCollections(shopDomain, after)
    const collections = (apiResponse.response.edges ?? []) as any[]

    return {
      collections: collections.map(x => x.node),
      pageInfo: apiResponse.response.pageInfo
    }
  }

  fetchCollection = async (collectionId: string): Promise<any> => {
    const apiResponse = await this.api.getCollection(collectionId)
    const collection = apiResponse.response?.shopifyCollection
    const collectionTitle = collection?.title
    const collectionSrc = undefined

    const products = collection?.productsConnection.edges ?? []
    const normalizedProducts = products.map(el =>
      normalizeProducts(el.node, undefined, collectionId)
    ) as ShopifyProductItem[]

    return {
      id: collectionId,
      title: collectionTitle,
      src: collectionSrc,
      products: normalizedProducts
    }
  }

  fetchProducts = async (
    shopDomain: string,
    collectionId?: string,
    offset = 0
  ): Promise<any[]> => {
    const data = await this.api.getProducts(
      shopDomain,
      offset,
      this.productsPageSize
    )
    const products = data.response as any[]
    const normalizedProducts = products.map(product =>
      normalizeProducts(product, shopDomain, collectionId)
    ) as ShopifyProductItem[]

    return normalizedProducts || []
  }

  get productsPageSize() {
    return 100
  }

  fetchProductsByIDs = async (
    shopDomain: string,
    productIds: string[]
  ): Promise<any[]> => {
    const data = await this.api.getProductsByIds(shopDomain, productIds)
    const products = data.response?.productsByIDs.filter(Boolean) ?? []
    const normalizedProducts = products.map(product =>
      normalizeProducts(product, shopDomain)
    ) as ShopifyProductItem[]

    return normalizedProducts || []
  }

  checkIfAppInstalled = async (shopDomain: string): Promise<boolean> => {
    const data = await this.api.checkIfAppInstalled(shopDomain)
    return Boolean(data.response)
  }

  reorderStore = (payload: ReorderShopifyStoreRequest[]) => {
    return this.shopifyService.reorderRyeShopifyStore(payload)
  }

  getRyeStores = async (
    talentProfileId: string
  ): Promise<RyeShopifyStore[]> => {
    const data = await this.shopifyService.getRyeShopifyStores(talentProfileId)
    return data.response?.result?.stores || []
  }

  createRyeStore = async (
    talentProfileId: string,
    storeDomain: string
  ): Promise<boolean> => {
    const resp = await this.shopifyService.createRyeShopifyStore(
      talentProfileId,
      storeDomain
    )
    return Boolean(resp.ok && resp?.response?.success)
  }

  updateRyeStoreName = (
    talentProfileId: string,
    storeDomain: string,
    name: string
  ): Promise<Response<any>> => {
    return this.shopifyService.updateRyeShopifyStoreName(
      talentProfileId,
      storeDomain,
      name
    )
  }

  updateRyeStoreStatus = (
    talentProfileId: string,
    storeDomain: string,
    connected: boolean
  ): Promise<Response<any>> => {
    return this.shopifyService.updateRyeShopifyStoreStatus(
      talentProfileId,
      storeDomain,
      connected
    )
  }

  removeRyeStore = (
    talentProfileId: string,
    storeDomain: string
  ): Promise<Response<any>> => {
    return this.shopifyService.removeRyeShopifyStore(
      talentProfileId,
      storeDomain
    )
  }

  generateRyeShopifyAppInstalLink(storeCanonicalDomain: string) {
    return this.api.generateRyeShopifyAppInstalLink(storeCanonicalDomain)
  }
}
