package com.bonus.canteen.core.customer.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.canteen.core.common.constant.LeMqConstant;
import com.bonus.canteen.core.common.utils.JacksonUtil;
import com.bonus.canteen.core.customer.changelog.po.cust.diningplace.po.CustDiningPlacePO;
import com.bonus.canteen.core.customer.constants.CustDiningPlaceTypeEnum;
import com.bonus.canteen.core.customer.mapper.CustDiningPlaceMapper;
import com.bonus.canteen.core.customer.model.CustDiningPlace;
import com.bonus.canteen.core.customer.service.CustDiningPlaceService;
import com.bonus.common.houqin.i18n.I18n;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.invoke.SerializedLambda;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class CustDiningPlaceServiceImpl extends ServiceImpl<CustDiningPlaceMapper, CustDiningPlace> implements CustDiningPlaceService {
   private static final Logger log = LoggerFactory.getLogger(CustDiningPlaceServiceImpl.class);
   @Autowired
   CustDiningPlaceMapper custDiningPlaceMapper;

   @Transactional(
      rollbackFor = {Exception.class}
   )
   public void save(Long custId, JsonNode diningPlace) {
      log.info("就餐地={}", diningPlace);
      if (diningPlace != null && !diningPlace.isNull() && !diningPlace.isEmpty()) {
         List<CustDiningPlace> custDiningPlaceList = convertDiningPlace(custId, diningPlace);
         this.save(custId, custDiningPlaceList);
      }
   }

   protected void save(Long custId, List<CustDiningPlace> custDiningPlaceList) {
      check(custDiningPlaceList);
      this.deleteByCustIds(Collections.singleton(custId), (Collection)null);
      this.insertBatch(custDiningPlaceList);
      this.noticeChange(custId, custDiningPlaceList);
   }

   protected void noticeChange(Long custId, List<CustDiningPlace> custDiningPlaceList) {
 //     List<CustDiningPlacePO.DiningPlace> diningPlaceList = (List)Optional.ofNullable(custDiningPlaceList).map((list) -> {
//         return list.stream().map((custDiningPlace) -> {
//            return (new CustDiningPlacePO.DiningPlace()).setType(custDiningPlace.getType()).setDiningPlaceId(custDiningPlace.getDiningPlaceId());
//         }).toList();
//      }).orElse(new ArrayList());
      List<CustDiningPlacePO.DiningPlace> diningPlaceList = custDiningPlaceList.stream()
              .map(custDiningPlace -> new CustDiningPlacePO.DiningPlace()
                      .setType(custDiningPlace.getType())
                      .setDiningPlaceId(custDiningPlace.getDiningPlaceId()))
              .collect(Collectors.toList());
      CustDiningPlacePO custDiningPlacePO = (new CustDiningPlacePO()).setCustId(custId).setDiningPlaceList(diningPlaceList);
     // MqUtil.sendDataChange(custDiningPlacePO, LeMqConstant.DataChangeType.UPDATE, LeMqConstant.Topic.DATA_CHANGE_CUSTOMER_DINING_PLACE);
   }

   public Map<Long, JsonNode> getDiningPlaceMapByCustIds(Collection<Long> custIds) {
      List<CustDiningPlace> custDiningPlaceList = this.getCustDiningPlaceList(custIds, (Collection)null, (Collection)null);
      return generateMultiDiningPlaceJson(custDiningPlaceList);
   }

   protected static void check(List<CustDiningPlace> custDiningPlaceList) {
      if (1L < custDiningPlaceList.stream().map(CustDiningPlace::getType).filter((s) -> {
         return s.equals(CustDiningPlaceTypeEnum.AREA.getKey());
      }).count()) {
         throw new ServiceException(I18n.getMessage("customer.diningPlace.area.chooseOne", new Object[0]));
      }
   }

   protected static Map<Long, JsonNode> generateMultiDiningPlaceJson(List<CustDiningPlace> custDiningPlaceList) {
      Map<Long, List<CustDiningPlace>> custId_diningPlaceList = (Map)custDiningPlaceList.stream().collect(Collectors.groupingBy(CustDiningPlace::getCustId));
      Map<Long, JsonNode> custId_diningPlaceJson = new HashMap(8);
      custId_diningPlaceList.forEach((custId, custDiningPlaceLists) -> {
         ObjectNode objectNode = generateSingleDiningPlaceJson(custDiningPlaceLists);
         custId_diningPlaceJson.put(custId, objectNode);
      });
      return custId_diningPlaceJson;
   }

   protected static ObjectNode generateSingleDiningPlaceJson(List<CustDiningPlace> custDiningPlaceLists) {
      ObjectNode objectNode = JacksonUtil.objectNode();
      Map<String, List<CustDiningPlace>> type_diningPlace = (Map)custDiningPlaceLists.stream().collect(Collectors.groupingBy(CustDiningPlace::getType));
      CustDiningPlaceTypeEnum[] var3 = CustDiningPlaceTypeEnum.values();
      int var4 = var3.length;

      for(int var5 = 0; var5 < var4; ++var5) {
         CustDiningPlaceTypeEnum placeTypeEnum = var3[var5];
         List<CustDiningPlace> diningPlaceList = (List)type_diningPlace.get(placeTypeEnum.getKey());
         if (CollUtil.isEmpty(diningPlaceList)) {
            objectNode.set(placeTypeEnum.getKey(), JacksonUtil.arrayNode());
         } else {
            List<String> ids = (List)diningPlaceList.stream().map((custDiningPlace) -> {
               return "\"" + custDiningPlace.getDiningPlaceId() + "\"";
            }).collect(Collectors.toList());
            objectNode.set(placeTypeEnum.getKey(), JacksonUtil.readTree(ids.toString()));
         }
      }

      return objectNode;
   }

   protected static List<CustDiningPlace> convertDiningPlace(Long custId, JsonNode diningPlace) {
      List<CustDiningPlace> custDiningPlaceList = new ArrayList();
      CustDiningPlaceTypeEnum[] var3 = CustDiningPlaceTypeEnum.values();
      int var4 = var3.length;

      for(int var5 = 0; var5 < var4; ++var5) {
         CustDiningPlaceTypeEnum placeTypeEnum = var3[var5];
         ArrayList<Long> diningPlaceIds = (ArrayList)JacksonUtil.treeToValue(diningPlace.path(placeTypeEnum.getKey()), new TypeReference<ArrayList<Long>>() {
         });
         custDiningPlaceList.addAll(generateDiningPlaceList(Collections.singleton(custId), diningPlaceIds, placeTypeEnum));
      }

      return custDiningPlaceList;
   }

   public static List<CustDiningPlace> generateDiningPlaceList(Collection<Long> custIds, Collection<Long> diningPlaceIds, CustDiningPlaceTypeEnum custDiningPlaceTypeEnum) {
//      return (List)(!CollUtil.isEmpty(custIds) && !CollUtil.isEmpty(diningPlaceIds) && !ObjectUtil.isNull(custDiningPlaceTypeEnum) ? (List)custIds.stream().map((custId) -> {
//         return diningPlaceIds.stream().map((diningPlaceId) -> {
//            return (new CustDiningPlace()).setCustId(custId).setDiningPlaceId(diningPlaceId).setType(custDiningPlaceTypeEnum.getKey()).setHalfSelect(1);
//         }).toList();
//      }).flatMap(Collection::stream).collect(Collectors.toList()) : new ArrayList());
      if (CollUtil.isEmpty(custIds) || CollUtil.isEmpty(diningPlaceIds) || ObjectUtil.isNull(custDiningPlaceTypeEnum)) {
         return new ArrayList<>();
      }
      return custIds.stream()
              .flatMap(custId -> diningPlaceIds.stream()
                      .map(diningPlaceId -> new CustDiningPlace()
                              .setCustId(custId)
                              .setDiningPlaceId(diningPlaceId)
                              .setType(custDiningPlaceTypeEnum.getKey())
                              .setHalfSelect(1)))
              .collect(Collectors.toList());
   }

   public void insertBatch(List<CustDiningPlace> custDiningPlaceList) {
      if (!CollUtil.isEmpty(custDiningPlaceList)) {
         this.saveBatch(custDiningPlaceList);
      }
   }

   public void deleteByCustIds(Collection<Long> custIds, Collection<Long> diningPlaceIds) {
//      if (!CollUtil.isEmpty(custIds) || !CollUtil.isEmpty(diningPlaceIds)) {
//         this.custDiningPlaceMapper.delete(((LambdaQueryWrapper)Wrappers.lambdaQuery(CustDiningPlace.class).in(CollUtil.isNotEmpty(custIds), CustDiningPlace::getCustId, custIds)).in(CollUtil.isNotEmpty(diningPlaceIds), CustDiningPlace::getDiningPlaceId, diningPlaceIds));
//      }
      if (CollUtil.isNotEmpty(custIds) || CollUtil.isNotEmpty(diningPlaceIds)) {
         LambdaQueryWrapper<CustDiningPlace> queryWrapper = Wrappers.lambdaQuery(CustDiningPlace.class)
                 .in(CollUtil.isNotEmpty(custIds), CustDiningPlace::getCustId, custIds)
                 .in(CollUtil.isNotEmpty(diningPlaceIds), CustDiningPlace::getDiningPlaceId, diningPlaceIds);
         this.custDiningPlaceMapper.delete(queryWrapper);
      }
   }

   public List<Long> listCustIdByHaveDiningPlace(Long diningPlaceId, CustDiningPlaceTypeEnum custDiningPlaceTypeEnum) {
     // return (List)this.getCustDiningPlaceList((Collection)null, Collections.singleton(diningPlaceId), Collections.singleton(custDiningPlaceTypeEnum)).stream().map(CustDiningPlace::getCustId).collect(Collectors.toList());
      return this.getCustDiningPlaceList(null, Collections.singleton(diningPlaceId), Collections.singleton(custDiningPlaceTypeEnum))
              .stream()
              .map(CustDiningPlace::getCustId)
              .collect(Collectors.toList());
   }

   public List<CustDiningPlace> getCustDiningPlaceList(Collection<Long> custIds, Collection<Long> diningPlaceIds, Collection<CustDiningPlaceTypeEnum> custDiningPlaceTypeEnums) {
      List<String> typeList = new ArrayList();
      if (CollUtil.isNotEmpty(custDiningPlaceTypeEnums)) {
         typeList = (List)custDiningPlaceTypeEnums.stream().map(CustDiningPlaceTypeEnum::getKey).collect(Collectors.toList());
      }


      return this.custDiningPlaceMapper.selectList(Wrappers.lambdaQuery(CustDiningPlace.class)
              .eq(CustDiningPlace::getHalfSelect, 1)
              .in(CollUtil.isNotEmpty(custIds), CustDiningPlace::getCustId, custIds)
              .in(CollUtil.isNotEmpty(diningPlaceIds), CustDiningPlace::getDiningPlaceId, diningPlaceIds)
              .in(CollUtil.isNotEmpty(typeList), CustDiningPlace::getType, typeList));
      //return this.custDiningPlaceMapper.selectList(((LambdaQueryWrapper)((LambdaQueryWrapper)((LambdaQueryWrapper)Wrappers.lambdaQuery(CustDiningPlace.class).eq(CustDiningPlace::getHalfSelect, 1)).in(CollUtil.isNotEmpty(custIds), CustDiningPlace::getCustId, custIds)).in(CollUtil.isNotEmpty(diningPlaceIds), CustDiningPlace::getDiningPlaceId, diningPlaceIds)).in(CollUtil.isNotEmpty((Collection)typeList), CustDiningPlace::getType, (Collection)typeList));
   
   }

   // $FF: synthetic method
//   private static Object $deserializeLambda$(SerializedLambda lambda) {
//      switch (lambda.getImplMethodName()) {
//         case "getDiningPlaceId":
//            if (lambda.getImplMethodKind() == 5 && lambda.getFunctionalInterfaceClass().equals("com/baomidou/mybatisplus/core/toolkit/support/SFunction") && lambda.getFunctionalInterfaceMethodName().equals("apply") && lambda.getFunctionalInterfaceMethodSignature().equals("(Ljava/lang/Object;)Ljava/lang/Object;") && lambda.getImplClass().equals("net/xnzn/core/customer/model/CustDiningPlace") && lambda.getImplMethodSignature().equals("()Ljava/lang/Long;")) {
//               return CustDiningPlace::getDiningPlaceId;
//            }
//
//            if (lambda.getImplMethodKind() == 5 && lambda.getFunctionalInterfaceClass().equals("com/baomidou/mybatisplus/core/toolkit/support/SFunction") && lambda.getFunctionalInterfaceMethodName().equals("apply") && lambda.getFunctionalInterfaceMethodSignature().equals("(Ljava/lang/Object;)Ljava/lang/Object;") && lambda.getImplClass().equals("net/xnzn/core/customer/model/CustDiningPlace") && lambda.getImplMethodSignature().equals("()Ljava/lang/Long;")) {
//               return CustDiningPlace::getDiningPlaceId;
//            }
//            break;
//         case "getType":
//            if (lambda.getImplMethodKind() == 5 && lambda.getFunctionalInterfaceClass().equals("com/baomidou/mybatisplus/core/toolkit/support/SFunction") && lambda.getFunctionalInterfaceMethodName().equals("apply") && lambda.getFunctionalInterfaceMethodSignature().equals("(Ljava/lang/Object;)Ljava/lang/Object;") && lambda.getImplClass().equals("net/xnzn/core/customer/model/CustDiningPlace") && lambda.getImplMethodSignature().equals("()Ljava/lang/String;")) {
//               return CustDiningPlace::getType;
//            }
//            break;
//         case "getHalfSelect":
//            if (lambda.getImplMethodKind() == 5 && lambda.getFunctionalInterfaceClass().equals("com/baomidou/mybatisplus/core/toolkit/support/SFunction") && lambda.getFunctionalInterfaceMethodName().equals("apply") && lambda.getFunctionalInterfaceMethodSignature().equals("(Ljava/lang/Object;)Ljava/lang/Object;") && lambda.getImplClass().equals("net/xnzn/core/customer/model/CustDiningPlace") && lambda.getImplMethodSignature().equals("()Ljava/lang/Integer;")) {
//               return CustDiningPlace::getHalfSelect;
//            }
//            break;
//         case "getCustId":
//            if (lambda.getImplMethodKind() == 5 && lambda.getFunctionalInterfaceClass().equals("com/baomidou/mybatisplus/core/toolkit/support/SFunction") && lambda.getFunctionalInterfaceMethodName().equals("apply") && lambda.getFunctionalInterfaceMethodSignature().equals("(Ljava/lang/Object;)Ljava/lang/Object;") && lambda.getImplClass().equals("net/xnzn/core/customer/model/CustDiningPlace") && lambda.getImplMethodSignature().equals("()Ljava/lang/Long;")) {
//               return CustDiningPlace::getCustId;
//            }
//
//            if (lambda.getImplMethodKind() == 5 && lambda.getFunctionalInterfaceClass().equals("com/baomidou/mybatisplus/core/toolkit/support/SFunction") && lambda.getFunctionalInterfaceMethodName().equals("apply") && lambda.getFunctionalInterfaceMethodSignature().equals("(Ljava/lang/Object;)Ljava/lang/Object;") && lambda.getImplClass().equals("net/xnzn/core/customer/model/CustDiningPlace") && lambda.getImplMethodSignature().equals("()Ljava/lang/Long;")) {
//               return CustDiningPlace::getCustId;
//            }
//      }
//
//      throw new IllegalArgumentException("Invalid lambda deserialization");
//   }
}
