package com.izouma.nineth.service;

import com.alibaba.fastjson.JSONArray;
import com.izouma.nineth.config.Constants;
import com.izouma.nineth.domain.Asset;
import com.izouma.nineth.domain.Collection;
import com.izouma.nineth.dto.PageQuery;
import com.izouma.nineth.dto.PageWrapper;
import com.izouma.nineth.dto.UserHoldDTO;
import com.izouma.nineth.enums.AssetStatus;
import com.izouma.nineth.repo.AssetRepo;
import com.izouma.nineth.repo.CollectionRepo;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

@Service
@AllArgsConstructor
public class UserHoldCountService {

    private AssetRepo assetRepo;

    private CollectionRepo collectionRepo;

    @Cacheable(value = "userHoldList", key = "#pageQuery.hashCode()")
    public PageWrapper<UserHoldDTO> all(PageQuery pageQuery) {
        int page = pageQuery.getPage();
        int size = pageQuery.getSize();
        int start = page * size;
        Map<String, BigDecimal> minPriceMap = new HashMap<>();
        int totalElements = assetRepo.totalElements();
        List<Map<String, String>> assets = assetRepo.findByPage(start, size);
        JSONArray jsonArray = new JSONArray();
        jsonArray.addAll(assets);
        List<UserHoldDTO> userHoldDTOS = jsonArray.toJavaList(UserHoldDTO.class);
        userHoldDTOS.forEach(userHoldDTO -> {
            List<Asset> userAssets = assetRepo.findAllByUserIdAndStatusIn(userHoldDTO.getUserId(), new ArrayList<>(Arrays.asList(AssetStatus.NORMAL, AssetStatus.TRADING, AssetStatus.GIFTING, AssetStatus.MINTING, AssetStatus.AUCTIONING)));
            // 分类计算各资产寄售最低价
            userAssets.forEach(asset -> {
                if (StringUtils.isBlank(asset.getPrefixName())) {
                    return;
                }
                if (asset.getName().contains(Constants.Rarity.SR_LIKE) && !asset.getName().contains(Constants.Rarity.SSR_LIKE)) {
                    calculatePrice(userHoldDTO, asset, minPriceMap, Constants.Rarity.SR_LIKE, Constants.Rarity.SSR_LIKE);
                    return;
                }
                if (asset.getName().contains(Constants.Rarity.U_LIKE)) {
                    calculatePrice(userHoldDTO, asset, minPriceMap, Constants.Rarity.U_LIKE, Constants.Rarity.R_LIKE);
                    return;
                }
                if (asset.getName().contains(Constants.Rarity.R_LIKE) && !asset.getName().contains(Constants.Rarity.SR_LIKE)) {
                    calculatePrice(userHoldDTO, asset, minPriceMap, Constants.Rarity.R_LIKE, Constants.Rarity.SR_LIKE);
                    return;
                }
                if (asset.getName().contains(Constants.Rarity.SSR_LIKE)) {
                    calculatePrice(userHoldDTO, asset, minPriceMap, Constants.Rarity.SSR_LIKE, Constants.Rarity.U_LIKE);
                    return;
                }
                calculatePrice(userHoldDTO, asset, minPriceMap, null, null);
            });
        });
        return new PageWrapper<>(userHoldDTOS, page,
                size, totalElements);
    }

    private void calculatePrice(UserHoldDTO userHoldDTO, Asset asset, Map<String, BigDecimal> minPriceMap, String nameLike, String nameNotLike) {
        BigDecimal minPrice;
        String minPriceMapKey = StringUtils.isBlank(nameLike) ? asset.getPrefixName() : asset.getPrefixName().concat(nameLike);
        if (minPriceMap.containsKey(minPriceMapKey)) {
            minPrice = minPriceMap.get(minPriceMapKey);
        } else {
            // 该系列寄售最低价
            if (StringUtils.isBlank(nameLike)) {
                minPrice = collectionRepo.findMinPriceByPrefixName(asset.getPrefixName());
            } else {
                minPrice = collectionRepo.findMinPriceByNameAndPrefixName(asset.getPrefixName(), nameLike, nameNotLike);
            }
            // 该系列没有寄售的话取originalPrice
            if(Objects.isNull(minPrice)) {
                Collection collection = collectionRepo.findById(asset.getCollectionId()).orElse(null);
                if (Objects.isNull(collection)) {
                    minPrice = BigDecimal.ZERO;
                } else {
                    minPrice = collection.getOriginalPrice();
                }
            }
//            minPrice = Objects.isNull(minPrice) ? BigDecimal.ZERO : minPrice;
            minPriceMap.put(minPriceMapKey, minPrice);
        }
        userHoldDTO.setPrice(userHoldDTO.getPrice().add(minPrice));
    }

}
