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

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
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.constant.LeConstants;
import com.bonus.core.customer.constants.CustConstant;
import com.bonus.core.customer.constants.PersonalStatusEnum;
import com.bonus.core.customer.dto.AddPsnTypeDTO;
import com.bonus.core.customer.dto.UpdatePsnTypeDTO;
import com.bonus.core.customer.mapper.CustPsnTypeMapper;
import com.bonus.core.customer.model.CustInfo;
import com.bonus.core.customer.model.CustPsnType;
import com.bonus.core.customer.service.CustInfoService;
import com.bonus.core.customer.service.CustPsnTypeService;
import com.bonus.core.customer.vo.PsnTypeBacisInfoVO;
import com.bonus.i18n.I18n;
import com.bonus.utils.LeBeanUtil;
import com.bonus.utils.RetCodeEnum;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;

@Service
public class CustPsnTypeServiceImpl extends ServiceImpl<CustPsnTypeMapper, CustPsnType> implements CustPsnTypeService {

   @Resource
   private CustInfoService custInfoService;

   public PsnTypeBacisInfoVO getPsnTypeBasicInfoVO(Integer psnType) {
      //return PsnTypeBacisInfoVO.custPsnType2PsnTypeBacisInfoVO((CustPsnType)((CustPsnTypeMapper)this.baseMapper).selectOne((Wrapper)((LambdaQueryWrapper)Wrappers.lambdaQuery(CustPsnType.class).select(new SFunction[]{CustPsnType::getId, CustPsnType::getPsnType, CustPsnType::getPsnTypeName}).eq(CustPsnType::getPsnType, psnType)).eq(CustPsnType::getDelFlag, LeConstants.COMMON_NO)));
      return PsnTypeBacisInfoVO.custPsnType2PsnTypeBacisInfoVO(
              this.baseMapper.selectOne(
                      Wrappers.lambdaQuery(CustPsnType.class)
                              .select(CustPsnType::getId, CustPsnType::getPsnType, CustPsnType::getPsnTypeName)
                              .eq(CustPsnType::getPsnType, psnType)
                              .eq(CustPsnType::getDelFlag, LeConstants.COMMON_NO)
              )
      );
   }

   @Override
   public String insertOrUpdatePsnType(Integer psnType, String psnTypeName) {
      if (ObjectUtil.isNull(psnType)) {
         return "";
      } else {
         PsnTypeBacisInfoVO psnTypeBasicInfoVO = this.getPsnTypeBasicInfoVO(psnType);
         String actualPsnTypeName = CharSequenceUtil.isBlank(psnTypeName) ? this.getDefaultPsnTypeName(psnType) : psnTypeName;
         if (ObjectUtil.isNull(psnTypeBasicInfoVO)) {
            AddPsnTypeDTO addPsnTypeDTO = (new AddPsnTypeDTO()).setPsnType(psnType).setPsnTypeName(actualPsnTypeName);
            this.addPsnType(addPsnTypeDTO);
         } else if (CharSequenceUtil.isNotBlank(psnTypeName) && !psnTypeName.equals(psnTypeBasicInfoVO.getPsnTypeName())) {
            UpdatePsnTypeDTO updatePsnTypeDTO = (new UpdatePsnTypeDTO()).setId(psnTypeBasicInfoVO.getId()).setPsnType(psnType).setPsnTypeName(psnTypeName);
            this.updatePsnTypeById(updatePsnTypeDTO);
         }

         return actualPsnTypeName;
      }
   }

   public void updatePsnTypeById(UpdatePsnTypeDTO param) {
      this.check(param.getId(), param.getPsnType(), param.getPsnTypeName());
      CustPsnType custPsnType = (CustPsnType) LeBeanUtil.copyCreateProperties(param, CustPsnType.class);
      this.updateOneById(custPsnType);
     // this.custInfoService
      // .update((Wrapper)((LambdaUpdateWrapper)((LambdaUpdateWrapper)Wrappers
      // .lambdaUpdate(CustInfo.class)
      // .set(CustInfo::getPsnTypeName, param.getPsnTypeName()))
      // .eq(CustInfo::getCustState, PersonalStatusEnum.NORMAL.getKey()))
      // .eq(CustInfo::getPsnType, param.getPsnType()));
      this.custInfoService.update(
              Wrappers.lambdaUpdate(CustInfo.class)
                      .set(CustInfo::getPsnTypeName, param.getPsnTypeName())
                      .eq(CustInfo::getCustState, PersonalStatusEnum.NORMAL.getKey())
                      .eq(CustInfo::getPsnType, param.getPsnType())
      );

   }

   protected String getDefaultPsnTypeName(Integer psnType) {
      return "类别" + psnType;
   }

   protected void updateOneById(CustPsnType custPsnType) {
      ((CustPsnTypeMapper)this.baseMapper).update(custPsnType, (Wrapper)Wrappers.lambdaQuery(CustPsnType.class).eq(CustPsnType::getId, custPsnType.getId()));
   }

   public CustPsnType addPsnType(AddPsnTypeDTO param) {
      this.check((Long)null, param.getPsnType(), param.getPsnTypeName());
      CustPsnType psnType = (new CustPsnType()).setPsnType(param.getPsnType()).setPsnTypeName(param.getPsnTypeName());
      this.add(psnType);
      return psnType;
   }

   protected void check(Long id, @NotNull Integer psnType, String psnTypeName) {
      if (notInPsnTypeRange(psnType)) {
         throw new ServiceException(I18n.getMessage("customer.psnType.id.outOfRange", new Object[0]));
      } else if (this.existsRepeatedPsnTypeOrName(id, psnType, psnTypeName)) {
         throw new ServiceException(RetCodeEnum.CORE_IMPORT_EMPTY+":"+I18n.getMessage("customer.psnType.idOrName.exists", new Object[0]));
      }
   }

   protected void add(CustPsnType psnType) {
      ((CustPsnTypeMapper)this.baseMapper).insert(psnType);
   }
   protected boolean existsRepeatedPsnTypeOrName(Long excludeId, @NotNull Integer psnType, String psnTypeName) {
//      return ((CustPsnTypeMapper)this.baseMapper).exists((Wrapper)((LambdaQueryWrapper)((LambdaQueryWrapper)Wrappers.lambdaQuery().eq(CustPsnType::getDelFlag, LeConstants.COMMON_NO)).ne(ObjectUtil.isNotNull(excludeId), CustPsnType::getId, excludeId)).and((i) -> {
//         ((LambdaQueryWrapper)((LambdaQueryWrapper)i.eq(CustPsnType::getPsnType, psnType)).or()).eq(CharSequenceUtil.isNotBlank(psnTypeName), CustPsnType::getPsnTypeName, psnTypeName);
//      }));
      return this.baseMapper.exists(
              Wrappers.lambdaQuery(CustPsnType.class)
                      .eq(CustPsnType::getDelFlag, LeConstants.COMMON_NO)
                      .ne(ObjectUtil.isNotNull(excludeId), CustPsnType::getId, excludeId)
                      .and(i -> i.eq(CustPsnType::getPsnType, psnType)
                              .or()
                              .eq(CharSequenceUtil.isNotBlank(psnTypeName), CustPsnType::getPsnTypeName, psnTypeName))
      );
   }


   public static boolean notInPsnTypeRange(Integer psnType) {
      return psnType < CustConstant.PSN_TYPE_MIN || psnType > CustConstant.PSN_TYPE_MAX;
   }

}
