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

import com.neusoft.smart.pos.card.constants.CardErrorCode;
import com.neusoft.smart.pos.card.constants.CardType;
import com.neusoft.smart.pos.card.persistent.domain.Card;
import com.neusoft.smart.pos.card.service.CardService;
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.dto.member.response.MemberResponse;
import com.neusoft.smart.pos.framework.exception.BusinessCommonException;
import com.neusoft.smart.pos.framework.task.TaskExecutor;
import com.neusoft.smart.pos.member.constants.MemberErrorCode;
import com.neusoft.smart.pos.member.persistent.domain.*;
import com.neusoft.smart.pos.member.persistent.mapper.MemberCardRelationMapper;
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.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.security.crypto.password.PasswordEncoder;
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("memberService")
public class MemberService {

    @Autowired
    CardService cardService;

    @Autowired
    private MemberLevelPolicyService memberLevelPolicyService;

    @Resource
    MemberMapper memberMapper;

    @Resource
    MemberCardRelationMapper memberCardRelationMapper;

    //TODO 需要更新以适应新的表结构
    @Resource
    MemberWithCardMapper memberWithCardMapper;

    @Autowired
    protected Environment env;

    @Autowired
    protected PasswordEncoder passwordEncoder;

    @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("member_id desc");

        switch (RequestHeaderUtil.getRole()) {
            case "sa":
                if (request.getOrg() == null) {
                    throw new BusinessCommonException(MemberErrorCode.NO_ORG_PROVIDED);
                }
                criteria.andMemberOrgIdEqualTo(request.getOrg());
                break;
            case "admin":
            case "user":
                criteria.andMemberOrgIdEqualTo(RequestHeaderUtil.getOrgId());
                break;
            default:
                if(!StringUtils.isEmpty(request.getOpenId())) {
                    criteria.andMemberOrgIdEqualTo(request.getOrg());
                    criteria.andOpenIdEqualTo(request.getOpenId());
                } else {
                    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 if(!StringUtils.isEmpty(request.getOpenId())) {
            //No Store here
        } 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());
        //实际业务中一个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;
    }

    protected List<MemberCardRelation> getMemberCardRelationsByCardId(Integer cardId) {
        MemberCardRelationExample example = new MemberCardRelationExample();
        MemberCardRelationExample.Criteria criteria = example.createCriteria();
        criteria.andCardIdEqualTo(cardId);
        return memberCardRelationMapper.selectByExample(example);
    }

    public DetailedMemberResponse getMemberById(Integer id) {
        Member member = memberMapper.selectByPrimaryKey(id);
        return fillDetailedMemberResponse(new DetailedMemberResponse(), member);
    }

    /*
    获取会员信息, 用于交易时会员优惠
    */
    public DetailedMemberResponse getSingleMember(String mobile, String cardNum, String cardHardwareCode, Integer org, Integer store) {
        Member mobileMember = null;

        if (StringUtils.isEmpty(mobile) && StringUtils.isEmpty(cardNum) && StringUtils.isEmpty(cardHardwareCode)) {
            throw new BusinessCommonException(MemberErrorCode.NO_CARD_NUM_OR_MOBILE_PROVIDED);
        } else {//参数完整
            Card card = null;
            List<MemberCardRelation> relations = null;
            if (!StringUtils.isEmpty(mobile)) {
                //从手机获取会员
                MemberExample example = new MemberExample();
                MemberExample.Criteria criteria = example.createCriteria();
                if (org > 0) {
                    criteria.andMemberOrgIdEqualTo(org);
                }
                if (store > 0) {
                    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);
                }
            }
            if (!(StringUtils.isEmpty(cardNum) && StringUtils.isEmpty(cardHardwareCode))) {
                //从卡取会员
                card = cardService.getSingleCard(cardNum, cardHardwareCode, null, null, null, null);
                if(card == null) {
                    throw new BusinessCommonException(CardErrorCode.CARD_NOT_EXIST);
                }
                relations = getMemberCardRelationsByCardId(card.getCardId());
            }

            //获取完成, 校验和填充

            if (relations == null || 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);
                    }
                }
            }
        }
    }


    public Integer getStoreMemberNum(Integer org, Integer store) {
        MemberExample example = new MemberExample();
        MemberExample.Criteria criteria = example.createCriteria();

        criteria.andMemberOrgIdEqualTo(org);
        criteria.andMemberStoreIdEqualTo(store);

        return memberMapper.countByExample(example);
    }

    //TODO: 需要更新到新表结构
    @Transactional
    public DetailedMemberResponse createMember(CreateMemberRequest request) {
        MemberExample memberExample = new MemberExample();
        MemberExample.Criteria memberExampleCriteria = memberExample.createCriteria();
        Integer org = request.getOrg();
        if (org == null || org == 0) {
            org = RequestHeaderUtil.getOrgId();
        }
        Integer store = request.getStore();
        if (!StringUtils.isEmpty(request.getMobile())) {
            memberExampleCriteria.andMemberMobileEqualTo(request.getMobile());
            memberExampleCriteria.andMemberOrgIdEqualTo(org);
            memberExampleCriteria.andMemberStoreIdEqualTo(store);

            if (memberMapper.countByExample(memberExample) > 0) {
                throw new BusinessCommonException(MemberErrorCode.MEMBER_EXISTS);
            }
        } else if (!StringUtils.isEmpty(request.getOpenId())) {
        	//手机号会员和openid会员二选一；对于OpenId的会员，会员是否重复的检查需要按照会员类型及openid一起检查
        	//避免类似微信和Line的openId相同但其实不是同一个会员的情况；
        	//TODO: 如何识别line和微信实质上是同一个会员，可能将来需要考虑手机号或其他的识别
        	memberExampleCriteria.andOpenidEqualTo(request.getOpenId());
        	memberExampleCriteria.andMemberTypeEqualTo(request.getMemberType());
            memberExampleCriteria.andMemberOrgIdEqualTo(org);
            memberExampleCriteria.andMemberStoreIdEqualTo(store);

            if (memberMapper.countByExample(memberExample) > 0) {
                throw new BusinessCommonException(MemberErrorCode.MEMBER_EXISTS);
            }
        } else {
            //Never be Here
        	//支持两种会员，一种是手机创建的会员，另一种通过OpenId创建的会员；因此如果不是这两种会员，目前不支持
        	//后续如果有新类型的会员需要针对修改；
            throw new BusinessCommonException("500", "手机号/OpenId不可同时为空");
        }


        Member member = new Member();
        member.setMemberName(validateMemberName(request.getName()));
        member.setMemberOrgId(org);
        member.setMemberStoreId(store);
        member.setCreatedBy(RequestHeaderUtil.getUserId() + "");
        if (!StringUtils.isEmpty(request.getMobile())) {
            member.setMemberMobile(validateMemberMobile(request.getMobile()));
        }

        if (request.getBirthday() != null) member.setMemberBirthday(request.getBirthday());
        if (request.getGender() != null) member.setGender(request.getGender());
        if (!StringUtils.isEmpty(request.getAddress())) member.setAddress(request.getAddress());
        if (!StringUtils.isEmpty(request.getAvatar())) member.setAvatar(request.getAvatar());
        if (!StringUtils.isEmpty(request.getContent())) member.setContent(request.getContent());

        if (!StringUtils.isEmpty(request.getMemberCode())) member.setMemberCode(request.getMemberCode());
        if (!StringUtils.isEmpty(request.getMemberEmail())) member.setMemberEmail(request.getMemberEmail());
        if (!StringUtils.isEmpty(request.getOpenId()) && !StringUtils.isEmpty(request.getMemberType())){
        	member.setOpenid(request.getOpenId());
        	member.setMemberType(request.getMemberType());
        }
        Integer uid = request.getUserId();
        if (uid != null && uid != 0) {
            member.setUserId(uid);
        }

        memberMapper.insertSelective(member);

        //删除卡创建；member与卡是不同的事情，创建member不一定需要创建卡，如果member有默认的卡，
        //需要在对应业务的controller中建立member与卡的关系，而不是service的內秉逻辑
//        Card card = new Card();
//        card.setBeanName("defaultCardRelationRepository");
//        card.setCardType(CardType.MEMBER_CARD.getCode());
//        card.setCardNum(request.getCardNum());
//        card.setCardPassword(passwordEncoder.encode(request.getCardPassword()));
//        card.setCardBalance(0L);
//        card.setCardPoint(0);
//        card.setIsActive(1);
//
//        cardService.createCard(card);
//
//
//        MemberCardRelation relation = new MemberCardRelation();
//        relation.setCardId(card.getCardId());
//        relation.setMemberId(member.getMemberId());
//
//        memberCardRelationMapper.insert(relation);

        DetailedMemberResponse rs =  getMemberById(member.getMemberId());
        return rs;
    }

    public void createMember(Member member) {
        memberValidate(member);

        Integer org = member.getMemberOrgId();
        Integer store = member.getMemberStoreId();

        MemberExample memberExample = new MemberExample();
        MemberExample.Criteria memberExampleCriteria = memberExample.createCriteria();
        memberExampleCriteria.andMemberMobileEqualTo(member.getMemberMobile());
        memberExampleCriteria.andMemberOrgIdEqualTo(org);
        memberExampleCriteria.andMemberStoreIdEqualTo(store);
        if (memberMapper.countByExample(memberExample) > 0) {
            throw new BusinessCommonException(MemberErrorCode.MEMBER_EXISTS);
        }

        memberMapper.insertSelective(member);
    }

    protected void memberValidate(Member member) {
        String msg = "";
        if (StringUtils.isEmpty(member.getMemberName())) {
            msg += "姓名不可为空|";
        }
        //手机号会员或OpenId会员，即第三方社交应用会员；TODO：支持其他类型会员需要修改
        if (StringUtils.isEmpty(member.getMemberMobile()) && StringUtils.isEmpty(member.getOpenid())) {
            msg += "手机号/OpenId不可同时为空|";
        }
        if (null == member.getMemberOrgId()) {
            msg += "集团id不可为空|";
        }
        if (!StringUtils.isEmpty(msg)) {
            throw new BusinessCommonException("500", msg);
        }

    }

    protected void memberValidate(CreateMemberRequest request) {
        String msg = "";
        if (StringUtils.isEmpty(request.getName())) {
            msg += "姓名不可为空|";
        }
        //手机号会员或OpenId会员，即第三方社交应用会员；TODO：支持其他类型会员需要修改
        if (StringUtils.isEmpty(request.getMobile()) && StringUtils.isEmpty(request.getOpenId())) {
            msg += "手机号/OpenId不可同时为空|";
        }
//        if (null == request.getOrg()) {
//            msg += "集团id不可为空|";
//        }
//		if(null == request.getStore() || 0 ==request.getStore()) {
//			msg+="门店id不可为空";
//		}
        //删除密码，会员不需要与密码关联
//        if ("1".equals(request.getNeedPassword()) && StringUtils.isEmpty(request.getCardPassword())) {
//            msg += "卡密码不可为空";
//        }
        if (!StringUtils.isEmpty(msg)) {
            throw new BusinessCommonException("500", msg);
        }

    }

    @Transactional
    public DetailedMemberResponse updateMember(UpdateMemberRequest request) {
        Member member = new Member();

        member.setMemberId(request.getId());
        member.setGender(request.getGender());
        if (request.getName() != null) member.setMemberName(validateMemberName(request.getName()));
        if (!StringUtils.isEmpty(request.getMobile()))
            member.setMemberMobile(validateMemberMobile(request.getMobile()));
        if (request.getBirthday() != null) member.setMemberBirthday(request.getBirthday());
        if (request.getAddress() != null) member.setAddress(request.getAddress());
        if (!StringUtils.isEmpty(request.getAvatar())) member.setAvatar(request.getAvatar());
        if (request.getContent() != null) member.setContent(request.getContent());

        if (request.getIsActive() != null) member.setIsActive(request.getIsActive());

        memberMapper.updateByPrimaryKeySelective(member);

        DetailedMemberResponse detailedMemberResponse = this.getMemberById(member.getMemberId());
        //更新一下缓存
        MemberRedisTask memberRedisTask = new MemberRedisTask();
        memberRedisTask.setDetailedMemberResponse(detailedMemberResponse);
        taskExecutor.getExecutorService().submit(memberRedisTask);
        return detailedMemberResponse;
    }

    @Transactional
    public DetailedMemberResponse updateMember(Member member) {
        memberMapper.updateByPrimaryKeySelective(member);

        DetailedMemberResponse detailedMemberResponse = this.getMemberById(member.getMemberId());
        //更新一下缓存
        MemberRedisTask memberRedisTask = new MemberRedisTask();
        memberRedisTask.setDetailedMemberResponse(detailedMemberResponse);
        taskExecutor.getExecutorService().submit(memberRedisTask);
        return detailedMemberResponse;
    }

    protected DetailedMemberResponse fillDetailedMemberResponse(DetailedMemberResponse resp, Member member) {
        fillMemberResponse(resp, member);
        resp.setBalance(0L);
        //弃用member_card表
//        resp.setBalance(member.getCardBalance());
//        resp.setPoint(member.getCardPoint());
//        resp.setCardId(member.getCardId());
//        resp.setCardNum(member.getCardNum());
//        resp.setCardHidCode(member.getCardHidCode());
//        resp.setCardActive(member.getCardActive());

        return resp;
    }

    private MemberResponse fillMemberResponse(MemberResponse resp, Member member) {
        resp.setId(member.getMemberId());
        resp.setOpenid(member.getOpenid());
        resp.setName(member.getMemberName());
        resp.setOrg(member.getMemberOrgId());
        resp.setStore(member.getMemberStoreId());
        resp.setMobile(member.getMemberMobile());
        resp.setBirthday(member.getMemberBirthday());
        resp.setGender(member.getGender());
        resp.setAddress(member.getAddress());
        resp.setAvatar(member.getAvatar());
        resp.setIsActive(member.getIsActive());
        resp.setContent(member.getContent());
        resp.setCreatedTime(member.getCreatedTime());
        resp.setMemberEmail(member.getMemberEmail());
        resp.setMemberCode(member.getMemberCode());
        resp.setMemberType(member.getMemberType());
        resp.setMemberLevelId(member.getMemberLevelId());
        resp.setUserId(member.getUserId());

        return resp;
    }

    private String validateMemberName(String name) {
    	//微信、Line的昵称可以到16个字
        if (name.length() > 16) {
            throw new BusinessCommonException(MemberErrorCode.INVALID_MEMBER_NAME);
        }
        return name;
    }

    private String validateMemberMobile(String mobile) {
        if (mobile.length() != 11) {
            throw new BusinessCommonException(MemberErrorCode.INVALID_MEMBER_MOBILE);
        }
        return mobile;
    }

    public void updateMemberLevelId(Integer id) {
        Member member = memberMapper.selectByPrimaryKey(id);
        memberMapper.updateByPrimaryKey(member);
    }
}
