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

import com.neusoft.smart.pos.card.constants.CardErrorCode;
import com.neusoft.smart.pos.card.persistent.domain.Card;
import com.neusoft.smart.pos.card.persistent.mapper.CardMapper;
import com.neusoft.smart.pos.dto.member.request.CreateMemberRequest;
import com.neusoft.smart.pos.dto.member.request.GetMembersRequest;
import com.neusoft.smart.pos.dto.member.request.UpdateMemberRequest;
import com.neusoft.smart.pos.dto.member.response.DetailedMemberResponse;
import com.neusoft.smart.pos.dto.member.response.GetMembersResponse;
import com.neusoft.smart.pos.framework.exception.BusinessCommonException;
import com.neusoft.smart.pos.framework.task.TaskExecutor;
import com.neusoft.smart.pos.framework.utils.DateUtils;
import com.neusoft.smart.pos.member.constants.MemberErrorCode;
import com.neusoft.smart.pos.member.persistent.domain.*;
import com.neusoft.smart.pos.member.persistent.mapper.MemberMapper;
import com.neusoft.smart.pos.member.persistent.mapper.MemberWithCardMapper;
import com.neusoft.smart.pos.member.task.MemberRedisTask;
import com.neusoft.smart.pos.utils.RequestHeaderUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@EnableTransactionManagement
@Service
public class Member4CanteenService extends MemberService {
	
	@Resource
	private CardMapper cardMapper;
	
	@Resource
	MemberMapper memberMapper;
	
	@Resource
	MemberWithCardMapper memberWithCardMapper;
	
	@Autowired
	private TaskExecutor taskExecutor;


	public GetMembersResponse getMembers(GetMembersRequest request) {
		GetMembersResponse resp = new GetMembersResponse();
		List<Integer> memberIds = new ArrayList<>();
		if (!StringUtils.isEmpty(request.getCardNum())) {
			try {
				Integer cardId = cardService.getCardByCardNum(request.getCardNum()).getCardId();
				List<MemberCardRelation> memberCardRelation = getMemberCardRelationsByCardId(cardId);

				memberCardRelation.stream().forEach(a -> {
					if (!StringUtils.isEmpty(a.getMemberId()))
						memberIds.add(a.getMemberId());
				});
			} catch (BusinessCommonException e) {
				resp.setTotal(0);
				return resp;
			}
		}

		MemberExample example = new MemberExample();
		MemberExample.Criteria criteria = example.createCriteria();
		Integer limit = request.getLimit() != null ? request.getLimit() : 10;
		Integer offset = request.getOffset() != null ? request.getOffset() : 0;
		
		example.page(offset, limit);
		example.setOrderByClause("m.member_id desc");
		
		switch (RequestHeaderUtil.getRole()) {
			case "sa":
				criteria.andMemberOrgIdEqualTo(request.getOrg());
				if (request.getOrg() == null) {
					throw new BusinessCommonException(MemberErrorCode.NO_ORG_PROVIDED);
				}
				break;
			case "admin":
			case "user":
				criteria.andMemberOrgIdEqualTo(RequestHeaderUtil.getOrgId());
				break;
			default:
				throw new BusinessCommonException(MemberErrorCode.UNKNOWN_USER_ROLE);
		}
		
		if (request.getOrgMember() != null && request.getOrgMember() == 1) {
			criteria.andMemberStoreIdEqualTo(0);
		} else if (request.getStore() != null) {
			criteria.andMemberStoreIdEqualTo(request.getStore());
		} else {
			throw new BusinessCommonException(MemberErrorCode.NO_STORE_PROVIDED);
		}
		
		if (!StringUtils.isEmpty(request.getName())) criteria.andMemberNameLike("%" + request.getName() + "%");
		if (!StringUtils.isEmpty(request.getMobile())) criteria.andMemberMobileEqualTo(request.getMobile());
		if (!StringUtils.isEmpty(request.getMemberCode())) criteria.andMemberCodeEqualTo(request.getMemberCode());
		if (!StringUtils.isEmpty(request.getMemberEmail())) criteria.andMemberEmailEqualTo(request.getMemberEmail());
		//实际业务中一个card只可能有一个member
		if (memberIds.size() > 0) criteria.andMemberIdIn(memberIds);

		resp.setTotal(memberMapper.countByExample(example));
		
		List<DetailedMemberResponse> l = new ArrayList<>();
		for (Member member : memberMapper.selectByExample(example)) {
			DetailedMemberResponse r = new DetailedMemberResponse();
			l.add(fillDetailedMemberResponse(r, member));
		}
		resp.setData(l);
		
		return resp;
	}

	public DetailedMemberResponse getSingleMember(String mobile, String cardNum, Integer org, Integer store) {
		Member mobileMember = null;

		if (StringUtils.isEmpty(mobile) && StringUtils.isEmpty(mobile) && StringUtils.isEmpty(mobile)) {
			throw new BusinessCommonException(MemberErrorCode.NO_CARD_NUM_OR_MOBILE_PROVIDED);
		} else {//参数完整
			if (!StringUtils.isEmpty(mobile)) {
				MemberExample example = new MemberExample();
				MemberExample.Criteria criteria = example.createCriteria();
				criteria.andMemberOrgIdEqualTo(org);
				criteria.andMemberStoreIdEqualTo(store);
				criteria.andIsActiveEqualTo(1);
				criteria.andMemberMobileEqualTo(mobile);
				List<Member> result = memberMapper.selectByExample(example);
				if (result.size() == 0) {
					throw new BusinessCommonException(MemberErrorCode.MEMBER_NOT_FOUND);
				} else {
					mobileMember = result.get(0);
				}
			}
		}

		//从卡获取会员 检查并返回结果
		Card card = cardService.getSingleCard(cardNum, null, null, null, null, null);
		if(card == null) {
			throw new BusinessCommonException(CardErrorCode.CARD_NOT_EXIST);
		}
		List<MemberCardRelation> relations = getMemberCardRelationsByCardId(card.getCardId());
		if (relations.size() == 0) {
			if (mobileMember == null) {//没给电话 卡也找不到会员, 就是一张没绑会员的卡
				return null;
			} else {//电话找到会员  卡找不到会员, 按电话会员算
				return fillDetailedMemberResponse(new DetailedMemberResponse(), mobileMember);
			}
		} else {
			if (mobileMember == null) {//没给电话 卡找到会员了
				return getMemberById(relations.get(0).getMemberId());
			} else {//电话找到会员 卡也找到会员
				if (relations.get(0).getMemberId() == mobileMember.getMemberId()) {
					return fillDetailedMemberResponse(new DetailedMemberResponse(), mobileMember);
				} else {
					throw new BusinessCommonException(MemberErrorCode.NOT_YOUR_CARD);
				}
			}
		}

	}

	//TODO: 需要更新到新表结构
	@Transactional
	public DetailedMemberResponse createMember(CreateMemberRequest request) {
		memberValidate(request);
		MemberWithCardExample memberWithCardExample = new MemberWithCardExample();
		Integer orgId = RequestHeaderUtil.getOrgId();
		MemberWithCardExample.Criteria criteria = memberWithCardExample.createCriteria().andCardActiveIn(Arrays.asList(1, 2)).andMemberOrgIdEqualTo(orgId);
		if (request.getMemberType().equals(0)) {
			criteria.andMemberCodeEqualTo(request.getMemberCode());
		} else {
			criteria.andCardNumEqualTo(request.getCardNum());
			request.setMemberCode(DateUtils.getTimestampString());
		}
		
		//有效卡和冻结卡 不可创建
		if (memberWithCardMapper.countByExample4Canteen(memberWithCardExample) > 0) {
			throw new BusinessCommonException(MemberErrorCode.CANTEEN_MEMBER_EXISTS);
		}
		
		Member member = new Member();
		
		MemberExample example = new MemberExample();
		example.createCriteria().andMemberCodeEqualTo(request.getMemberCode());
		List<Member> tempList = memberMapper.selectByExample(example);
		if (!tempList.isEmpty()) {
			member = tempList.get(0);
			member.setIsActive(1);
			member.setUpdatedBy(RequestHeaderUtil.getUserId() + "");
			memberMapper.updateByPrimaryKeySelective(member);
		} else {
			BeanUtils.copyProperties(request, member);
			//如果员工卡号是空的 给个默认的
			if (StringUtils.isEmpty(member.getMemberCode())) {
				member.setMemberCode(DateUtils.getTimestampString());
			}
			member.setMemberName(request.getName());
			member.setMemberOrgId(orgId);
			member.setMemberStoreId(request.getStore());
			member.setCreatedBy(RequestHeaderUtil.getUserId() + "");
			memberMapper.insertSelective(member);
		}
		
		Card card = new Card();
		card.setCardNum(request.getCardNum());
//		card.setCardPassword(request.getCardPassword());
		card.setCardOtherId(request.getCardHidCode());
		card.setCardBalance(0L);
		card.setCardPoint(0);
		card.setIsActive(1);
		card.setCreatedBy(RequestHeaderUtil.getUserId() + "");
		card.setBeanName("");

		cardMapper.insertSelective(card);
		
		Member temp = memberMapper.selectByPrimaryKey(member.getMemberId());
		MemberWithCard memberWithCard = new MemberWithCard();
		BeanUtils.copyProperties(temp, memberWithCard);
		Card tempC = cardMapper.selectByPrimaryKey(card.getCardId());
		memberWithCard.setCardActive(tempC.getIsActive());
		memberWithCard.setCardBalance(tempC.getCardBalance());
		memberWithCard.setCardOtherId(tempC.getCardOtherId());
		memberWithCard.setCardId(tempC.getCardId());
		memberWithCard.setCardNum(tempC.getCardNum());
		memberWithCard.setCardPoint(tempC.getCardPoint());
		memberWithCard.setLastRechargeAmount(tempC.getLastRechargeAmount());
		
		//跟新一下缓存
		DetailedMemberResponse detailedMemberResponse = fillDetailedMemberResponse(new DetailedMemberResponse(), memberWithCard);
		MemberRedisTask memberRedisTask = new MemberRedisTask();
		memberRedisTask.setDetailedMemberResponse(detailedMemberResponse);
		taskExecutor.getExecutorService().submit(memberRedisTask);
		return detailedMemberResponse;
	}
	
	@Override
	protected void memberValidate(CreateMemberRequest request) {
		String msg = "";
//		if (null == request.getOrg()) {
//			msg += "集团id不可为空|";
//		}
		if (StringUtils.isEmpty(request.getName())) {
			msg += "员工姓名不可为空|";
		}
		if (null == request.getMemberType()) {
			msg += "员工类型不可为空|";
		}
//		if (StringUtils.isEmpty(request.getCardNum())) {
//			msg += "员工印刷卡号不可为空|";
//		}
		if (StringUtils.isEmpty(request.getCardHidCode())) {
			msg += "员工hid卡号不可为空|";
		}
		if (null != request.getMemberType() && request.getMemberType().equals(0) && StringUtils.isEmpty(request.getMemberCode())) {
			msg += "员工号不可为空";
		}
		if (!StringUtils.isEmpty(msg)) {
			throw new BusinessCommonException("500", msg);
		}
	}

    private void memberValidate(UpdateMemberRequest request) {
        String msg = "";
//		if (null == request.getOrg()) {
//			msg += "集团id不可为空|";
//		}
        if (StringUtils.isEmpty(request.getName())) {
            msg += "员工姓名不可为空|";
        }

        if (null != request.getMemberType() && request.getMemberType().equals(0) && StringUtils.isEmpty(request.getMemberCode())) {
            msg += "员工号不可为空";
        }
        if (!StringUtils.isEmpty(msg)) {
            throw new BusinessCommonException("500", msg);
        }
    }
	
	@Autowired
	private RedisTemplate redisTemplate;
	
	@Scheduled(cron = "0 0 1 * * ?")
	public void updateMemberRedis() {
		MemberWithCardExample example = new MemberWithCardExample();
		MemberWithCardExample.Criteria criteria = example.createCriteria();
		criteria.andIsActiveEqualTo(1);
		
		List<MemberWithCard> result = memberWithCardMapper.selectByExample4Canteen(example);
		result.forEach(mwc -> {
			DetailedMemberResponse detailedMemberResponse = new DetailedMemberResponse();
			fillDetailedMemberResponse(detailedMemberResponse, mwc);
			redisTemplate.opsForValue().set(detailedMemberResponse.getCardHidCode(), detailedMemberResponse);
		});
	}
	
	/**
	 * 根据hidCode 获取完整的会员信息
	 *
	 * @param hidCode
	 * @return
	 */
	public DetailedMemberResponse getDetailByHidCode(String hidCode) {
		MemberWithCardExample example = new MemberWithCardExample();
		example.createCriteria().andCardActiveIn(Arrays.asList(1, 2)).andCardOtherIdEqualTo(hidCode);
		example.setOrderByClause("card_Id desc");
		List<MemberWithCard> result = memberWithCardMapper.selectByExample4Canteen(example);
		if (result.isEmpty()) {
			return null;
		}
		MemberWithCard memberWithCard = result.get(0);
		DetailedMemberResponse detailedMemberResponse = new DetailedMemberResponse();
		fillDetailedMemberResponse(detailedMemberResponse, memberWithCard);
		redisTemplate.opsForValue().set(detailedMemberResponse.getCardHidCode(), detailedMemberResponse);
		return detailedMemberResponse;
	}
	
	/**
	 * 注销会员卡
	 *
	 * @param cardHidCode
	 */
	@Transactional
	public void nullifyMember(String cardHidCode) {
		DetailedMemberResponse detailedMemberResponse = this.getDetailByHidCode(cardHidCode);
		if (null == detailedMemberResponse) {
			throw new BusinessCommonException(MemberErrorCode.MEMBER_CARD_NOT_EXIST);
		}
		Member member = new Member();
		member.setMemberId(detailedMemberResponse.getId());
		member.setIsActive(0);
		memberMapper.updateByPrimaryKeySelective(member);

		Card card = new Card();
		card.setCardId(detailedMemberResponse.getCardId());
		card.setIsActive(0);
		cardMapper.updateByPrimaryKeySelective(card);
	}

	public DetailedMemberResponse getMemberById(Integer id, Integer cardId, Boolean isActive) {
		MemberWithCard memberWithCard = memberWithCardMapper.selectByMemberId4Canteen(id, cardId, isActive);
		return fillDetailedMemberResponse(new DetailedMemberResponse(), memberWithCard);
	}

	public String getSingleMemberUrl4H5(String mobile, String password, String businessCode) {
		String orgAndStoreId = env.getProperty("business.getSingleMember.code_" + businessCode);
		if (StringUtils.isEmpty(orgAndStoreId)) {
			throw new BusinessCommonException(MemberErrorCode.BUSINESS_CODE_NOT_EXISTS);
		}
		MemberWithCardExample example = new MemberWithCardExample();
		MemberWithCardExample.Criteria criteria = example.createCriteria();
		String orgId = orgAndStoreId.split("@")[0];
		String storeId = orgAndStoreId.split("@")[1];
		criteria.andMemberMobileEqualTo(mobile);
		criteria.andMemberOrgIdEqualTo(Integer.valueOf(orgId));
		criteria.andMemberStoreIdEqualTo(Integer.valueOf(storeId)).andIsActiveEqualTo(1);

		List<MemberWithCard> result = memberWithCardMapper.selectByExample(example);
		if (result.size() == 0) {
			throw new BusinessCommonException(MemberErrorCode.MEMBER_NOT_FOUND);
		}

		MemberWithCard memberWithCard = result.get(0);
		if (!passwordEncoder.matches(password, memberWithCard.getCardPassword())) {
			throw new BusinessCommonException(MemberErrorCode.WRONG_MEMBER_CARD_PASSWORD);
		}

		return env.getProperty("business.codeMatchOrgAndStoreId.code_" + businessCode + "_url");
	}
}
