package com.neusoft.smart.pos.member.service;

import com.neusoft.smart.pos.dto.member.request.MemberCardChangeRequest;
import com.neusoft.smart.pos.dto.member.request.UpdateCardPointRequest;
import com.neusoft.smart.pos.framework.exception.BusinessCommonException;
import com.neusoft.smart.pos.framework.utils.BeanUtil;
import com.neusoft.smart.pos.framework.utils.IdGenerateUtils;
import com.neusoft.smart.pos.member.constants.MemberErrorCode;
import com.neusoft.smart.pos.member.persistent.domain.*;
import com.neusoft.smart.pos.member.persistent.mapper.MemberCardMapper;
import com.neusoft.smart.pos.member.persistent.mapper.MemberCardRelationMapper;
import com.neusoft.smart.pos.member.persistent.mapper.MemberWithCardMapper;
import com.neusoft.smart.pos.utils.RequestHeaderUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Random;

@Service
public class MemberCardService {
	@Autowired
	private PasswordEncoder passwordEncoder;
	
	@Autowired
	private MemberWithCardMapper memberWithCardMapper;
	
	@Autowired
	private MemberCardRelationMapper memberCardRelationMapper;
	
	
	@Autowired
	private MemberCardMapper memberCardMapper;
	
	public void validateByCardNum(String cardNum) {
		MemberWithCardExample memberWithCardExample = new MemberWithCardExample();
		memberWithCardExample.createCriteria().andCardNumEqualTo(cardNum);
		MemberWithCard memberWithCard = memberWithCardMapper.selectByExample(memberWithCardExample).stream().filter(card -> card.getCardActive().equals(1)).findAny().orElse(null);
		if (null != memberWithCard) {
			throw new BusinessCommonException(MemberErrorCode.MEMBER_CARD_NUM_DUPLICATE);
		}
	}
	
	@Transactional
	public String changeCard(MemberCardChangeRequest memberCardChangeRequest) {
		MemberWithCardExample memberWithCardExample = new MemberWithCardExample();
		memberWithCardExample.createCriteria().andMemberIdEqualTo(memberCardChangeRequest.getMemberId());
		MemberWithCard memberWithCard = memberWithCardMapper.selectByExample(memberWithCardExample).stream().filter(card -> card.getCardActive().equals(1)).findAny().orElse(null);
		if (StringUtils.isEmpty(memberCardChangeRequest.getCardNum())) {
			memberCardChangeRequest.setCardNum(generateCardNum());
		}
		//没有可用的会员卡
		if (null != memberWithCard) {
			MemberCard memberCard = new MemberCard();
			memberCard.setCardNum(memberCardChangeRequest.getCardNum());
			memberCard.setCardHidCode(memberCardChangeRequest.getCardHidCode());
			memberCard.setMemberId(memberCardChangeRequest.getMemberId());

			memberCardMapper.insertSelective(memberCard);
			
			this.createRelation(memberCardChangeRequest.getMemberId(), memberCard.getCardId());
		} else {
			//新插入一张会员卡
			MemberCard memberCard = memberCardMapper.selectByPrimaryKey(memberWithCard.getCardId());
			MemberCard newMemberCard = new MemberCard();
			BeanUtils.copyProperties(memberCard, newMemberCard, "cardId", "cardNum", "version", "createdTime", "createdBy", "updatedTime",
					"updatedBy");
			newMemberCard.setCreatedBy(RequestHeaderUtil.getUserId()+"");
			newMemberCard.setCreatedTime(new Date());
			newMemberCard.setCardNum(memberCardChangeRequest.getCardNum());
			memberCardMapper.insertSelective(newMemberCard);
			
			this.createRelation(memberCardChangeRequest.getMemberId(), newMemberCard.getCardId());
			
			//更新下原始会员卡数据
			memberCard.setCardBalance(BigDecimal.valueOf(0));
			memberCard.setCardPoint(0);
			memberCard.setIsActive(0);
			memberCardMapper.updateByPrimaryKey(memberCard);
		}
		
		return memberCardChangeRequest.getCardNum();
		
	}
	
	public MemberCard createMemberCard(MemberCard memberCard) {
		if(memberCard.isNeedPwd()) {
			memberCard.setCardPassword(passwordEncoder.encode(memberCard.getCardPassword()));
		} else {
			memberCard.setCardPassword("");
		}

		MemberWithCard memberWithCard = null;
		if (StringUtils.isEmpty(memberCard.getCardNum())) {
			memberCard.setCardNum(generateCardNum());
		} else{
			MemberWithCardExample memberWithCardExample = new MemberWithCardExample();
			memberWithCardExample.createCriteria().andCardNumEqualTo(memberCard.getCardNum());
			memberWithCard = memberWithCardMapper.selectByExample(memberWithCardExample).stream().filter(card -> card.getCardActive().equals(1)).findAny().orElse(null);
		}

		if (memberWithCard != null) {
			MemberCardRelationExample memberCardRelationExample = new MemberCardRelationExample();
			memberCardRelationExample.createCriteria().andCardIdEqualTo(memberWithCard.getCardId());
			if (memberCardRelationMapper.countByExample(memberCardRelationExample) > 0) {
				throw new BusinessCommonException(MemberErrorCode.MEMBER_CARD_BOUNDED);
			}
			memberCard.setCardId(memberWithCard.getCardId());
			memberCardMapper.updateByPrimaryKey(memberCard);
		} else {
			memberCardMapper.insertSelective(memberCard);
		}

		return memberCard;
	}
	
	public String generateCardNum() {
		return IdGenerateUtils.generateMemberCardNum();
	}
	
	public void updateCardPoint(UpdateCardPointRequest request) {
		MemberCardExample example = new MemberCardExample();
		example.createCriteria().andCardNumEqualTo(request.getCardNum()).andIsActiveEqualTo(1);
		
		List<MemberCard> result = memberCardMapper.selectByExample(example);
		if (result.size() == 0) {
			throw new BusinessCommonException(MemberErrorCode.MEMBER_CARD_NOT_EXIST);
		}
		
		MemberCard memberCard = new MemberCard();
		BeanUtils.copyProperties(result.get(0), memberCard, "cardId", "cardPoint");
		
		memberCard.setCardPoint(memberCard.getCardPoint() + request.getCardPoint());
		memberCardMapper.updateByPrimaryKeySelective(memberCard);
	}
	
	private void createRelation(Integer memberId, Integer cardId) {
		MemberCardRelation memberCardRelation = new MemberCardRelation();
		memberCardRelation.setMemberId(memberId);
		memberCardRelation.setCardId(cardId);
		memberCardRelationMapper.insertSelective(memberCardRelation);
	}
	
}
