package com.flossom.system.service.impl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

import com.flossom.common.core.domain.entity.*;
import com.flossom.common.core.domain.req.WxUserIntegralVm;
import com.flossom.common.core.domain.req.WxUserMemberReq;
import com.flossom.common.core.domain.req.WxUserMemberVm;
import com.flossom.common.core.domain.ret.WxUserMemberRet;
import com.flossom.common.core.domain.vo.WxUserMemberVo;
import com.flossom.common.core.enums.BindingStatusEnums;
import com.flossom.common.core.enums.IntegralChangeTypeEnum;
import com.flossom.common.core.enums.Status;
import com.flossom.common.core.enums.TagTypeStatusEnum;
import com.flossom.common.core.exception.ServiceException;
import com.flossom.common.core.mapper.*;
import com.flossom.common.core.utils.DateUtils;
import com.flossom.common.security.utils.SecurityUtils;
import com.flossom.system.service.ISysUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.flossom.system.service.IWxUserMemberService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 用户Service业务层处理
 *
 * @author flossom
 * @date 2023-12-08
 */
@Service
public class WxUserMemberServiceImpl implements IWxUserMemberService {
    @Autowired
    private WxUserMemberMapper wxUserMemberMapper;

    @Autowired
    private WxUserTagMapper wxUserTagMapper;

    @Autowired
    private SysTagMapper sysTagMapper;

    @Autowired
    private WxUserIntegralLogMapper wxUserIntegralLogMapper;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private WxNoRemindRecordMapper wxNoRemindRecordMapper;

    @Autowired
    private WxUserRemarkMapper wxUserRemarkMapper;

    @Autowired
    private WxUserScriptLogMapper wxUserScriptLogMapper;

    @Autowired
    private SysRegionMapper sysRegionMapper;

    @Autowired
    private WxUserInstrumentMapper wxUserInstrumentMapper;

    @Autowired
    private WxUserInstrumentLogMapper wxUserInstrumentLogMapper;

    @Autowired
    private WxInstrumentSerialMapper wxInstrumentSerialMapper;

    /**
     * 查询用户
     *
     * @param id 用户主键
     * @return 用户
     */
    @Override
    public WxUserMemberVo selectWxUserMemberById(Long id) {
        WxUserMemberVo wxUserMemberVo = new WxUserMemberVo();
        WxUserMember wxUserMember = wxUserMemberMapper.selectWxUserMemberById(id);
        BeanUtils.copyProperties(wxUserMember, wxUserMemberVo);
        // 查询小程序标签
        WxUserTag query = new WxUserTag();
        query.setType(TagTypeStatusEnum.MINI_PROGRAM.getCode());
        query.setUserId(wxUserMember.getId());
        List<WxUserTag> miniProgramUserTagList = wxUserTagMapper.selectWxUserTagList(query);
        List<Long> collect = null;
        if (miniProgramUserTagList != null && miniProgramUserTagList.size() > 0) {
            collect = miniProgramUserTagList.stream().map(WxUserTag::getTagId).collect(Collectors.toList());
        }
        wxUserMemberVo.setMiniProgramTags(collect);
        // 查询外部标签
        query.setType(TagTypeStatusEnum.ENTERPRISE_WECHAT.getCode());
        List<WxUserTag> wecomUserTags = wxUserTagMapper.selectWxUserTagList(query);
        collect = null;
        if (wecomUserTags != null && wecomUserTags.size() > 0) {
            collect = wecomUserTags.stream().map(WxUserTag::getTagId).collect(Collectors.toList());
        }
        wxUserMemberVo.setWecomTags(collect);
        // 查询用户备注
        WxUserRemark wxUserRemark = new WxUserRemark();
        wxUserRemark.setUserId(wxUserMember.getId());
        wxUserRemark.setStatus(Status.OK.getCode());
        wxUserMemberVo.setWxUserRemarkList(wxUserRemarkMapper.selectWxUserRemarkList(wxUserRemark));
        return wxUserMemberVo;
    }

    @Override
    public WxUserMember selectWxUserMemberByIdInit(Long id) {
        return wxUserMemberMapper.selectWxUserMemberById(id);
    }

    /**
     * 查询用户列表
     *
     * @param wxUserMember 用户
     * @return 用户
     */
    @Override
    public List<WxUserMember> selectWxUserMemberList(WxUserMember wxUserMember) {
        return wxUserMemberMapper.selectWxUserMemberList(wxUserMember);
    }

    /**
     * 查询用户列表
     *
     * @param wxUserMemberVm 用户
     * @return 用户
     */
    @Override
    public List<WxUserMember> selectWxUserMemberList(WxUserMemberVm wxUserMemberVm) {
        return wxUserMemberMapper.selectWxUserMemberListByVm(wxUserMemberVm);
    }

    /**
     * 新增用户
     *
     * @param wxUserMember 用户
     * @return 结果
     */
    @Override
    public int insertWxUserMember(WxUserMember wxUserMember) {
        wxUserMember.setCreateTime(DateUtils.getNowDate());
        return wxUserMemberMapper.insertWxUserMember(wxUserMember);
    }

    /**
     * 修改用户
     *
     * @param
     * @return 结果
     */
    @Override
    public int updateWxUserMember(WxUserMemberReq wxUserMemberReq) {
        wxUserMemberReq.setUpdateTime(DateUtils.getNowDate());
        WxUserMember wxUserMember = new WxUserMember();
        BeanUtils.copyProperties(wxUserMemberReq, wxUserMember);
        // 补充 省市区信息
        if (wxUserMemberReq.getProvinceId() != null) {
            SysRegion province = sysRegionMapper.selectSysRegionById(wxUserMemberReq.getProvinceId());
            wxUserMember.setProvince(province.getName());
        }
        if (wxUserMemberReq.getCityId() != null) {
            SysRegion city = sysRegionMapper.selectSysRegionById(wxUserMemberReq.getCityId());
            wxUserMember.setCity(city.getName());
        }
        if (wxUserMemberReq.getAreaId() != null) {
            SysRegion area = sysRegionMapper.selectSysRegionById(wxUserMemberReq.getAreaId());
            wxUserMember.setArea(area.getName());
        }

        // 删除用户与标签的关联关系
        wxUserTagMapper.deleteWxUserTagByUserId(wxUserMemberReq.getId());
        // 添加用户与小程序标签关联
        List<Integer> userIdList = new ArrayList<>();
        userIdList.add(wxUserMemberReq.getId().intValue());
        if (wxUserMemberReq.getMiniProgramTags() != null && wxUserMemberReq.getMiniProgramTags().size() > 0) {
            batchAddMiniProgramTag(wxUserMemberReq.getMiniProgramTags(), userIdList);
        }
        // 添加用户与外部标签关联
        if (wxUserMemberReq.getWecomTags() != null && wxUserMemberReq.getWecomTags().size() > 0) {
            batchAddWecomTag(wxUserMemberReq.getWecomTags(), userIdList);
        }
        return wxUserMemberMapper.updateWxUserMember(wxUserMember);
    }

    /**
     * 批量删除用户
     *
     * @param ids 需要删除的用户主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteWxUserMemberByIds(Long[] ids) {
        for (Long id : ids) {
            WxUserMember wxUserMember = wxUserMemberMapper.selectWxUserMemberById(id);
            if (wxUserMember != null) {
                // sys_user 删除系统用户关联表
                SysUser sysUser = sysUserService.selectUserByUserName(wxUserMember.getOpenid());
                if (sysUser != null) {
                    sysUserService.deleteWxUserById(sysUser.getUserId());
                }
                // wx_user_integral_log 用户积分关联表
                wxUserIntegralLogMapper.deleteWxUserIntegralLogByUserId(wxUserMember.getId());
                // wx_no_remain_record 不提醒关联表
                wxNoRemindRecordMapper.deleteWxNoRemindRecordByOpenid(wxUserMember.getOpenid());
                // wx_user_remark 备注关联表
                wxUserRemarkMapper.deleteWxUserRemarkByUserId(wxUserMember.getId());
                // wx_user_script_log 话术发送记录关联表
                wxUserScriptLogMapper.deleteWxUserScriptLogByWxUserId(wxUserMember.getId());
                // wx_user_tag 用户标签关联表
                wxUserTagMapper.deleteWxUserTagByUserId(wxUserMember.getId());
                // wx_instrument_serial 仪器序列号解绑
                WxUserInstrument query = new WxUserInstrument();
                query.setUserId(wxUserMember.getId());
                query.setBindingStatus(BindingStatusEnums.BINDED.getCode());
                query.setStatus(Status.OK.getCode().longValue());
                List<WxUserInstrument> wxUserInstruments = wxUserInstrumentMapper.selectWxUserInstrumentList(query);
                if (wxUserInstruments != null && wxUserInstruments.size() > 0) {
                    List<String> serialList = wxUserInstruments.stream().map(WxUserInstrument::getSerial).collect(Collectors.toList());
                    for (String serial : serialList) {
                        WxInstrumentSerial wxInstrumentSerial = new WxInstrumentSerial();
                        wxInstrumentSerial.setSerial(serial);
                        wxInstrumentSerial.setBindingStatus(BindingStatusEnums.UN_BOUND.getCode());
                        wxInstrumentSerial.setCreateBy(SecurityUtils.getUsername());
                        wxInstrumentSerial.setCreateTime(DateUtils.getNowDate());
                        wxInstrumentSerialMapper.updateBySerial(wxInstrumentSerial);
                    }
                }
                // wx_user_instrument 用户仪器关联表
                wxUserInstrumentMapper.deleteByUserId(wxUserMember.getId());
                // wx_user_instrument_log 用户仪器关联表记录
                wxUserInstrumentLogMapper.deleteByUserId(wxUserMember.getId());
            }
        }
        // wx_user_member 微信用户表
        return wxUserMemberMapper.deleteWxUserMemberByIds(ids);
    }

    /**
     * 删除用户信息
     *
     * @param id 用户主键
     * @return 结果
     */
    @Override
    public int deleteWxUserMemberById(Long id) {
        return wxUserMemberMapper.deleteWxUserMemberById(id);
    }

    @Override
    public List<Integer> selectUserCount() {
        return wxUserMemberMapper.selectUserCount();
    }

    /**
     * 批量添加外部标签
     *
     * @param tagIdList
     * @param userIdList
     */
    @Override
    public void batchAddWecomTag(List<Integer> tagIdList, List<Integer> userIdList) {
        batchAddTag(tagIdList, userIdList, TagTypeStatusEnum.ENTERPRISE_WECHAT.getCode());
    }

    /**
     * 批量添加小程序标签
     *
     * @param tagIdList
     * @param userIdList
     */
    @Override
    public void batchAddMiniProgramTag(List<Integer> tagIdList, List<Integer> userIdList) {
        batchAddTag(tagIdList, userIdList, TagTypeStatusEnum.MINI_PROGRAM.getCode());
    }

    /**
     * 批量添加标签
     * code 标签类型 {@link TagTypeStatusEnum}
     *
     * @param tagIdList
     * @param userIdList
     */
    public void batchAddTag(List<Integer> tagIdList, List<Integer> userIdList, Integer code) {
        // 对单个标签操作
        for (Integer tagId : tagIdList) {
            SysTag sysTag = sysTagMapper.selectDeptById(tagId.longValue());
            if (sysTag != null) {
                List<Integer> needAddIdList = new ArrayList<>();
                // 1、查询该标签下，有那些用户关联
                List<Integer> existedUserList = wxUserTagMapper.selectWxUserTagByTagId(tagId, code);
                Iterator<Integer> iterator = userIdList.iterator();
                while (iterator.hasNext()) {
                    Integer element = iterator.next();
                    if (!existedUserList.contains(element)) {
                        needAddIdList.add(element);
                    }
                }

                // 2、添加用户与标签的关联
                List<WxUserTag> list = new ArrayList<>();
                WxUserTag wxUserTag;
                if (needAddIdList != null && needAddIdList.size() > 0) {
                    for (Integer userId : needAddIdList) {
                        wxUserTag = new WxUserTag(null, userId.longValue(), sysTag.getTagName(), tagId.longValue(), code, null);
                        wxUserTag.setCreateTime(DateUtils.getNowDate());
                        list.add(wxUserTag);
                    }
                    wxUserTagMapper.insertBatch(list);
                }
            }
        }
        // TODO: 对接数赢：批量添加小程序标签
    }


    /**
     * 批量删除小程序标签
     *
     * @param tagIdList
     * @param userIdList
     */
    @Override
    public void batchDelMiniProgramTag(List<Integer> tagIdList, List<Integer> userIdList) {
        wxUserTagMapper.deleteBatch(tagIdList, userIdList);
        // TODO: 对接数赢：批量删除小程序标签
    }

    /**
     * 批量 增加/减少 积分
     *
     * @param wxUserIntegralVm
     * @param userIdList
     */
    @Transactional
    @Override
    public void batchChangIntegral(WxUserIntegralVm wxUserIntegralVm, List<Long> userIdList) {
        for (Long userId : userIdList) {
            // 1、记录积分操作日志
            WxUserMember wxUserMember = wxUserMemberMapper.selectWxUserMemberById(userId);
            if (wxUserMember != null) {
                WxUserIntegralLog wxUserIntegralLog = new WxUserIntegralLog();
                wxUserIntegralLog.setUserId(userId);
                wxUserIntegralLog.setUserName(wxUserMember.getNickname());
                wxUserIntegralLog.setUserPhone(wxUserMember.getMobile());
                BeanUtils.copyProperties(wxUserIntegralVm, wxUserIntegralLog);
                wxUserIntegralLog.setCreateTime(DateUtils.getNowDate());
                wxUserIntegralLog.setCreateBy(SecurityUtils.getUsername());
                wxUserIntegralLogMapper.insertWxUserIntegralLog(wxUserIntegralLog);
            }
            // 2、变更总积分
            WxUserMember changeUserMember = new WxUserMember();
            if (wxUserIntegralVm.getSource().equals(IntegralChangeTypeEnum.INCREASE.getCode())) {
                changeUserMember.setCredit(wxUserMember.getCredit() + wxUserIntegralVm.getFloatScore().intValue());
            } else if (wxUserIntegralVm.getSource().equals(IntegralChangeTypeEnum.REDUCE.getCode())) {
                if (wxUserMember.getCredit() >= wxUserIntegralVm.getFloatScore().intValue()) {
                    changeUserMember.setCredit(wxUserMember.getCredit() - wxUserIntegralVm.getFloatScore().intValue());
                } else {
                    changeUserMember.setCredit(0);
                }
            }
            changeUserMember.setId(wxUserMember.getId());
            changeUserMember.setUpdateTime(DateUtils.getNowDate());
            changeUserMember.setUpdateBy(SecurityUtils.getUsername());
            wxUserMemberMapper.updateWxUserMember(changeUserMember);
        }
        // TODO: 对接数赢：批量积分操作
    }

    @Override
    public void openOrCloseClock(Long id) {
        WxUserMember wxUserMember = wxUserMemberMapper.selectWxUserMemberById(id);
        if (wxUserMember == null) {
            throw new ServiceException("用户不存在");
        }
        WxUserMember update = new WxUserMember();
        update.setId(id);
        if (wxUserMember.getClock() == 1) {
            update.setClock(2);
        } else {
            update.setClock(1);
        }
        wxUserMemberMapper.updateWxUserMember(update);
    }

    @Override
    public void openOrCloseActivity(Long id) {
        WxUserMember wxUserMember = wxUserMemberMapper.selectWxUserMemberById(id);
        if (wxUserMember == null) {
            throw new ServiceException("用户不存在");
        }
        WxUserMember update = new WxUserMember();
        update.setId(id);
        if (wxUserMember.getActivity() == 1) {
            update.setActivity(2);
        } else {
            update.setActivity(1);
        }
        wxUserMemberMapper.updateWxUserMember(update);
    }

    @Override
    public List<WxUserMemberRet> selectWxUserMemberRetList(WxUserMemberVm wxUserMemberVm) {
        if (wxUserMemberVm.getWecomTags() != null) {
            wxUserMemberVm.setWecomTagNum(wxUserMemberVm.getWecomTags().size());
        }
        if (wxUserMemberVm.getMiniProgramTags() != null) {
            wxUserMemberVm.setMiniProgramTagNum(wxUserMemberVm.getMiniProgramTags().size());
        }
        List<WxUserMemberRet> wxUserMemberRetList = wxUserMemberMapper.selectWxUserMemberRetListByVm(wxUserMemberVm);
        if (wxUserMemberRetList != null && wxUserMemberRetList.size() > 0) {
            for (WxUserMemberRet wxUserMemberRet : wxUserMemberRetList) {
                WxUserTag wxUserTag = new WxUserTag();
                wxUserTag.setUserId(wxUserMemberRet.getId());
                wxUserTag.setType(TagTypeStatusEnum.MINI_PROGRAM.getCode());
                wxUserMemberRet.setMiniProgramTags(wxUserTagMapper.selectWxUserTagList(wxUserTag));
                wxUserTag.setType(TagTypeStatusEnum.ENTERPRISE_WECHAT.getCode());
                wxUserMemberRet.setWecomTags(wxUserTagMapper.selectWxUserTagList(wxUserTag));
                WxUserInstrument wxUserInstrument = new WxUserInstrument();
                wxUserInstrument.setUserId(wxUserMemberRet.getId());
                wxUserInstrument.setBindingStatus(BindingStatusEnums.BINDED.getCode());
                wxUserInstrument.setStatus(Status.OK.getCode().longValue());
                wxUserMemberRet.setInstrumentList(wxUserInstrumentMapper.selectWxUserInstrumentList(wxUserInstrument));
            }
        }
        return wxUserMemberRetList;
    }

    @Override
    public List<WxUserMemberRet> selectWxUserMemberByIdList(List<Integer> userIdList) {
        List<WxUserMemberRet> list = new ArrayList<>();
        List<WxUserMemberRet> wxUserMemberRetList = wxUserMemberMapper.selectWxUserMemberRetByIdList(userIdList);
        if (wxUserMemberRetList != null && wxUserMemberRetList.size() > 0) {
            for (WxUserMemberRet wxUserMemberRet : wxUserMemberRetList) {
                WxUserTag wxUserTag = new WxUserTag();
                wxUserTag.setUserId(wxUserMemberRet.getId());
                wxUserTag.setType(TagTypeStatusEnum.MINI_PROGRAM.getCode());
                wxUserMemberRet.setMiniProgramTags(wxUserTagMapper.selectWxUserTagList(wxUserTag));
                wxUserTag.setType(TagTypeStatusEnum.ENTERPRISE_WECHAT.getCode());
                wxUserMemberRet.setWecomTags(wxUserTagMapper.selectWxUserTagList(wxUserTag));
                WxUserInstrument wxUserInstrument = new WxUserInstrument();
                wxUserInstrument.setUserId(wxUserMemberRet.getId());
                wxUserInstrument.setBindingStatus(BindingStatusEnums.BINDED.getCode());
                wxUserInstrument.setStatus(Status.OK.getCode().longValue());
                wxUserMemberRet.setInstrumentList(wxUserInstrumentMapper.selectWxUserInstrumentList(wxUserInstrument));
                list.add(wxUserMemberRet);
            }
        }
        return list;
    }
}
