// withHooks

import { LibCurl } from 'esoftplay/cache/lib/curl/import';
import { LibDialog } from 'esoftplay/cache/lib/dialog/import';
import { LibIcon } from 'esoftplay/cache/lib/icon/import';
import { LibList } from 'esoftplay/cache/lib/list/import';
import { LibNavigation } from 'esoftplay/cache/lib/navigation/import';
import { LibObject } from 'esoftplay/cache/lib/object/import';
import { LibProgress } from 'esoftplay/cache/lib/progress/import';
import { LibSkeleton } from 'esoftplay/cache/lib/skeleton/import';
import { LibStyle } from 'esoftplay/cache/lib/style/import';
import { LibTextstyle } from 'esoftplay/cache/lib/textstyle/import';
import { LibToastProperty } from 'esoftplay/cache/lib/toast/import';
import { LibUtils } from 'esoftplay/cache/lib/utils/import';
import { MarketButton } from 'esoftplay/cache/market/button/import';
import { MarketCart_item } from 'esoftplay/cache/market/cart_item/import';
import { MarketEmpty } from 'esoftplay/cache/market/empty/import';
import { MarketHeader } from 'esoftplay/cache/market/header/import';
import { MarketMerchant_favorite } from 'esoftplay/cache/market/merchant_favorite/import';
import { MarketStyle } from 'esoftplay/cache/market/style/import';
import { MarketWishlist } from 'esoftplay/cache/market/wishlist/import';
import esp from 'esoftplay/esp';

import useGlobalState, { useGlobalReturn } from 'esoftplay/global';
import useSafeState from 'esoftplay/state';
import React, { useEffect } from 'react';
import { TouchableOpacity, View } from 'react-native';

export interface MarketCartArgs {
  initialIndex?: number
}

export interface MarketCartProps {

}

const cartData = {
  list: [],
  empty: false,
  check: 0
}

const count = useGlobalState<number>(0)
export function countState(): useGlobalReturn<number> {
  return count
}

const productIds = useGlobalState<any[]>([])
const merchantIds = useGlobalState<any[]>([])

export function getCountState(): void {
  new LibCurl('shop/product_cart_count', null, (r: any) => count.set(parseInt(r)), () => count.set(0))
}

export function add(product_id: string, qty: number, notes?: string, price_id?: string, advert_id?: string, advert_keyword?: string): void {
  new LibCurl('shop/product_cart_add', { product_id, qty, price_id, notes, advert_id: advert_id || '', advert_keyword: advert_keyword || '' },
    (res, msg) => {
      getCountState()
      LibToastProperty.show(res)
    },
    (msg) => {
      LibToastProperty.show(msg?.message)
    }, 1
  )
}

export function updateStructure(res: any) {
  let newRes = Object.values(res.list).map((item: any) => {
    let newProduct = Object.values(item.products).map((variant: any) => Object.values(variant))
    return ({
      ...item,
      merchant: { ...item.merchant },
      products: newProduct
        .reduce((acc, val: any) => acc.concat(val), [])
        .map((val: any) => ({ ...val, subtotal_price: val.sale * val.qty, check: 1 }))
    })
  })
  return newRes
}

export function buyNow(product_id: string, qty: number, notes?: string, price_id?: string, advert_id?: string, advert_keyword?: string) {
  LibProgress.show(esp.lang("market/cart", "buy_wait"))
  //first need to add item to cart
  new LibCurl('shop/product_cart_add', { product_id, qty, price_id, notes, advert_id: advert_id || '', advert_keyword: advert_keyword || '' },
    (res1, msg) => {
      //get list if cart
      new LibCurl('shop/product_cart?page=0', null,
        (res) => {
          const newRes = updateStructure(res)
          //get cart_ids item recent add
          const cart_ids = newRes[0].products?.filter?.((f: any, i: number) => f.id == product_id && f.price_id == price_id)[0].cart_id
          const url = 'shop/product_cart_checkout'
          const scart_ids = JSON.stringify([cart_ids])
          //update qty with new qty
          new LibCurl('shop/product_cart_update', { id: cart_ids, qty, notes },
            (update) => {
              //success to update qty
              //checkout
              new LibCurl(url, { cart_ids: scart_ids },
                (res, msg) => {
                  LibProgress.hide()
                  LibNavigation.navigate("market/checkout", { data: res, url, cart_ids: scart_ids })
                },
                (msg) => {
                  LibProgress.hide()
                  LibDialog.warning(esp.lang("market/cart", "failed_cart_update1"), msg?.message)
                }, 1
              )
            }, (err) => {
              LibProgress.hide()
              LibDialog.warning(esp.lang("market/cart", "failed_cart_update"), err?.message)
            }, 1)
        }, (msg) => {
          LibProgress.hide()
          LibDialog.warning(esp.lang("market/cart", "failed_cart"), msg?.message)
        }, 1
      )
    },
    (msg) => {
      LibProgress.hide()
      LibDialog.warning(esp.lang("market/cart", "failed_cart_add"), msg?.message)
    }, 1
  )
}

export default function m(props: MarketCartProps): any {
  const { initialIndex } = LibNavigation.getArgsAll<any>(props)
  const [data, setData, getData] = useSafeState<any>(cartData)
  const [page, setPage] = useSafeState<number>(0)
  const [tab, setTab] = useSafeState<number>(initialIndex || 0)

  const menus = [
    {
      label: esp.lang("market/cart", "label_cart")
    },
    {
      label: esp.lang("market/cart", "label_wishlist")
    },
    {
      label: esp.lang("market/cart", "label_favorite")
    },
  ]


  useEffect(() => {
    list()
  }, [])

  function list(page?: number): void {
    new LibCurl('shop/product_cart?page=' + (page || 0), null,
      (res, msg) => {
        let newRes = Object.values(res.list).map((item: any) => {
          let newProduct = Object.values(item.products).map((variant: any) => Object.values(variant))
          return ({
            ...item,
            check: merchantIds.get().includes(item?.merchant?.id) ? 1 : 0,
            merchant: { ...item.merchant },
            products: newProduct
              .reduce((acc, val: any) => acc.concat(val), [])
              .map((val: any) => ({ ...val, subtotal_price: val.sale * val.qty, check: productIds.get().includes(val.id) ? 1 : 0 }))
          })
        })
        res.list = newRes
        let allData = page == 0 ? newRes : [...getData().list, ...newRes]
        let checked = 0
        let newData = { ...getData(), check: checked, list: allData }
        newData.total_price = newData.list
          .reduce((acc: number, merchant: any) => acc + merchant.products
            .filter((x: any) => x.check == 1)
            .reduce((acc: number, cur: any) => acc + Number(cur.subtotal_price), 0), 0)
        setData(newData)

        if (allData.length >= res.total) {
          setPage(-1)
        } else
          setPage(page || 0)
      }, (msg) => {
        setData((x: any) => ({ ...x, empty: msg?.message }))
      }
    )
  }

  function edit(cart_id: string, qty?: number, notes?: string, data?: any): void {
    new LibCurl('shop/product_cart_update', { id: cart_id, qty, notes },
      (res, msg) => {
        getCountState()
        if (data)
          setData(data)
      },
      (msg) => {
        LibToastProperty.show(msg?.message)
      }, 1
    )
  }

  function del(cart_id: string, data?: any): void {
    new LibCurl('shop/product_cart_delete', { id: cart_id },
      (res, msg) => {
        getCountState()
        if (data)
          setData(data)
      },
      (msg) => {
        LibToastProperty.show(msg?.message)
      }, 1
    )
  }

  function deleteProduct(indexMerchant: number, indexProduct: number) {
    let newData = LibObject.assign({}, getData())()
    let merchant = newData.list[indexMerchant]
    let productDeleted = merchant.products?.[indexProduct]
    merchant.products?.splice(indexProduct, 1)
    merchant.check = merchant.products?.some?.((x: any) => x.check == 0) ? 0 : 1
    newData.list[indexMerchant] = merchant
    if (merchant.products?.length == 0) {
      newData.list.splice(indexMerchant, 1)
    }
    newData.total_price = newData.list
      .reduce((acc: number, merchant: any) => acc + merchant.products
        .filter((x: any) => x.check == 1)
        .reduce((acc: number, cur: any) => acc + Number(cur.subtotal_price), 0), 0)
    del(productDeleted.cart_id, newData)
  }

  function deleteMerchant(indexMerchant: number) {
    let newData = LibObject.assign({}, getData())()
    newData.list.splice(indexMerchant, 1)
    newData.total_price = newData.list
      .reduce((acc: number, merchant: any) => acc + merchant.products
        .filter((x: any) => x.check == 1)
        .reduce((acc: number, cur: any) => acc + Number(cur.subtotal_price), 0), 0)
    newData.check = newData.list.some((x: any) => x.check == 0) ? 0 : 1
    let _merchant = newData.list[indexMerchant]
    _merchant.products?.map?.((product: any) => {
      del(product.cart_id)
    })
    setData(newData)
  }

  function changeQty(indexMerchant: number, indexProduct: number, qty: number) {
    let newData = LibObject.assign({}, getData())()
    let merchant = newData.list[indexMerchant]
    merchant.products[indexProduct].qty = qty
    merchant.products[indexProduct].subtotal_price = qty * merchant.products?.[indexProduct].sale
    newData.list[indexMerchant] = merchant
    newData.total_price = newData.list
      .reduce((acc: number, merchant: any) => acc + merchant.products
        .filter((x: any) => x.check == 1)
        .reduce((acc: number, cur: any) => acc + Number(cur.subtotal_price), 0), 0)

    let _merchant = newData.list[indexMerchant]
    let product = _merchant.products[indexProduct]
    edit(product.cart_id, product.qty, product.notes, newData)
  }

  function changeNotes(indexMerchant: number, indexProduct: number, notes: string) {
    let newData = LibObject.assign({}, getData())()
    let merchant = newData.list[indexMerchant]
    merchant.products[indexProduct].notes = notes
    newData.list[indexMerchant] = merchant

    let _merchant = newData.list[indexMerchant]
    let product = _merchant.products[indexProduct]
    edit(product.cart_id, product.qty, product.notes, newData)
  }

  function checkAll(check: 0 | 1) {
    let newData = LibObject.assign({}, getData())()
    for (let i = 0; i < newData.list.length; i++) {
      let merchant = newData.list[i];
      merchant.check = merchant.products?.some?.((x: any) => x.disabled == 0) ? check : 0
      for (let j = 0; j < merchant.products?.length; j++) {
        let product = merchant.products[j];
        product.check = product.disabled == 1 ? 0 : check
        merchant.products[j] = product
      }
      newData.list[i] = merchant
    }
    newData.check = check
    newData.total_price = newData.list
      .reduce((acc: number, merchant: any) => acc + merchant.products
        .filter((x: any) => x.check == 1 && x.disabled == 0)
        .reduce((acc: number, cur: any) => acc + Number(cur.subtotal_price), 0), 0)
    setData((x: any) => LibObject.set(x, newData)())
  }

  function checkMerchant(index: number, check: 0 | 1) {
    let newData = LibObject.assign({}, getData())()
    let merchant = newData.list[index]
    let products = merchant.products
    let _newData = newData.list.filter((x: any) => x.products?.some?.((y: any) => y.disabled == 0))
    products?.forEach((product: any, idx: number) => {
      product.check = product.disabled == 1 ? 0 : check
      merchant.products[idx] = product
    });
    merchant.check = check
    newData.list[index] = merchant
    //check for other all merchant hsyaas been check
    newData.check = _newData.some((x: any) => x.check == 0) ? 0 : 1
    newData.total_price = newData.list
      .reduce((acc: number, merchant: any) => acc + merchant.products
        .filter((x: any) => x.check == 1 && x.disabled != 1)
        .reduce((acc: number, cur: any) => acc + Number(cur.subtotal_price), 0), 0)
    setData((x: any) => LibObject.set(x, newData)())
  }

  function checkProduct(indexMerchant: number, indexProduct: number, check: 0 | 1) {
    let newData = LibObject.assign({}, getData())()
    let merchant = newData.list[indexMerchant]
    let product_merchant = merchant.products?.filter?.((x: any) => x.disabled == 0)
    let _newData = newData.list.filter((x: any) => x.products?.some?.((y: any) => y.disabled == 0))
    merchant.products[indexProduct].check = check
    merchant.check = product_merchant.some((x: any) => x.check == 0) ? 0 : 1
    newData.list[indexMerchant] = merchant
    newData.check = _newData.some((x: any) => x.check == 0) ? 0 : 1
    newData.total_price = newData.list
      .reduce((acc: number, merchant: any) => acc + merchant.products
        .filter((x: any) => x.check == 1)
        .reduce((acc: number, cur: any) => acc + Number(cur.subtotal_price), 0), 0)
    setData((x: any) => LibObject.set(x, newData)())
  }

  function saveProductId(item: any, idxProduct: number) {
    const id = item?.products?.[idxProduct]?.id
    let data = productIds.get()
    const idx = data.findIndex((t) => t == id)
    if (productIds.get().includes(id)) {
      data = LibObject.splice(data, idx, 1)()
    } else {
      data = LibObject.push(data, id)()
    }
    productIds.set(data)
  }

  function saveMerchantId(item: any) {
    const id = item?.merchant?.id
    let data = merchantIds.get()
    const idx = data.findIndex((t) => t == id)
    const product_id = item.products?.map?.((t: any) => t.id)
    let newProductId = productIds.get()

    if (merchantIds.get().includes(id)) {
      data = LibObject.splice(data, idx, 1)()
      newProductId = newProductId.filter((t) => !product_id.includes(t))
    } else {
      data = LibObject.push(data, id)()
      newProductId = product_id.concat(productIds.get().filter((item) => product_id.indexOf(item) < 0))
    }
    merchantIds.set(data)
    productIds.set(newProductId)
  }

  function doCheckout() {
    const cart_ids = data.list
      .map((x: any) => x.products)
      .reduce((acc: any[], curr: any[]) => [...acc, ...curr], [])
      .filter((x: any) => x.check == 1)
      .map((x: any) => x.cart_id)
    const url = 'shop/product_cart_checkout'
    LibProgress.show(esp.lang("market/cart", "checkout_wait"))
    const scart_ids = JSON.stringify(cart_ids)
    new LibCurl(url, { cart_ids: scart_ids },
      (res, msg) => {
        LibProgress.hide()
        LibNavigation.navigate("market/checkout", { data: res, url, cart_ids: scart_ids })
      },
      (msg) => {
        LibProgress.hide()
        LibToastProperty.show(msg?.message, 4000)
      }, 1
    )
  }

  return (
    <View style={styleId_ZcMJmd} >
      <MarketHeader
        leftIcon={{ name: "close", onPress: () => LibNavigation.back() }}
        title={esp.lang("market/cart", "header_title")}
        subtitle={esp.lang("market/cart", "header_subtitle")}
      />
      <View style={styleId_12U7Tm}>
        {
          menus.map((item: any, i: number) => {
            return (
              <TouchableOpacity
                key={i}
                onPress={() => setTab(i)}
                style={[styleId_AWk1u, { backgroundColor: i == tab ? MarketStyle.colorPrimaryMarket : 'transparent', borderColor: i == tab ? 'transparent' : '#ccc' }]} >
                <LibTextstyle textStyle='footnote' text={item.label} style={{ color: i == tab ? '#f1f1f1' : '#4E4E4E' }} />
              </TouchableOpacity>
            )
          })
        }
      </View>
      {
        tab == 0 ?
          <>
            <View style={styleId_ZcMJmd} >
              <LibList
                data={data.list}
                onRefresh={() => list(0)}
                ListEmptyComponent={data.empty ? <MarketEmpty msg={data.empty} /> : null}
                ListFooterComponent={page > -1 ? data.empty ? null :
                  <View>
                    <LibSkeleton backgroundStyle={{ height: LibStyle.height }} >
                      <View style={styleId_244SP6}>
                        <LibIcon name="checkbox-blank-circle-outline" />
                        <View style={styleId_ZfxrbJ} />
                        <View style={styleId_ZkwSed}>
                          <View style={styleId_1b2cvL} />
                          <View style={styleId_Zrz44M}>
                            <LibIcon name="map-marker" size={16} />
                            <View style={styleId_Z1B9XJh} />
                          </View>
                        </View>
                      </View>
                      {
                        [1, 1, 1, 1].map((x: any, i: number) => (
                          <View style={styleId_2JvFA}>
                            <LibIcon name="checkbox-blank-circle-outline" style={styleId_2tlMHb} />
                            <View style={styleId_Z1wMUdr} />
                            <View style={styleId_ZEsW9C}>
                              <View style={styleId_Z1B9XJh} />
                              <View style={styleId_Wqk5L} />
                              <View style={styleId_1ewN2U}>
                                <LibIcon name='pencil' size={16} />
                                <View style={styleId_ZE0wcq} />
                              </View>
                              <View style={styleId_1exs4N}>
                                <LibIcon name='minus-circle' size={20} />
                                <View style={styleId_Z1GIIX1} />
                                <LibIcon name='plus-circle' size={20} />
                              </View>
                            </View>
                            <LibIcon name='delete' />
                          </View>
                        ))
                      }
                      <View style={styleId_Z1xUrle} />
                    </LibSkeleton>
                  </View>
                  : null}
                onEndReached={() => page == -1 ? {} : list(page + 1)}
                keyExtractor={(x, i) => i.toString()}
                renderItem={(item, i) => (
                  <MarketCart_item
                    {...item}
                    currency={data.currency}
                    key={i}
                    idx={i}
                    checkMerchant={(idx: number, check: 0 | 1) => {
                      checkMerchant(idx, check)
                      esp.isDebug('#saveRecentSelect') && saveMerchantId(item)
                    }}
                    checkProduct={(idxmerchant: number, idxproduct: number, check: 0 | 1) => {
                      checkProduct(idxmerchant, idxproduct, check)
                      esp.isDebug('#saveRecentSelect') && saveProductId(item, idxproduct)
                    }}
                    changeQty={changeQty}
                    changeNotes={changeNotes}
                    deleteMerchant={deleteMerchant}
                    deleteProduct={deleteProduct}
                  />
                )}
              />
            </View>
            <View style={styleId_1aTbKo} >
              <View style={[styleId_1fmvBo]} >
                <TouchableOpacity onPress={() => (checkAll(data.check == 1 ? 0 : 1))} style={styleId_1Apyol} >
                  <LibIcon name={data.check == 1 ? "checkbox-marked-circle-outline" : "checkbox-blank-circle-outline"} color={data.check == 1 ? MarketStyle.colorGreen : "#bbb"} />
                </TouchableOpacity>
                <View style={styleId_1KxIIo} >
                  <LibTextstyle text={esp.lang("market/cart", "text_all")} textStyle={'footnote'} />
                </View>
              </View>
              <View style={styleId_vhsaM} >
                <LibTextstyle style={styleId_TR7Py} text={esp.lang("market/cart", "text_total")} textStyle="footnote" />
                <LibTextstyle style={styleId_1Y1eaK} text={LibUtils.money(data.total_price, data.currency)} textStyle="footnote" />
              </View>
              <MarketButton text={esp.lang("market/cart", "btn_checkout")}
                color={"white"}
                colorBackground={data?.list?.length > 0 ? MarketStyle.colorPrimaryMarket : LibStyle.colorGrey}
                buttonStyle={styleId_17oll4}
                onPress={() => {
                  if (data?.list?.length > 0) {
                    doCheckout()
                  } else {
                    LibToastProperty.show(esp.lang("market/cart", "checkout_wait_btn"))
                  }
                }} />
            </View>
          </>
          : tab == 1 ?
            <MarketWishlist />
            : tab == 2 ?
              <MarketMerchant_favorite />
              : null
      }
    </View>
  )
}
const styleId_ZcMJmd: any = { flex: 1 }
const styleId_12U7Tm: any = { flexDirection: 'row', marginLeft: 20, marginRight: 20, marginTop: 15, marginBottom: 15, justifyContent: 'space-between' }
const styleId_AWk1u: any = { height: 32, marginRight: 10, borderRadius: 20, borderWidth: 1, paddingHorizontal: 17, justifyContent: 'center' }
const styleId_244SP6: any = { marginTop: 15, flexDirection: 'row', alignItems: 'center', marginHorizontal: 17, marginLeft: 25 }
const styleId_ZfxrbJ: any = { marginLeft: 15, width: 20, height: 20, borderRadius: 5, backgroundColor: 'white' }
const styleId_ZkwSed: any = { marginLeft: 15 }
const styleId_1b2cvL: any = { width: '40%', height: 14, borderRadius: 10, backgroundColor: 'white' }
const styleId_Zrz44M: any = { flexDirection: 'row', alignItems: 'center', marginTop: 5 }
const styleId_Z1B9XJh: any = { width: '60%', height: 12, borderRadius: 10, backgroundColor: 'white' }
const styleId_2JvFA: any = { flexDirection: 'row', marginTop: 20, marginHorizontal: 17, marginLeft: 25 }
const styleId_2tlMHb: any = { marginTop: 10 }
const styleId_Z1wMUdr: any = { marginLeft: 15, width: 50, height: 50, borderRadius: 5, backgroundColor: 'white' }
const styleId_ZEsW9C: any = { marginLeft: 15, flex: 1 }
const styleId_Wqk5L: any = { width: '40%', height: 14, borderRadius: 10, backgroundColor: 'white', marginTop: 10 }
const styleId_1ewN2U: any = { flexDirection: 'row', alignItems: 'center', marginTop: 10 }
const styleId_ZE0wcq: any = { marginLeft: 10, width: '40%', height: 14, borderRadius: 10, backgroundColor: 'white' }
const styleId_1exs4N: any = { flexDirection: 'row', alignItems: 'center', marginTop: 15 }
const styleId_Z1GIIX1: any = { width: 18, height: 18, borderRadius: 9, backgroundColor: 'white', marginHorizontal: 12 }
const styleId_Z1xUrle: any = { marginTop: 15, height: 20, backgroundColor: 'white' }
const styleId_1aTbKo: any = { flexDirection: "row", backgroundColor: "white", borderTopWidth: 1, borderTopColor: "#ddd" }
const styleId_1fmvBo: any = { flexDirection: 'row', alignItems: 'center' }
const styleId_1Apyol: any = { padding: 10, paddingRight: 0 }
const styleId_1KxIIo: any = { padding: 10 }
const styleId_vhsaM: any = { flex: 1, padding: 10 }
const styleId_TR7Py: any = { textAlign: "right" }
const styleId_1Y1eaK: any = { textAlign: "right", fontWeight: "bold" }
const styleId_17oll4: any = { margin: 10, paddingHorizontal: 15 }