package com.kiisoo.ic.login.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.kiisoo.ic.common.utils.MD5FileUtil;
import com.kiisoo.ic.constants.Constants;
import com.kiisoo.ic.login.bean.LoginBean;
import com.kiisoo.ic.login.enums.LoginEnum;
import com.kiisoo.ic.login.service.LoginService;
import com.kiisoo.ic.system.entity.PrivilageAccountDO;
import com.kiisoo.ic.system.entity.PrivilageRoleDO;
import com.kiisoo.ic.system.entity.PrivilageUserDO;
import com.kiisoo.ic.system.enums.AccountEnum;
import com.kiisoo.ic.system.mapper.PrivilageAccountDOMapper;
import com.kiisoo.ic.system.mapper.PrivilageRoleDOMapper;
import com.kiisoo.ic.system.mapper.PrivilageUserDOMapper;
import com.kiisoo.ic.wx.service.QWMailListManageService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.kiisoo.ic.constants.Constants.MINI_ROLE_CODE;

/**
 * @author jinchaofan
 * @Date 2020/2/25 12:57
 * @Company kiisoo
 * @Details 登录 实现
 */
@Service
@Slf4j
public class LoginServiceImpl implements LoginService {

    /**
     * 账号 mapper
     */
    private final PrivilageAccountDOMapper privilageAccountDOMapper;

    /**
     * 用户 mapper
     */
    private final PrivilageUserDOMapper privilageUserDOMapper;

    /**
     * 角色 mapper
     */
    private final PrivilageRoleDOMapper privilageRoleDOMapper;

    /**
     * 企业微信service
     */
    private final QWMailListManageService qwMailListManageService;

    @Autowired
    public LoginServiceImpl(PrivilageAccountDOMapper privilageAccountDOMapper, PrivilageUserDOMapper privilageUserDOMapper, PrivilageRoleDOMapper privilageRoleDOMapper, QWMailListManageService qwMailListManageService) {
        this.privilageAccountDOMapper = privilageAccountDOMapper;
        this.privilageUserDOMapper = privilageUserDOMapper;
        this.privilageRoleDOMapper = privilageRoleDOMapper;
        this.qwMailListManageService = qwMailListManageService;
    }


    @Override
    public LoginBean login(String login, String password, Boolean isMD5) {
        password = MD5FileUtil.getMD5String(password);
        UsernamePasswordToken token = new UsernamePasswordToken(login, password, false);
        Subject subject = SecurityUtils.getSubject();

        try {
            subject.login(token);
        } catch (UnknownAccountException e) {//账号不存在
            return new LoginBean(Constants.ERROR_ACCOUNT_NOT_EXIST);
        } catch (IncorrectCredentialsException e) {//密码错误
            return new LoginBean(Constants.ERROR_PASSWORD);
        }catch (AuthenticationException e) {
            log.info("login exception", e);
            return new LoginBean(Constants.ERROR_SYSTEM);
        }

        LoginBean loginBean = new LoginBean();
        if (subject.isAuthenticated()) {
            Map<String, Object> selectAccountMap = new HashMap<>();
            selectAccountMap.put("login", login);
            selectAccountMap.put("type", AccountEnum.ACCOUNT_TYPE_SYSTEM.getType());
            List<PrivilageAccountDO> privilageAccountDOS = privilageAccountDOMapper.selectByMap(selectAccountMap);
            Map<String, Object> loginInfoMap = new HashMap<>();
            PrivilageUserDO privilageUserDO = privilageUserDOMapper.selectById(privilageAccountDOS.get(0).getUserId());
            PrivilageRoleDO roleDO = privilageRoleDOMapper.selectRoleName(privilageAccountDOS.get(0).getUserId());

            //成功设置信息
            loginBean.setUserName(privilageUserDO.getName());
            loginBean.setUserId(privilageAccountDOS.get(0).getUserId());
            loginBean.setRoleId(privilageAccountDOS.get(0).getId());
            loginBean.setRoleCode(roleDO.getCode());
            loginBean.setLogin(login);
            loginInfoMap.put("code", LoginEnum.LOGIN_SUCCEED.getCode());
            loginBean.setLoginInfo(loginInfoMap);
        }else {
            return new LoginBean(Constants.LOGIN_NO_PERMISSIONS);
        }
        return loginBean;
    }

    @Override
    public LoginBean miniLogin(String login, String password, Boolean isMD5) {
        if (!isMD5){
            password = MD5FileUtil.getMD5String(password);
        }
        UsernamePasswordToken token = new UsernamePasswordToken(login, password, false);
        Subject subject = SecurityUtils.getSubject();

        try {
            subject.login(token);
        } catch (UnknownAccountException e) {//账号不存在
            return new LoginBean(Constants.ERROR_ACCOUNT_NOT_EXIST);
        } catch (IncorrectCredentialsException e) {//密码错误
            return new LoginBean(Constants.ERROR_PASSWORD);
        }catch (AuthenticationException e) {
            log.info("login exception", e);
            return new LoginBean(Constants.ERROR_SYSTEM);
        }

        LoginBean loginBean = new LoginBean();
        if (subject.isAuthenticated()) {
            Map<String, Object> selectAccountMap = new HashMap<>();
            selectAccountMap.put("login", login);
            selectAccountMap.put("type", AccountEnum.ACCOUNT_TYPE_SYSTEM.getType());
            List<PrivilageAccountDO> privilageAccountDOS = privilageAccountDOMapper.selectByMap(selectAccountMap);
            Map<String, Object> loginInfoMap = new HashMap<>();
            PrivilageUserDO privilageUserDO = privilageUserDOMapper.selectById(privilageAccountDOS.get(0).getUserId());
            PrivilageRoleDO roleDO = privilageRoleDOMapper.selectRoleName(privilageAccountDOS.get(0).getUserId());

            //成功设置信息
            loginBean.setUserName(privilageUserDO.getName());
            loginBean.setUserId(privilageUserDO.getId());
            loginBean.setRoleId(privilageUserDO.getId());
            loginBean.setRoleCode(roleDO.getCode());
            if (StringUtils.isNotBlank(roleDO.getCode()) && !MINI_ROLE_CODE.contains(roleDO.getCode())){
                return new LoginBean(Constants.ERROR_ROLE_NO_PERMISSION);
            }
            loginBean.setLogin(login);

            //查询绑定状态
            Map<String, Object> selectBindAccountMap = new HashMap<>();
            selectBindAccountMap.put("user_id", privilageUserDO.getId());
            selectBindAccountMap.put("type", AccountEnum.ACCOUNT_TYPE_QYWX.getType());
            List<PrivilageAccountDO> bindAccounts = privilageAccountDOMapper.selectByMap(selectBindAccountMap);
            if (CollectionUtils.isEmpty(bindAccounts)){
                loginInfoMap.put("code", LoginEnum.LOGIN_SUCCEED.getCode());
            }else{
                loginBean.setCpUserId(bindAccounts.get(0).getLogin());
                loginInfoMap.put("code", LoginEnum.LOGIN_USER_BINDED.getCode());
            }

            loginBean.setLoginInfo(loginInfoMap);
        }else {
            return new LoginBean(Constants.LOGIN_NO_PERMISSIONS);
        }
        return loginBean;
    }

    @Override
    public void bindQywxUserIdByUserId(Long userId, String qywxUserId) {
        Map<String, Object> selectAccountMap = new HashMap<>();
        selectAccountMap.put("login", qywxUserId);
        selectAccountMap.put("type", AccountEnum.ACCOUNT_TYPE_QYWX.getType());
        List<PrivilageAccountDO> privilageAccountDOS = privilageAccountDOMapper.selectByMap(selectAccountMap);
        //账号不存在
        if (privilageAccountDOS == null || privilageAccountDOS.size() == 0) {
            PrivilageAccountDO accountDO = new PrivilageAccountDO();
            accountDO.setLogin(qywxUserId);
            accountDO.setType(AccountEnum.ACCOUNT_TYPE_QYWX.getType());
            accountDO.setStatus(AccountEnum.ACCOUNT_STATUS_NORMAL.getType());
            accountDO.setCreateTime(new Date());
            accountDO.setUpdateTime(new Date());
            accountDO.setUserId(userId);
            privilageAccountDOMapper.insert(accountDO);
        }
    }

    @Override
    public Map<String, String> getLoginInfoByQywxUserId(String qywxUserId) {
        Map<String, Object> selectAccountMap = new HashMap<>();
        selectAccountMap.put("login", qywxUserId);
        selectAccountMap.put("type", AccountEnum.ACCOUNT_TYPE_QYWX.getType());
        List<PrivilageAccountDO> privilageAccountDOS = privilageAccountDOMapper.selectByMap(selectAccountMap);
        //账号不存在
        if (privilageAccountDOS == null || privilageAccountDOS.size() == 0) {
            return null;
        } else {
            selectAccountMap = new HashMap<>();
            selectAccountMap.put("user_id", privilageAccountDOS.get(0).getUserId());
            selectAccountMap.put("type", AccountEnum.ACCOUNT_TYPE_SYSTEM.getType());
            List<PrivilageAccountDO> accountDOS = privilageAccountDOMapper.selectByMap(selectAccountMap);
            if (accountDOS != null && accountDOS.size() > 0) {
                Map<String, String> result = new HashMap<>(2);
                result.put("login", accountDOS.get(0).getLogin());
                result.put("password", accountDOS.get(0).getPassword());
                return result;
            } else {
                return null;
            }
        }

    }

    @Override
    public Map<String, String> qyMiniAutoLogin(String code) throws WxErrorException {
        Map<String, String> result = new HashMap<>(3);

        String cpUserId = qwMailListManageService.getCpUserIdByCode(code);
        result.put("cpUserId",cpUserId);
        Map<String, Object> selectAccountMap = new HashMap<>();
        selectAccountMap.put("login", cpUserId);
        selectAccountMap.put("type", AccountEnum.ACCOUNT_TYPE_QYWX.getType());
        List<PrivilageAccountDO> privilageAccountDOS = privilageAccountDOMapper.selectByMap(selectAccountMap);
        //账号不存在
        if (privilageAccountDOS != null && privilageAccountDOS.size() > 0) {
            selectAccountMap = new HashMap<>();
            selectAccountMap.put("user_id", privilageAccountDOS.get(0).getUserId());
            selectAccountMap.put("type", AccountEnum.ACCOUNT_TYPE_SYSTEM.getType());
            List<PrivilageAccountDO> accountDOS = privilageAccountDOMapper.selectByMap(selectAccountMap);
            if (accountDOS != null && accountDOS.size() > 0) {
                result.put("login", accountDOS.get(0).getLogin());
                result.put("password", accountDOS.get(0).getPassword());
            }
        }
        return result;
    }
}
