package com.yonge.cooleshow.auth.service.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.yonge.cooleshow.api.feign.AdminFeignService;
import com.yonge.cooleshow.api.feign.dto.UserFriendInfoVO;
import com.yonge.cooleshow.auth.api.dto.QRLoginDto;
import com.yonge.cooleshow.auth.api.dto.RealnameAuthReq;
import com.yonge.cooleshow.auth.api.dto.SysUserInfo;
import com.yonge.cooleshow.auth.api.dto.SysUserQueryInfo;
import com.yonge.cooleshow.auth.api.dto.UserSetReq;
import com.yonge.cooleshow.auth.api.entity.SysUser;
import com.yonge.cooleshow.auth.api.vo.UserSetVo;
import com.yonge.cooleshow.auth.config.CustomerServiceConfig;
import com.yonge.cooleshow.auth.config.RongCloudConfig;
import com.yonge.cooleshow.auth.dal.dao.SysUserDao;
import com.yonge.cooleshow.auth.service.SysConfigService;
import com.yonge.cooleshow.auth.service.SysRoleMenuService;
import com.yonge.cooleshow.auth.service.SysUserRoleService;
import com.yonge.cooleshow.auth.service.SysUserService;
import com.yonge.cooleshow.common.constant.SysConfigConstant;
import com.yonge.cooleshow.common.entity.HttpResponseResult;
import com.yonge.cooleshow.common.entity.ImUserModel;
import com.yonge.cooleshow.common.enums.CacheNameEnum;
import com.yonge.cooleshow.common.enums.SysUserType;
import com.yonge.cooleshow.common.enums.UserFirstTimeTypeEnum;
import com.yonge.toolset.base.exception.BizException;
import com.yonge.toolset.base.util.ThreadPool;
import com.yonge.toolset.mybatis.dal.BaseDAO;
import com.yonge.toolset.mybatis.service.impl.BaseServiceImpl;
import io.rong.models.user.UserModel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.stream.Collectors;

@Slf4j
@Service
@RefreshScope
public class SysUserServiceImpl extends BaseServiceImpl<Long, SysUser> implements SysUserService {

    @Autowired
    private SysUserDao sysUserDao;
    @Autowired
    private SysUserRoleService sysUserRoleService;
    @Autowired
    private SysRoleMenuService sysRoleMenuService;
    @Autowired
    private SysConfigService sysConfigService;
    @Autowired
    private RedissonClient redissonClient;
    @Resource
    private AdminFeignService adminFeignService;
    @Autowired
    private CustomerServiceConfig customerServiceConfig;

    @Override
    public BaseDAO<Long, SysUser> getDAO() {
        return sysUserDao;
    }

    @Override
    public SysUser queryByUsername(String username) {
        return sysUserDao.queryByUsername(username);
    }

    @Override
    public SysUser queryByPhone(String phone) {
        return sysUserDao.queryByPhone(phone);
    }

    @Override
    public SysUser queryLockByPhone(String phone) {
        return sysUserDao.queryLockByPhone(phone);
    }

    @Override
    public SysUser queryByPhoneAndClient(String phone, String client) {
        return sysUserDao.queryByPhoneAndClient(phone, client);
    }

    @Override
    public SysUserInfo queryUserInfoByUsername(String username) {
        return getSysUserInfo(queryByUsername(username));
    }

    @Override
    public SysUserInfo queryUserInfoByPhone(String phone) {
        return getSysUserInfo(queryLockByPhone(phone));
    }

    @Override
    public SysUserInfo queryUserInfoByPhoneAndClient(String phone, String client) {
        return getSysUserInfo(queryByPhoneAndClient(phone, client));
    }

    private SysUserInfo getSysUserInfo(SysUser sysUser) {
        if (sysUser == null) {
            return null;
        }
        SysUserInfo userInfo = new SysUserInfo();
        userInfo.setSysUser(sysUser);

        List<String> roleCodeList = sysUserRoleService.queryRoleCodeListByUserId(sysUser.getId());
        userInfo.setRoles(roleCodeList.toArray(new String[roleCodeList.size()]));

        List<Long> roleIdList = sysUserRoleService.queryRoleIdListByUserId(sysUser.getId());
        List<String> permissionList = sysRoleMenuService.queryPermissionsByRoleIdList(roleIdList);

        userInfo.setPermissions(permissionList.toArray(new String[permissionList.size()]));

        return userInfo;
    }

    @Override
    public void updatePassword(String mobile, String password) {
        sysUserDao.updatePassword(mobile, password);
    }

    @Override
    public Long add(SysUser sysUser) {
        sysUserDao.insert(sysUser);
        return sysUser.getId();
    }

    @Override
    public ImUserModel getBasic(Long userId) {
        return sysUserDao.getBasic(userId);
    }

    @Override
    public void updateBaseInfo(SysUser sysUser) {
        sysUserDao.update(sysUser);
    }

    @Override
    public SysUser queryUserInfo(Long userId) {
        return sysUserDao.get(userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SysUserInfo registerUser(String phone, String clientId, String loginUserType) {

        SysUserInfo userInfo = null;
        if (StringUtils.equalsIgnoreCase(loginUserType, "TEACHER")) {
            userInfo = registerTeacher(phone);
        } else if (StringUtils.equalsIgnoreCase(loginUserType, "STUDENT")) {
            userInfo = registerStudent(phone);
        } else if (StringUtils.equalsIgnoreCase(clientId, "TEACHER")) {
            userInfo = registerTeacher(phone);
        } else if (StringUtils.equalsIgnoreCase(clientId, "STUDENT")) {
            userInfo = registerStudent(phone);
        }

        return userInfo;
    }

    private SysUserInfo registerTeacher(String phone) {
        SysUser sysUser = new SysUser();
        sysUser.setPhone(phone);
        String defaultHeard = sysConfigService.findConfigValue(SysConfigConstant.DEFAULT_HEARD);
        sysUser.setAvatar(defaultHeard);
        sysUser.setGender(1);
        sysUser.setUserType("TEACHER");
        sysUserDao.insert(sysUser);
        //创建teacher表
        saveTeacher(sysUser);
        //用户默认昵称
        sysUser.setUsername("游客" + sysUser.getId());
        sysUserDao.update(sysUser);

        return queryUserInfoByPhone(phone);
    }

    private SysUserInfo registerStudent(String phone) {
        SysUser sysUser = new SysUser();
        sysUser.setPhone(phone);
        String defaultHeard = sysConfigService.findConfigValue(SysConfigConstant.DEFAULT_HEARD);
        sysUser.setAvatar(defaultHeard);
        sysUser.setGender(1);
        sysUser.setUserType("STUDENT");
        sysUserDao.insert(sysUser);
        saveStudent(sysUser);

        //用户默认昵称
        sysUser.setUsername("游客" + sysUser.getId());
        sysUserDao.update(sysUser);

        return queryUserInfoByPhone(phone);
    }

    /**
     * 添加系统客服好友消息
     * @param sysUser SysUser
     */
    public void sendSysCustomerServiceFriendMessage(SysUser sysUser) {

        try {

            ThreadPool.getExecutor().submit(() -> {

                String customerService = customerServiceConfig.getCustomerService();
                if (StringUtils.isNotEmpty(customerService)) {

                    List<String> collect = Arrays.stream(customerService.split(",")).collect(Collectors.toList());

                    Random rand = new Random();
                    String mobile = collect.get(rand.nextInt(collect.size()));

                    // 系统客服好友
                    SysUser friend = sysUserDao.queryByPhone(mobile);

                    // 发送添加系统客服好友消息
                    HttpResponseResult<Boolean> result = adminFeignService.customerService(UserFriendInfoVO.builder()
                            .userId(sysUser.getId())
                            .friendIds(Lists.newArrayList(friend.getId()))
                            .build());
                    log.info("sendSysCustomerServiceFriendMessage mobile={}, ret={}", mobile, JSON.toJSONString(result));
                }

            });

        } catch (Exception e) {
            log.error("sendSysCustomerServiceFriendMessage userId={}", sysUser.getId(), e);
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void refreshImToken(SysUser sysUser) {
        sysUserDao.refreshImToken(sysUser.getId(), sysUser.getImToken());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveStudent(SysUser sysUser) {
        sysUserDao.saveStudent(sysUser.getId());
        sysUserDao.createUserAccount(sysUser.getId());

        //记录注册时间
        adminFeignService.recordTime(sysUser.getId(), SysUserType.STUDENT.getCode(), UserFirstTimeTypeEnum.REGISTER_STUDENT);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveTeacher(SysUser sysUser) {
        sysUserDao.saveTeacher(sysUser.getId());
        sysUserDao.createUserAccount(sysUser.getId());

        //记录注册时间
        adminFeignService.recordTime(sysUser.getId(), SysUserType.TEACHER.getCode(), UserFirstTimeTypeEnum.REGISTER_TEACHER);
    }

    @Override
    public void updateUserCard(RealnameAuthReq realNameAuthDto) {
        sysUserDao.updateUserCard(realNameAuthDto);
    }

    @Override
    public UserSetVo getSetDetail(Long id) {
        return sysUserDao.getSetDetail(id);
    }

    @Override
    public void submitSetDetail(UserSetReq setReq, Long id) {
        sysUserDao.updatetSetDetail(setReq, id);
        //更新融云用户基本信息
        this.updateRongCloudUserInfo(id);
    }

    @Override
    public void updateRongCloudUserInfo(Long userId) {
        UserSetVo setDetail = this.getSetDetail(userId);
        //更新imGroupMember表用户头像
        sysUserDao.updateImGroupMember(userId, setDetail.getUsername(), setDetail.getAvatar());
        //更新imUserFriend表用户头像
        sysUserDao.updateImUserFriend(userId, setDetail.getUsername(), setDetail.getAvatar());
        try {
            RongCloudConfig.rongCloud.user.update(new UserModel(userId.toString(), setDetail.getUsername(), setDetail.getAvatar()));
        } catch (Exception e) {
            throw new BizException("更新用户信息失败");
        }
    }

    @Override
    public List<SysUser> queryEmployeeList(SysUserQueryInfo queryInfo) {
        return sysUserDao.queryEmployeeList(queryInfo);
    }

    @Override
    public boolean verifyQrCode(String phone, String qrCode) {
        if (StringUtils.isEmpty(phone) || StringUtils.isEmpty(qrCode)) {
            return false;
        }
        Object data = redissonClient.getBucket(CacheNameEnum.QR_LOGIN_CODE.getRedisKey(qrCode))
                .get();
        if (null == data) {
            return false;
        }
        QRLoginDto dto = (QRLoginDto) data;
        if (phone.equals(dto.getPhone()) && qrCode.equals(dto.getCode())) {
            return true;
        }
        return false;
    }

    @Override
    public void logoffById(Long id) {
        //判断用户是否有未结束的课程
        Integer num = sysUserDao.getUnCompCourseNum(id);
        if (num > 0) {
            throw new BizException("用户有未完成的课程");
        }

        List<SysUser> sysUsers = sysUserDao.queryHistoryUserById(id);
        Integer maxVersion = 0;
        if (!CollectionUtils.isEmpty(sysUsers)) {
            for (SysUser sysUser : sysUsers) {
                String[] split = sysUser.getPhone().split("\\+");
                if (split.length == 2) {
                    String version = split[0].substring(1);
                    if (maxVersion < Integer.parseInt(version)) {
                        maxVersion = Integer.parseInt(version);
                    }
                }
            }
        }
        maxVersion += 1;
        sysUserDao.logoffById(id, maxVersion);
    }

    @Override
    public void updateLockStatus(Long userId, Integer lockFlag, String sysUserType) {
        sysUserDao.updateLockStatus(userId, lockFlag, sysUserType);
    }
}
