package com.github.wxiaoqi.security.admin.biz;

import com.ace.cache.annotation.Cache;
import com.ace.cache.annotation.CacheClear;
import com.alibaba.fastjson.JSONObject;
import com.github.wxiaoqi.security.admin.bo.UserBo;
import com.github.wxiaoqi.security.admin.dto.AccountBindDTO;
import com.github.wxiaoqi.security.admin.entity.AppUserLogin;
import com.github.wxiaoqi.security.admin.entity.AppUserPositionTemp;
import com.github.wxiaoqi.security.admin.entity.AppUserRelation;
import com.github.wxiaoqi.security.admin.mapper.AppUserLoginMapper;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
import com.github.wxiaoqi.security.common.config.rabbit.RabbitConstant;
import com.github.wxiaoqi.security.common.constant.UserConstant;
import com.github.wxiaoqi.security.common.msg.ObjectRestResponse;
import com.xxfc.platform.universal.entity.IdInformation;
import com.xxfc.platform.universal.feign.MQSenderFeign;
import com.xxfc.platform.universal.feign.ThirdFeign;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.servlet.http.HttpServletRequest;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * ${DESCRIPTION}
 *
 * @author wanghaobin
 * @create 2017-06-08 16:23
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class AppUserLoginBiz extends BaseBiz<AppUserLoginMapper, AppUserLogin> {

    private static final String WX_TYPE = "wx";
    private static final String QQ_TYPE = "q";
    private static final String ALIPAY_TYPE = "aliPay";

    @Autowired
    ThirdFeign thirdFeign;
    @Autowired
    MQSenderFeign mqSenderFeign;

    @Autowired
    AppUserDetailBiz appUserDetailBiz;

    @Autowired
    private AppUserAlipayBiz appUserAlipayBiz;

    @Autowired
    private AppUserRelationBiz appUserRelationBiz;

    @Autowired
    private AppUserSellingWaterBiz appUserSellingWaterBiz;

    @Autowired
    private AppUserPositionTempBiz appUserPositionTempBiz;

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    @Override
    public void insertSelective(AppUserLogin entity) {
        String password = new BCryptPasswordEncoder(UserConstant.PW_ENCORDER_SALT).encode(entity.getPassword());
        entity.setPassword(password);
        super.insertSelective(entity);
    }

    @Override
    @CacheClear(pre = "user{1.username}")
    public void updateSelectiveById(AppUserLogin entity) {
        super.updateSelectiveById(entity);
    }

    @CacheClear(pre = "user{1.username}")
    public int bindOpenid(AppUserLogin entity) {
        return mapper.bindOpenId(entity);
    }

    @CacheClear(pre = "user{1.username}")
    public void updatePasswordById(AppUserLogin entity) {
        String password = new BCryptPasswordEncoder(UserConstant.PW_ENCORDER_SALT).encode(entity.getPassword());
        entity.setPassword(password);
        super.updateSelectiveById(entity);
    }

    public Object test() {
        threadRunner();
        return "success";
    }

    public void threadRunner() {
        List<AppUserLogin> list = mapper.selectAll();
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                if (list != null && list.size() > 0) {
                    for (AppUserLogin appUserLogin : list) {
                        try {
                            Thread.sleep(3000);
                        } catch (Exception e) {
                        }
                        IdInformation idInformation = thirdFeign.getOneByUserId(appUserLogin.getId());
                        if (idInformation != null) { //实名认证
                            JSONObject jsonObject = new JSONObject();
                            jsonObject.put("userId", appUserLogin.getId());
                            jsonObject.put("integralRuleCode", "CRETIFICATION");
                            jsonObject.put("channelId", idInformation.getId());
                            mqSenderFeign.sendMessage(RabbitConstant.INTEGRAL_TOPIC, RabbitConstant.INTEGRAL_ROUTING_KEY, jsonObject.toJSONString());
                        }
                        try {
                            Thread.sleep(3000);
                        } catch (Exception e) {
                        }
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("userId", appUserLogin.getId());
                        jsonObject.put("integralRuleCode", "REGISTER");
                        jsonObject.put("channelId", appUserLogin.getId());
                        mqSenderFeign.sendMessage(RabbitConstant.INTEGRAL_TOPIC, RabbitConstant.INTEGRAL_ROUTING_KEY, jsonObject.toJSONString());

                    }
                }
            }
        });
    }

    /**
     * 根据用户名获取用户信息
     *
     * @param username
     * @return
     */
    @Cache(key = "user{1}")
    public AppUserLogin getUserByUsername(String username) {
        AppUserLogin user = new AppUserLogin();
        user.setUsername(username);
        return mapper.selectOne(user);
    }

   /* public TableResultResponse<AppUserLogin> selectPage(Query query, AppUserLogin currentUser) {
        if(DATA_ALL_TRUE.equals(currentUser.getDataAll())) {
            return super.selectByQuery(query);
        }else {
            Example example = new Example(User.class);
            if(query.entrySet().size()>0) {
                Example.Criteria criteria = example.createCriteria();
                for (Map.Entry<String, Object> entry : query.entrySet()) {
                    criteria.andLike(entry.getKey(), "%" + entry.getValue().toString() + "%");
                }
            }
            if(StringUtils.isNotBlank(currentUser.getDataCompany())){
                example.createCriteria().andIn("companyId", Arrays.asList(currentUser.getDataCompany().split(",")));
            }
            if(StringUtils.isNotBlank(currentUser.getDataZone())){
                example.createCriteria().andIn("zoneId", Arrays.asList(currentUser.getDataZone().split(",")));
            }
            Page<Object> result = PageHelper.startPage(query.getPage(), query.getLimit());
            List<User> list = mapper.selectByExample(example);
            return new TableResultResponse<User>(result.getTotal(), list);
        }
    }*/

    /**
     * 根据手机号码判断是否存在用户
     *
     * @param username
     * @return
     * @throws Exception
     */

    public AppUserLogin checkeUserLogin(String username) {
        Example example = new Example(AppUserLogin.class);
        example.createCriteria().andEqualTo("username", username).andEqualTo("isdel", 0);
        List<AppUserLogin> userLoginList = mapper.selectByExample(example);
        if (userLoginList != null && userLoginList.size() != 0) {
            return userLoginList.get(0);
        }
        return null;
    }

    /**
     * 根据微信号判断是否存在用户
     *
     * @param openid
     * @return
     */
    public AppUserLogin getUserByOpenid(String openid, Integer isQQ) {
        Example example = new Example(AppUserLogin.class);
        if (isQQ == 1) {
            example.createCriteria().andEqualTo("openid", openid).andEqualTo("isdel", 0);
        } else {
            example.createCriteria().andEqualTo("wxOpenid", openid).andEqualTo("isdel", 0);
        }
        List<AppUserLogin> userLoginList = mapper.selectByExample(example);
        if (userLoginList != null && userLoginList.size() != 0) {
            return userLoginList.get(0);
        }
        return null;
    }

    /**
     * 根据手机号码判断是否已绑定微信
     *
     * @param userLogin
     * @return
     */
    public boolean checkeWechatUser(AppUserLogin userLogin) {
        boolean flag = true;
        if (null != userLogin) {
            Integer userid = userLogin.getId();
            userLogin = mapper.selectByPrimaryKey(userid);
            if (userLogin == null) {
                flag = false;
            }
        }
        return flag;
    }

    //获取用户信息
    public AppUserLogin getUserById(Integer userId) {
        return mapper.selectByPrimaryKey(userId);
    }

    /**
     * 登录信息更改
     *
     * @param userId
     * @param ip
     */
    public void updateLoginInfo(Integer userId, String ip) {
        mapper.updateLoginUserInfoById(userId, ip, Instant.now().toEpochMilli());
    }

    public Map<String, Integer> findPhoneAndUserIdMapByPhones(List<String> phones) {
        List<AppUserLogin> appUserLogins = mapper.selectbyPhones(phones);
        Map<String, Integer> phoneAndUserIdMap = null;
        if (CollectionUtils.isNotEmpty(appUserLogins)) {
            phoneAndUserIdMap = appUserLogins.parallelStream().collect(Collectors.toMap(AppUserLogin::getUsername, AppUserLogin::getId));
        }
        return phoneAndUserIdMap;
    }

    public Map<String, Integer> findPhoneAndUserIdMapByPhonesForDel(List<String> phones) {
        Example example = new Example(AppUserLogin.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("username", phones);
        List<AppUserLogin> appUserLogins = mapper.selectByExample(example);
        Map<String, Integer> phoneAndUserIdMap = null;
        if (CollectionUtils.isNotEmpty(appUserLogins)) {
            phoneAndUserIdMap = appUserLogins.parallelStream().collect(Collectors.toMap(AppUserLogin::getUsername, AppUserLogin::getId));
        }
        return phoneAndUserIdMap;
    }

    public Map<Integer, AppUserLogin> findUserIdAndUserLoginMapByMemberIds(List<Integer> memberIds) {
        Map<Integer, AppUserLogin> userIdAndAppUserLoginMap = new HashMap<>();
        List<AppUserLogin> appUserLogins = mapper.selectByIdList(memberIds);
        if (CollectionUtils.isNotEmpty(appUserLogins)) {
            userIdAndAppUserLoginMap = appUserLogins.stream().collect(Collectors.toMap(AppUserLogin::getId, Function.identity()));
        }
        return userIdAndAppUserLoginMap;
    }

    public AppUserLogin findUserByImiId(Integer imiId) {
        Example example = new Example(AppUserLogin.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("imUserid", imiId);
        List<AppUserLogin> appUserLogins = mapper.selectByExample(example);
        if (CollectionUtils.isNotEmpty(appUserLogins)) {
            return appUserLogins.get(0);
        }
        return null;
    }

    @CacheClear(pre = "user{1.id}")
    public void disable(AppUserLogin appUserLogin) {
        mapper.updateByPrimaryKeySelective(appUserLogin);
    }

    @CacheClear(pre = "user{1.id}")
    public void available(AppUserLogin appUserLogin) {
        mapper.updateByPrimaryKeySelective(appUserLogin);
    }

    public void deleteByPhones(List<String> phons) {
        Example example = new Example(AppUserLogin.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("username", phons);
        mapper.deleteByExample(example);
    }

    @CacheClear(pre = "user{1}")
    @Transactional(rollbackFor = Exception.class)
    public void deleteAppUserById(Integer id) {
        AppUserLogin appUserLogin = new AppUserLogin();
        appUserLogin.setId(id);
        appUserLogin.setIsdel(1);
        mapper.updateByPrimaryKeySelective(appUserLogin);
    }

    public List<Integer> findAllExistUserIds() {
        return mapper.selectAllExistUserIds();
    }

    /**
     * 检查第三方是否绑定
     *
     * @param wxOpenId
     * @param wxUnionId
     * @param openId
     * @return
     */
    public boolean checkThirdPartyBindingState(String wxOpenId, String wxUnionId, String openId) {
        AppUserLogin appUserLogin = new AppUserLogin();
        appUserLogin.setWxOpenid(wxOpenId);
        appUserLogin.setUnionid(wxUnionId);
        appUserLogin.setOpenid(openId);
        return mapper.selectOne(appUserLogin) != null;
    }

    @CacheClear(pre = "user{2}")
    public void unBindThirdPartyByType(String type, String username, Integer userId) {
        AppUserLogin appUserLogin = new AppUserLogin();
        appUserLogin.setId(userId);
        //微信解绑
        if (WX_TYPE.equals(type)) {
            appUserLogin.setWxOpenid("");
            appUserLogin.setUnionid("");
            mapper.updateByPrimaryKeySelective(appUserLogin);
        }
        //qq解绑
        if (QQ_TYPE.equals(type)) {
            appUserLogin.setOpenid("");
            mapper.updateByPrimaryKeySelective(appUserLogin);
        }
    }

    public List<AppUserLogin> getUserByUsernameAndRealName(String username, String realName) {
       
        return mapper.getUserByUsernameAndRealName(username,realName);


    }

    @CacheClear(pre = "user{2}")
    public ObjectRestResponse bindAccount(AccountBindDTO accountBindDTO, Integer userId, HttpServletRequest request) {
        switch (accountBindDTO.getType()) {
            case WX_TYPE:
                wxBinding(accountBindDTO, userId);
                break;
            case QQ_TYPE:
                qqBinding(accountBindDTO, userId);
                break;
            case ALIPAY_TYPE:
                return appUserAlipayBiz.getUserInfo(accountBindDTO.getCode(), request);
            default:
                break;
        }
        return ObjectRestResponse.succ(accountBindDTO.getNickName());
    }

    /**
     * 微信绑定
     *
     * @param accountBindDTO
     */
    private void wxBinding(AccountBindDTO accountBindDTO, Integer userId) {
        //检查微信是否绑定
   /*     Example example = new Example(AppUserLogin.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("id", userId);
        criteria.andEqualTo("wxOpenid", accountBindDTO.getOpendId());
        List<AppUserLogin> appUserLogins = mapper.selectByExample(example);
        if (CollectionUtils.isNotEmpty(appUserLogins)) {
            throw new BaseException("该微信已经绑定过了");
        }*/

        AppUserLogin appUserLogin = new AppUserLogin();
        appUserLogin.setId(userId);
        appUserLogin.setWxOpenid(accountBindDTO.getOpenId());
        appUserLogin.setUnionid(accountBindDTO.getUnionId());
        mapper.updateByPrimaryKeySelective(appUserLogin);
        appUserDetailBiz.updateByUserId(accountBindDTO, userId);
    }

    /**
     * QQ绑定
     *
     * @param accountBindDTO
     */
    private void qqBinding(AccountBindDTO accountBindDTO, Integer userId) {
        //检查qq是否绑定
/*        Example example = new Example(AppUserLogin.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("id", userId);
        criteria.andEqualTo("openid", accountBindDTO.getOpendId());
        List<AppUserLogin> appUserLogins = mapper.selectByExample(example);
        if (CollectionUtils.isNotEmpty(appUserLogins)) {
            throw new BaseException("该qq已经绑定过了");
        }*/
        AppUserLogin appUserLogin = new AppUserLogin();
        appUserLogin.setId(userId);
        appUserLogin.setOpenid(accountBindDTO.getOpenId());
        mapper.updateByPrimaryKeySelective(appUserLogin);
        appUserDetailBiz.updateByUserId(accountBindDTO, userId);
    }

    public void updateAppuserLogin(AppUserLogin appUserLogin) {
        appUserLogin.setUpdatetime(Instant.now().getEpochSecond());
        mapper.updateByPrimaryKeySelective(appUserLogin);
    }

    public List<Integer> findAppuser(String phone, String leaderPhone, String name) {
        List<Integer> memberIds = null;
        //1.根据leader手机号查询userid
         boolean isNoNullLeaderPhone = StringUtils.isNotEmpty(leaderPhone) && leaderPhone.trim().length()>0;
        if (isNoNullLeaderPhone) {
            List<AppUserLogin> appUserLogins = mapper.selectbyPhones(Arrays.asList(leaderPhone));
            Integer leaderId = null;
            if (CollectionUtils.isEmpty(appUserLogins)) {
                return Collections.EMPTY_LIST;
            }
            leaderId = appUserLogins.get(0).getId();
        //2.根据leader userId查询下级 userid
        if (Objects.nonNull(leaderId)) {
              memberIds = appUserSellingWaterBiz.findMemberIdByLeaderIdAndOrdreType(leaderId,3);
            if(CollectionUtils.isEmpty(memberIds)){
                return Collections.EMPTY_LIST;
            }
        }
        }
        List<Integer> userIds = mapper.findAppUser(phone, name, memberIds);
        return  userIds==null?Collections.EMPTY_LIST:userIds;
    }

    public List<UserBo> findUserDetailInfo(List<UserBo> userBos) {
        Map<String, Integer> userIdAndFacilitateIdMap = userBos.stream().filter(x->Objects.nonNull(x.getFacilitateId())).collect(Collectors.toMap(UserBo::getOrderNo, UserBo::getFacilitateId));
        List<Integer> userIdList = userBos.stream().map(UserBo::getUserId).distinct().collect(Collectors.toList());

        //查询上级人
        List<AppUserRelation> appUserRelationList = appUserRelationBiz.findLeaderByUserIds(userIdList);
        Map<Integer, Integer> memberIdAndParentMap = appUserRelationList.stream().collect(Collectors.toMap(AppUserRelation::getUserId, AppUserRelation::getParentId));

        List<Integer>  uids = new ArrayList<>();
        uids.addAll(userIdAndFacilitateIdMap==null?Collections.EMPTY_LIST:userIdList);
        uids.addAll(userIdAndFacilitateIdMap==null?Collections.EMPTY_LIST:userIdAndFacilitateIdMap.values());
        uids.addAll(memberIdAndParentMap==null?Collections.EMPTY_LIST:memberIdAndParentMap.values());

        List<UserBo> userBoList = mapper.selectByUserIds(uids);
        Map<Integer, UserBo> userMap = userBoList==null?Collections.EMPTY_MAP:userBoList.stream().collect(Collectors.toMap(UserBo::getUserId, Function.identity()));
        if (userMap.isEmpty()){
            return Collections.EMPTY_LIST;
        }

        for (UserBo userBo : userBos) {
            UserBo bo = userMap.get(userBo.getUserId());
            if (Objects.nonNull(bo)) {
                userBo.setPhone(bo.getPhone());
                userBo.setName(bo.getName());
            }
            Integer leaderId = memberIdAndParentMap.get(userBo.getUserId());
            UserBo leader = userMap.get(leaderId);
            if (Objects.nonNull(leader)) {
                userBo.setLeaderName(leader.getName());
                userBo.setLeaderPhone(leader.getPhone());
            }
            UserBo facilitate = userMap.get(userBo.getFacilitateId());
            if (Objects.nonNull(facilitate)) {
                userBo.setFacilitateName(facilitate.getName());
            }
        }
        return userBos;
    }
  @CacheClear(pre = "user{1}")
    public void updateUserPosition(Integer userId, Integer positionId, Integer operatorId) {
        AppUserLogin appUserLogin = selectById(userId);
        if (appUserLogin != null) {
            String phone = appUserLogin.getUsername();
            appUserPositionTempBiz.findUserPositionTemp(userId, positionId, operatorId);
        }
        appUserDetailBiz.updateUserPositionByUserId(userId, positionId);
    }

    @CacheClear(pre = "user{1}")
    public void updateUserPosition(Integer userId, Integer positionId) {
        appUserDetailBiz.updateUserPositionByUserId(userId, positionId);
    }


}
