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.store.entity.PoiStoreStaff;
import com.kiisoo.ic.store.mapper.PoiStoreStaffDOMapper;
import com.kiisoo.ic.store.mapper.PrivilageCpUserStoreDOMapper;
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.system.service.PrivilageAccountService;
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 PrivilageCpUserStoreDOMapper privilageCpUserStoreDOMapper;

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

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

    /**
     * 账号service
     */
    @Autowired
    private PrivilageAccountService privilageAccountService;

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


    @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);
            if (StringUtils.isNotBlank(roleDO.getCode()) && MINI_ROLE_CODE.contains(roleDO.getCode())){
                return new LoginBean(Constants.ERROR_ROLE_NO_PERMISSION);
            }
        }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);
        }
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(login, password, true);

        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());
            Long storeId = privilageUserDOMapper.selectStoreIdByUserId(privilageAccountDOS.get(0).getUserId());
            //成功设置信息
            loginBean.setUserName(privilageUserDO.getName());
            loginBean.setUserId(privilageUserDO.getId());
            loginBean.setRoleId(privilageUserDO.getId());
            loginBean.setRoleCode(roleDO.getCode());
            loginBean.setStoreId(storeId);
            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 LoginBean mobileLogin(String mobile) {
        //查询账号
        QueryWrapper<PrivilageAccountDO> accountQw = new QueryWrapper<>();
        accountQw.eq("login",mobile);
        accountQw.eq("type",AccountEnum.ACCOUNT_TYPE_MOBILE.getType());
        List<PrivilageAccountDO> mobileAccounts = privilageAccountDOMapper.selectList(accountQw);
        Long userId = null;
        if (CollectionUtils.isNotEmpty(mobileAccounts)){
            userId = mobileAccounts.get(0).getUserId();
        }else{
            QueryWrapper<PrivilageUserDO> userQw = new QueryWrapper<>();
            userQw.eq("mobil",mobile);
            //无账号则绑定账号
            List<PrivilageUserDO> privilageUserDOS = privilageUserDOMapper.selectList(userQw);
            if (CollectionUtils.isNotEmpty(privilageUserDOS)){
                userId = privilageUserDOS.get(0).getId();
                PrivilageAccountDO privilageAccountDO = new PrivilageAccountDO();
                privilageAccountDO.setLogin(mobile);
                privilageAccountDO.setStatus(1);
                privilageAccountDO.setUserId(userId);
                privilageAccountDO.setType(AccountEnum.ACCOUNT_TYPE_MOBILE.getType());
                int insert = privilageAccountDOMapper.insert(privilageAccountDO);
                if (insert == 0){
                    return new LoginBean(Constants.ERROR_SYSTEM);
                }
            }else{
                return new LoginBean(Constants.ERROR_ROLE_NO_PERMISSION);
            }
        }


        LoginBean loginBean = new LoginBean();
        Map<String, Object> selectAccountMap = new HashMap<>();

        PrivilageUserDO privilageUserDO = privilageUserDOMapper.selectById(userId);

        // 用户不存在
        if(null == privilageUserDO){
            return new LoginBean(Constants.ERROR_USER_NO_PERMISSION);
        }

        PrivilageAccountDO result = privilageAccountService.getAccountByUserId(userId);

        // 该账号已暂停，请联系店长
        if(null != result && result.getStatus().equals(2)){
            return new LoginBean(com.kiisoo.ic.constants.Constants.ERROR_ACCOUNT_STOP);
        }

        PrivilageRoleDO roleDO = privilageRoleDOMapper.selectRoleName(userId);
        Long storeId = privilageUserDOMapper.selectStoreIdByUserId(userId);
        Map<String, Object> loginInfoMap = new HashMap<>();
        //成功设置信息
        loginBean.setUserName(privilageUserDO.getName());
        loginBean.setUserId(privilageUserDO.getId());
        loginBean.setRoleId(privilageUserDO.getId());
        loginBean.setRoleCode(roleDO.getCode());
        loginBean.setStoreId(storeId);
        if (StringUtils.isNotBlank(roleDO.getCode()) && !MINI_ROLE_CODE.contains(roleDO.getCode())){
            return new LoginBean(Constants.ERROR_ROLE_NO_PERMISSION);
        }
        loginBean.setLogin(mobile);
        loginInfoMap.put("code", LoginEnum.LOGIN_SUCCEED.getCode());
        loginBean.setLoginInfo(loginInfoMap);
        return loginBean;
    }

    @Override
    public LoginBean cpUserIdLogin(String cpUserId) {
        //查询账号
        QueryWrapper<PrivilageAccountDO> accountQw = new QueryWrapper<>();
        accountQw.eq("login",cpUserId);
        accountQw.eq("type",AccountEnum.ACCOUNT_TYPE_QYWX.getType());
        List<PrivilageAccountDO> mobileAccounts = privilageAccountDOMapper.selectList(accountQw);
        Long userId = null;
        if (CollectionUtils.isNotEmpty(mobileAccounts)){
            userId = mobileAccounts.get(0).getUserId();
        }else{
            Long storeId = privilageCpUserStoreDOMapper.selectOneByCpUserId(cpUserId);
            if (null == storeId){
                return new LoginBean(Constants.ERROR_USER_NO_PERMISSION);
            }
            PoiStoreStaff poiStoreStaff = poiStoreStaffDOMapper.selectShopManagerDetailByShop(storeId);
            if (null == poiStoreStaff){
                return new LoginBean(Constants.ERROR_USER_NO_PERMISSION);
            }
            //无账号则绑定账号
            PrivilageUserDO privilageUserDO = privilageUserDOMapper.selectById(poiStoreStaff.getUserId());
            if (null != privilageUserDO){
                userId = privilageUserDO.getId();
                PrivilageAccountDO privilageAccountDO = new PrivilageAccountDO();
                privilageAccountDO.setLogin(cpUserId);
                privilageAccountDO.setStatus(1);
                privilageAccountDO.setUserId(userId);
                privilageAccountDO.setType(AccountEnum.ACCOUNT_TYPE_QYWX.getType());
                int insert = privilageAccountDOMapper.insert(privilageAccountDO);
                if (insert == 0){
                    return new LoginBean(Constants.ERROR_SYSTEM);
                }
            }else{
                return new LoginBean(Constants.ERROR_ROLE_NO_PERMISSION);
            }
        }


        LoginBean loginBean = new LoginBean();
        Map<String, Object> selectAccountMap = new HashMap<>();

        PrivilageUserDO privilageUserDO = privilageUserDOMapper.selectById(userId);

        // 用户不存在
        if(null == privilageUserDO){
            return new LoginBean(Constants.ERROR_USER_NO_PERMISSION);
        }

        PrivilageAccountDO result = privilageAccountService.getAccountByUserId(userId);

        // 该账号已暂停，请联系店长
        if(null != result && result.getStatus().equals(2)){
            return new LoginBean(com.kiisoo.ic.constants.Constants.ERROR_ACCOUNT_STOP);
        }

        PrivilageRoleDO roleDO = privilageRoleDOMapper.selectRoleName(userId);
        Long storeId = privilageUserDOMapper.selectStoreIdByUserId(userId);
        Map<String, Object> loginInfoMap = new HashMap<>();
        //成功设置信息
        loginBean.setUserName(privilageUserDO.getName());
        loginBean.setUserId(privilageUserDO.getId());
        loginBean.setRoleId(privilageUserDO.getId());
        loginBean.setRoleCode(roleDO.getCode());
        loginBean.setStoreId(storeId);
        if (StringUtils.isNotBlank(roleDO.getCode()) && !MINI_ROLE_CODE.contains(roleDO.getCode())){
            return new LoginBean(Constants.ERROR_ROLE_NO_PERMISSION);
        }
        loginBean.setLogin(cpUserId);
        loginInfoMap.put("code", LoginEnum.LOGIN_SUCCEED.getCode());
        loginBean.setLoginInfo(loginInfoMap);
        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<>(4);

        Map<String, String> codeInfo = qwMailListManageService.getCpUserIdByCode(code);
        result.put("cpUserId",codeInfo.get("cpUserId"));
        result.put("sessionKey",codeInfo.get("sessionKey"));
        Map<String, Object> selectAccountMap = new HashMap<>();
        selectAccountMap.put("login", codeInfo.get("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;
    }
}
