package com.iformall.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.iformall.common.IdWorker;
import com.iformall.domain.dto.WxCUserBasicInfoDto;
import com.iformall.domain.po.WxAuthorizerInfo;
import com.iformall.domain.po.WxCUser;
import com.iformall.domain.po.WxCUserBasicInfo;
import com.iformall.domain.po.WxCreditHistory;
import com.iformall.domain.po.msg.FmInsideCLoginMsg;
import com.iformall.domain.vo.UserCountVo;
import com.iformall.enums.*;
import com.iformall.exception.MallinkException;
import com.iformall.mapper.WxCUserMapper;
import com.iformall.mq.MqBaseProducer;
import com.iformall.service.*;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

@Service
public class WxCUserServiceImpl implements WxCUserService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    WxCUserMapper wxCUserMapper;

    @Autowired
    private WxCUserBasicInfoService wxCUserBasicInfoService;

    @Autowired
    private WxScoreRulesService wxScoreRulesService;

    @Autowired
    private WxCreditHistoryService wxCreditHistoryService;

    @Autowired
    private WxCUserTagsService wxCUserTagsService;

    @Autowired
    private MqBaseProducer mqBaseProducer;

    @Override
    public PageInfo<WxCUser> listAsPage(WxCUser record, Integer pageIndex, Integer pageSize) {
        return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxCUserMapper.findList(record));
    }

    @Override
    public WxCUser getById(Long id) {
        return wxCUserMapper.selectById(id);
    }

    @Override
    public WxCUser getByOpenId(WxCUser record) {
        return wxCUserMapper.findByOpenId(record);
    }

    @Override
    public WxCUser getByObject(WxCUser record) {
        try {
            return wxCUserMapper.selectOne(new QueryWrapper(record));
        } catch (Exception e) {
            logger.error("NOT found: " + e.getMessage());
        }
        return null;
    }

    @Override
    public int saveOrUpdate(WxCUser user) {
        int ret = 0;
        Date curr = new Date();
        if (user.getId() == null) {
            // 检查用户是否已有同一微信开放平台账号
            if(StringUtils.isNotBlank(user.getUnionId()) && StringUtils.isNotBlank(user.getOpenAppId())) {
                WxCUser oldUser = wxCUserMapper.findByUnionId(user);
                if(oldUser != null) {
                    // 已有，更新
                    user.setId(oldUser.getId());
                    // TODO 是否其他信息需要更新
                    ret = wxCUserMapper.updateById(user);
                    return ret;
                }
            }
            final IdWorker idWorker = IdWorker.get();
            user.setId(idWorker.nextId());
            user.setLoginCount(1);
            user.setCreateDate(curr);
            user.setUpdateDate(curr);
            ret = wxCUserMapper.insert(user);
        } else {
            user.setUpdateDate(curr);
            ret = wxCUserMapper.updateById(user);
        }

        return ret;
    }

    @Override
    public int saveOrUpdateMpUser(WxMpUser mpUser, WxAuthorizerInfo authorizerInfo) {
        // 1. check user exist
        WxCUser userQ = new WxCUser();
        userQ.setTenantId(authorizerInfo.getTenantId());
        boolean bHaveUnionId = false;
        if(StringUtils.isNotBlank(mpUser.getUnionId())) {
            userQ.setUnionId(mpUser.getUnionId());
            bHaveUnionId = true;
        } else {
            userQ.setOpenAppId(authorizerInfo.getOpenAppid());
            if(authorizerInfo.getType().equals(EnumAppType.MP_S.getCode())) {
                userQ.setMpOpenId(mpUser.getOpenId());
                userQ.setMpAppId(authorizerInfo.getAuthorizerAppid());
            } else if(authorizerInfo.getType().equals(EnumAppType.MP_P.getCode())) {
                userQ.setSubsOpenId(mpUser.getOpenId());
                userQ.setSubsAppId(authorizerInfo.getAuthorizerAppid());
            }
        }
        WxCUser oldUser = getByObject(userQ);
        boolean bHave = false;
        if(oldUser != null) {
            userQ.setId(oldUser.getId());
            bHave = true;
        }
        if(!bHave && !mpUser.getSubscribe()) {
            // 未找到，且是关注消息, 直接返回
            return 0;
        }
        if(bHaveUnionId) {
            userQ.setOpenAppId(authorizerInfo.getOpenAppid());
            if (authorizerInfo.getType().equals(EnumAppType.MP_S.getCode())) {
                userQ.setMpOpenId(mpUser.getOpenId());
                userQ.setMpAppId(authorizerInfo.getAuthorizerAppid());
            } else if (authorizerInfo.getType().equals(EnumAppType.MP_P.getCode())) {
                userQ.setSubsOpenId(mpUser.getOpenId());
                userQ.setSubsAppId(authorizerInfo.getAuthorizerAppid());
            }
        }
        if(((oldUser != null && StringUtils.isBlank(oldUser.getNickName())) || (oldUser == null))
                && StringUtils.isNotBlank(mpUser.getNickname())) {
            userQ.setNickName(mpUser.getNickname());
            userQ.setGender(mpUser.getSex());
            userQ.setAvatarUrl(mpUser.getHeadImgUrl());
            userQ.setCity(mpUser.getCity());
            userQ.setProvince(mpUser.getProvince());
            userQ.setLanguage(mpUser.getLanguage());
        }
        if(authorizerInfo.getType().equals(EnumAppType.MP_S.getCode())) {
            userQ.setMpSubscribe(mpUser.getSubscribe()?1:0);
            userQ.setMpSubscribeScene(mpUser.getSubscribeScene());
            userQ.setMpSubscribeTime(new Date(mpUser.getSubscribeTime()));
        } else if(authorizerInfo.getType().equals(EnumAppType.MP_P.getCode())) {
            userQ.setSubsSubscribe(mpUser.getSubscribe()?1:0);
            userQ.setSubsSubscribeScene(mpUser.getSubscribeScene());
            userQ.setMpSubscribeTime(new Date(mpUser.getSubscribeTime()));
        }
        return saveOrUpdate(userQ);
    }

    @Override
    public int updateScene(WxCUser record) {
        Date curr = new Date();
        WxCUser userL = new WxCUser();
        userL.setId(record.getId());
        userL.setScene(record.getScene());
        userL.setUpdateDate(curr);
        int ret = wxCUserMapper.updateById(userL);
        return ret;
    }

    @Override
    public int updateLBS(WxCUser record) {
        Date curr = new Date();
        WxCUser userL = new WxCUser();
        userL.setId(record.getId());
        userL.setLongitude(record.getLongitude());
        userL.setLatitude(record.getLatitude());
        userL.setUpdateDate(curr);
        int ret = wxCUserMapper.updateById(userL);
        return ret;
    }

    @Override
    public int updateExtInfo(WxCUser record) {
        Date curr = new Date();
        WxCUser userL = new WxCUser();
        userL.setId(record.getId());
        userL.setExtraInfo(record.getExtraInfo());
        userL.setUpdateDate(curr);
        int ret = wxCUserMapper.updateById(userL);
        return ret;
    }

    @Override
    public void deleteById(Long id) {
        wxCUserMapper.deleteById(id);
    }

    @Override
    public long findCount(WxCUserBasicInfoDto dto) {
        return wxCUserMapper.findCount(dto);
    }

    @Override
    public List<UserCountVo> findCountHistory(WxCUserBasicInfoDto dto) {
        return wxCUserMapper.findCountHistory(dto);
    }

    @Override
    public PageInfo<WxCUser> listByChannel(WxCUser user, Integer pageIndex, Integer pageSize) {
        return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxCUserMapper.listByChannel(user));
    }

    @Override
    public long countByChannel(WxCUser user) {
        return wxCUserMapper.countByChannel(user);
    }

    @Override
    public void actionMsgAfterLogin(WxCUser user, Boolean findByUnionId) {
        FmInsideCLoginMsg loginMsg = new FmInsideCLoginMsg();
        loginMsg.setMsgType(EnumMsgRecordType.INSIDE_C_LOGIN.getCode());
        loginMsg.setTenantId(user.getTenantId());
        loginMsg.setCUserId(user.getId());
        loginMsg.setFindByUnionId(findByUnionId);
        mqBaseProducer.sendMessage(loginMsg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode());
    }


    @Override
    public int actionAfterLogin(WxCUser user, Boolean findByUnionId) {
        int score = 0;
        int credit = 0;
        // 成长值
        try {
            score = wxScoreRulesService.addScore(EnumScoreType.LOGIN, user);
        } catch (MallinkException e) {
            logger.error("c_user 成长值 " + e.getMessage());
        } catch (Exception e) {
            logger.error("c_user 成长值 " + e.getMessage());
        }
        // 积分
        try {
            WxCreditHistory wxCreditHistory = addCredit(user, EnumScoreType.LOGIN);
            logger.info("wxCreditHistory_id" + wxCreditHistory.getId());
            credit = wxCreditHistory.getCreditNum() == null ? 0 : wxCreditHistory.getCreditNum();
            logger.info("user_id:" + user.getId() + " 登录新增积分:" + credit);
        } catch (MallinkException e) {
            logger.error("c_user 积分 " + e.getMessage());
        } catch (Exception e) {
            logger.error("c_user 积分 " + e.getMessage());
        }
        wxCUserTagsService.triggerAssignTags(EnumAssignTagsTrigger.ASSIGN_TAGS_TRIGGER_LOGIN, user);

        // 用户登陆后 更新最后一次活跃时间
        if (user.getId() != null) {
            WxCUserBasicInfo wxCUserBasicInfo = wxCUserBasicInfoService.getById(user.getId());
            if (wxCUserBasicInfo != null) {
                WxCUserBasicInfo basicInfo = new WxCUserBasicInfo();
                basicInfo.setId(user.getId());
                basicInfo.setActiveTime(new Date());
                wxCUserBasicInfoService.update(basicInfo);
            }
            WxCUser wxCUser = getById(user.getId());
            if (wxCUser != null) {
                WxCUser cUser = new WxCUser();
                cUser.setId(user.getId());
                cUser.setActiveTime(new Date());
                saveOrUpdate(cUser);
            }
        }
        // 用户从unionId来的，可能会有重复
        if(findByUnionId != null) {
            if(findByUnionId) {
                WxCUser userQ = new WxCUser();
                userQ.setOpenAppId(user.getAppId());
                userQ.setOpenId(user.getOpenId());
                List<WxCUser> userList = wxCUserMapper.findList(userQ);
                if(userList.size() > 1) {
                    for(WxCUser tempUser: userList) {
                        if(tempUser.getUnionId() == null) {
                            // 删除 无unionId的用户
                            wxCUserMapper.deleteById(tempUser.getId());
                        }
                    }
                }
            }
        }

        return score;
    }

    @Override
    public WxCreditHistory addCredit(WxCUser user, EnumScoreType enumScoreType) {
        WxCreditHistory wxCreditHistory = new WxCreditHistory();
        wxCreditHistory.setCUserId(user.getId());
        wxCreditHistory.setTenantId(user.getTenantId());
        wxCreditHistory.setCreateDate(new Date());
        wxCreditHistory.setCreditType(enumScoreType.getCode());
        wxCreditHistory.setOperatorType(EnumUserType.CUSER.getCode());
        wxCreditHistory.setOperatorId(user.getId());
        wxCreditHistory.setCreditNum(user.getCredit());
        wxCreditHistory.setCreditAmount(user.getCredit());
        WxCreditHistory record = wxCreditHistoryService.saveOrUpdate(wxCreditHistory);
        user.setCredit(record.getCreditAmount());
        return record;
    }
}
