// withHooks
import { applyStyle } from 'esoftplay';

import { LibIcon } from 'esoftplay/cache/lib/icon/import';
import { LibInfinite } from 'esoftplay/cache/lib/infinite/import';
import { LibLazy } from 'esoftplay/cache/lib/lazy/import';
import { LibNavigation } from 'esoftplay/cache/lib/navigation/import';
import { LibObject } from 'esoftplay/cache/lib/object/import';
import { LibSkeleton } from 'esoftplay/cache/lib/skeleton/import';
import { LibSlidingup } from 'esoftplay/cache/lib/slidingup/import';
import { LibStyle } from 'esoftplay/cache/lib/style/import';
import { LibTextstyle } from 'esoftplay/cache/lib/textstyle/import';
import { MarketAds_homeProperty } from 'esoftplay/cache/market/ads_home/import';
import { MarketAds_store_preview } from 'esoftplay/cache/market/ads_store_preview/import';
import { MarketDevice_type } from 'esoftplay/cache/market/device_type/import';
import { MarketEmpty_product } from 'esoftplay/cache/market/empty_product/import';
import { MarketHeader } from 'esoftplay/cache/market/header/import';
import { MarketProduct_item } from 'esoftplay/cache/market/product_item/import';
import { MarketProduct_list_filter } from 'esoftplay/cache/market/product_list_filter/import';
import { UserData } from 'esoftplay/cache/user/data/import';
import esp from 'esoftplay/esp';
import useGlobalState from 'esoftplay/global';
import useSafeState from 'esoftplay/state';

import React, { useEffect, useMemo, useRef } from 'react';
import { TouchableOpacity, View } from 'react-native';


export interface MarketProduct_list_searchArgs {
  title?: string
  url?: string
  keyword?: string
}

export interface MarketProduct_list_searchProps {
  noHeader?: boolean,
  url: string
}


function arrayArange(myArray: any[]) {
  let group_to_values = myArray.reduce((obj, item) => {
    obj[item.advert_id] = obj[item.advert_id] || [];
    obj[item.advert_id].push(item.product_id);
    return obj;
  }, {});
  let groups = Object.keys(group_to_values).map((key) => {
    return { advert_id: key, product_ids: group_to_values[key] };
  });
  return groups
}

const productCache = useGlobalState('{}', { persistKey: 'advert-market/product_list', loadOnInit: true })
const tokoCache = useGlobalState('{}', { persistKey: 'advert-market/product_list-toko', loadOnInit: true })

export function getProductCache(): string {
  return productCache.get()
}

export function getProductCacheMerchant(): string {
  return tokoCache.get()
}

export function setProductCache(data: any): void {
  let newCache = JSON.stringify(data)
  productCache.set(newCache)
}

export function setProductCacheMerchant(data: any): void {
  let newCache = JSON.stringify(data)
  tokoCache.set(newCache)
}

export function adsSaveCache(keyword: string, data: any[], type: 'product' | 'toko') {
  // AsyncStorage.removeItem('advert-market/product_list').then((x) => console.log('deleted', x))
  // AsyncStorage.removeItem('advert-market/product_list-toko').then((x) => console.log('deleted', x))
  const advertConfig = MarketAds_homeProperty.state().get()
  const _delay = ((type == 'product' ? advertConfig?.ads_cache : advertConfig?.ads_merchant_cache) || 86400) * 1000
  const _keyword = keyword.toLowerCase() || 'no-keyword'
  const dt = type == 'product' ? productCache.get() : tokoCache.get()

  const oldData = typeof dt == "object" ? dt : JSON.parse(dt) //returning object

  let newData: any = {};
  for (let i = 0; i < data.length; i++) {
    newData[data[i][1] + '-' + data[i][0]] = [data[i][0], data[i][1], data[i][2]];
  }

  if (oldData[_keyword]) {
    const a = Object.keys(oldData[_keyword])
    const c = Object.keys(newData)
    const res = a.filter((x) => c.some((y) => x === y));

    let result = {}
    let old = {}

    for (let i = 0; i < res.length; i++) {
      if ((newData[res[i]][2] - oldData[_keyword][res[i]][2]) >= _delay) {
        // @ts-ignore
        result[[res[i]]] = newData[res[i]]
      }
    }
    old = Object.assign(newData, result)
    oldData[_keyword] = Object.assign(oldData[_keyword], old)
  } else {
    oldData[_keyword] = newData
  }

  let saveData = JSON.stringify(oldData)
  type == 'product' ? productCache.set(saveData) : tokoCache.set(saveData)
}

export function getCacheToPost(keyword: string, type: 'product' | 'toko') {
  const advertConfig = MarketAds_homeProperty.state().get()
  const _delay = ((type == 'product' ? advertConfig?.ads_cache : advertConfig?.ads_merchant_cache) || 86400) * 1000
  let _keyword = keyword.toLowerCase() || 'no-keyword'
  const dt = type == 'product' ? productCache.get() : tokoCache.get()

  const data = typeof dt == "object" ? dt : JSON.parse(dt)
  const date = new Date().getTime()

  let post: any = []
  let itemIndex = data[_keyword]

  if (itemIndex) {
    post = Object.keys(itemIndex).filter((val) => (date - itemIndex[val][2]) < _delay)
      .map((t, i) => {
        return {
          advert_id: itemIndex[t][1],
          product_id: itemIndex[t][0]
        }
      })
  }
  return arrayArange(post)
}

export default function m(props: MarketProduct_list_searchProps): any {
  UserData.register('advert-market/product_list')
  const { url, title, keyword } = LibNavigation.getArgsAll<any>(props, { url: props.url || 'shop/product_list' })
  const [query, setQuery] = useSafeState(keyword || '')
  const [sort, setSort] = useSafeState('')
  const [location_id, setLocation_id] = useSafeState('')
  const [conditions, setConditions] = useSafeState('')
  const [product_cat, setProduct_cat] = useSafeState('')
  const [sale_min, setSale_min] = useSafeState('')
  const [sale_max, setSale_max] = useSafeState('')
  const refFilter = useRef<LibSlidingup>(null)
  const dimension = useMemo(() => MarketDevice_type(2, 4, 5), [])
  const imgDimension = useMemo(() => (LibStyle.width - ((dimension + 1) * 10)) / dimension, [])
  const [upData, setUpData] = useSafeState<any>()
  const [adsCache, setAdsCache] = useSafeState<any>()
  const timeStamp = useRef(new Date().getTime()).current
  let data: any = useRef([]).current

  useEffect(() => {
    if (upData != undefined) {
      setUpData(undefined)
    }
  }, [sort, query, location_id, conditions, product_cat, sale_min, sale_max])


  function buildUrl(url: string): string {
    if (sort != '') {
      url += url.includes('?') ? '&' : '?'
      url += 'sort=' + sort
    }
    if (query != '') {
      url += url.includes('?') ? '&' : '?'
      url += 'keyword=' + query
    }
    if (location_id != '') {
      url += url.includes('?') ? '&' : '?'
      url += 'location_id=' + location_id
    }
    if (conditions != '') {
      url += url.includes('?') ? '&' : '?'
      url += 'conditions=' + conditions
    }
    if (product_cat != '') {
      url += url.includes('?') ? '&' : '?'
      url += 'product_cat=' + product_cat
    }
    if (sale_min != '') {
      url += url.includes('?') ? '&' : '?'
      url += 'sale_min=' + sale_min
    }
    if (sale_max != '') {
      url += url.includes('?') ? '&' : '?'
      url += 'sale_max=' + sale_max
    }
    // if (adsId != '') {
    //   url += url.includes('?') ? '&' : '?'
    //   url += 'ads_id=' + adsId
    // }
    return url
  }

  let adsToPost = {
    advert_cache: JSON.stringify(getCacheToPost(keyword, 'product')),
    advert_merchant_cache: JSON.stringify(getCacheToPost(keyword, 'toko'))
  }

  function renderItems(item: any, i: number) {
    return (
      <MarketProduct_item key={i} {...item} width={imgDimension} search_keyword={query} onChangeWish={(wish) => { setUpData((x: any) => LibObject.set(x, wish)(i, 'wishlist')) }} />
    )
  }

  return (
    <View style={applyStyle({ flex: 1 })} >
      {
        !props.noHeader &&
        <View style={applyStyle({ backgroundColor: 'white' })} >
          <MarketHeader
            onlyBack
            centerView={() => (
              <TouchableOpacity
                onPress={() => LibNavigation.navigateForResult('market/product_search', { keyword: query }).then(setQuery)}
                style={applyStyle({ flex: 1, backgroundColor: '#f1f2f3', borderRadius: 10, height: 36, paddingHorizontal: 12, justifyContent: 'center' })} >
                <LibTextstyle text={query || esp.lang("market/product_list_search", "search")} textStyle={'callout'} style={applyStyle({ fontSize: 14, color: '#999' })} />
              </TouchableOpacity>
            )}
            rightView={() => (
              <TouchableOpacity onPress={() => refFilter.current!.show()} style={applyStyle({ width: 50, alignItems: 'center' })} >
                <LibIcon name='filter-outline' />
              </TouchableOpacity>
            )} />
        </View>
      }
      <LibLazy>
        <LibInfinite
          url={buildUrl(url)}
          key={buildUrl(url)}
          post={adsToPost}
          // isDebug={1}
          style={applyStyle({ marginHorizontal: 5, paddingTop: 10 })}
          initialNumToRender={4}
          numColumns={dimension}
          keyExtractor={(item, i) => i.toString()}
          onDataChange={(data: any, page: number) => { setUpData(data) }}
          onResponseEdit={(res) => {
            let newRes: any = res?.list?.filter?.((y: any) => y.advert_id != undefined).filter((d: any, i: any, s: any) => (
              s.findIndex((t: any) => (
                t.advert_id === d.advert_id && t.id === d.id
              )) == i
            ))?.map?.((x: any) => ([x.advert_id, x.id, timeStamp]))
            data = LibObject.push(data, ...newRes)()

            let toko = res?.ads_merchant?.map((item: any) => item.list.map((x: any) => [x.advert_id, x.id, timeStamp])).map((x: any) => x)
            let newDataToko: any = []
            if (toko) {
              toko.map((c: any) => {
                c.map((t: any) => {
                  newDataToko.push(t)
                })
              })
            }
            adsSaveCache(keyword, data, 'product')
            adsSaveCache(keyword, newDataToko, 'toko')
            setAdsCache(res?.ads_merchant)
            return res
          }}
          ListHeaderComponent={
            <>
              {
                adsCache?.length > 0 && adsCache?.map((item: any, i: number) => (
                  <MarketAds_store_preview key={i} description={item?.description} merchant={{ id: item?.merchant_id, image: item?.merchant_image, title: item?.merchant_name, url: item?.merchant_url }} products={item?.list} />
                ))
              }
            </>
          }
          errorView={(eror: string) => {
            if (eror) {
              return (
                <MarketEmpty_product message={eror} />
              )
            }
          }}
          LoadingView={
            <LibSkeleton backgroundStyle={{ height: LibStyle.height }}>
              <View style={{ flexDirection: 'row', alignItems: 'center', flexWrap: 'wrap', marginLeft: 10 }} >
                {
                  [1, 1, 1, 1].map((item: any, i: number) => (
                    <View key={i} style={{ width: imgDimension, borderWidth: 1, marginRight: 10, marginBottom: 10, borderRadius: 10, overflow: 'hidden' }}>
                      <View style={{ width: imgDimension, height: imgDimension, backgroundColor: 'white' }} />
                      <View style={{ width: '60%', height: 15, borderRadius: 7.5, backgroundColor: 'white', margin: 10 }} />
                      <View style={{ width: '50%', height: 20, borderRadius: 10, backgroundColor: 'white', margin: 10, marginTop: 5, marginBottom: 0 }} />
                      <LibIcon name="heart" style={{ marginHorizontal: 10, marginBottom: 10, alignSelf: 'flex-end' }} />
                    </View>
                  ))
                }
              </View>
            </LibSkeleton>
          }
          injectData={upData}
          renderItem={renderItems}
        />
      </LibLazy>
      <LibSlidingup ref={refFilter} >
        <MarketProduct_list_filter
          sale_min={sale_min}
          sale_max={sale_max}
          onChangeSaleMin={setSale_min}
          onChangeSaleMax={setSale_max}
          sort={sort}
          onChangeSort={setSort}
          conditions={conditions}
          onChangeCondition={setConditions}
          location_id={location_id}
          onChangeLocation={setLocation_id}
          category={product_cat}
          onChangeCategory={setProduct_cat}
          keyword={query}
          close={() => refFilter.current!.hide()} />
      </LibSlidingup>
    </View>
  )
}

