package com.mmc.iuav.user.service.impl;

import com.mmc.iuav.http.BizException;
import com.mmc.iuav.page.PageResult;
import com.mmc.iuav.response.ResultBody;
import com.mmc.iuav.response.ResultEnum;
import com.mmc.iuav.user.auth.PwdUtil;
import com.mmc.iuav.user.client.ImsClient;
import com.mmc.iuav.user.client.OmsClient;
import com.mmc.iuav.user.client.PmsClient;
import com.mmc.iuav.user.constant.GeneralConstant;
import com.mmc.iuav.user.dao.BackUserAccountDao;
import com.mmc.iuav.user.dao.BackUserSuggestionDao;
import com.mmc.iuav.user.dao.CooperationDao;
import com.mmc.iuav.user.dao.RoleDao;
import com.mmc.iuav.user.dao.dronepilot.PilotCertificationDao;
import com.mmc.iuav.user.entity.*;
import com.mmc.iuav.user.enums.CompanyTypeEnums;
import com.mmc.iuav.user.enums.RoleEnums;
import com.mmc.iuav.user.model.dto.LoginSuccessDTO;
import com.mmc.iuav.user.model.qo.BUserAccountQO;
import com.mmc.iuav.user.model.vo.BUserAccountVO;
import com.mmc.iuav.user.model.vo.BackUserAccountVO;
import com.mmc.iuav.user.model.vo.CompanyInfoVO;
import com.mmc.iuav.user.model.vo.NewMessageVO;
import com.mmc.iuav.user.service.BackUserAccountService;
import com.mmc.iuav.user.service.CompanyService;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author: zj
 * @Date: 2023/6/21 15:48
 */
@Service
public class BackUserAccountServiceImpl implements BackUserAccountService {
    @Autowired
    private BackUserAccountDao backUserAccountDao;

    @Autowired
    private CompanyService companyService;

    @Autowired
    private RoleDao roleDao;

    @Autowired
    private CooperationDao cooperationDao;

    @Autowired
    private PilotCertificationDao certificationDao;

    @Autowired
    private BackUserSuggestionDao backUserSuggestionDao;
    @Autowired
    private OmsClient omsClient;

    @Autowired
    private ImsClient imsClient;

    @Autowired
    private PmsClient pmsClient;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Transactional
    @Override
    public ResultBody insertBAccount(BUserAccountVO bUserAccountVO, LoginSuccessDTO loginSuccessDTO) {
        if (loginSuccessDTO != null && loginSuccessDTO.getCompanyInfoVO().getCompanyType().equals(CompanyTypeEnums.FRANCHISEE.getType())) {
            return ResultBody.error(ResultEnum.NO_RIGHT_UPDATE_ERROR);
        }
        if (!bUserAccountVO.getPassWord().equals(bUserAccountVO.getAlertPwd())) {
            // 两次密码不一致
            return ResultBody.error(ResultEnum.PWD_ALERT_ERROR);
        }
        // 获取新增的账户名是否已经存在
        int count = backUserAccountDao.countUserAccountNo(null, bUserAccountVO.getAccountNo());
        if (count > 0) {
            return ResultBody.error(ResultEnum.ADD_USER_ACCOUNT_NAME_EXISTS);
        }
        if (bUserAccountVO.getRoleId().equals(RoleEnums.ADMIN.getId())) {
            return ResultBody.error(ResultEnum.ONLY_ONE_ADMIN_ERROR);
        }
        BackUserAccountDO backUserAccountDO = new BackUserAccountDO(bUserAccountVO);
        try {
            backUserAccountDO.setPassword(PwdUtil.securityPwd(bUserAccountVO.getPassWord()));
        } catch (NoSuchAlgorithmException e) {
            return ResultBody.error(ResultEnum.PWD_CREATE_ERROR);
        }
        ResultBody<CompanyInfoVO> companyInfoVOResultBody = companyService.getCompanyInfoById(bUserAccountVO.getCompanyId());
        CompanyInfoVO companyInfoVO = companyInfoVOResultBody.getResult();
        if (companyInfoVO != null && companyInfoVO.getCompanyType().equals(CompanyTypeEnums.FRANCHISEE.getType())) {
            // 绑定企业为加盟公司，不能生成多个账号
            int bindingCount = companyService.countCompanyBackUser(companyInfoVO.getId());
            CompanyBackUserDO companyBackDO = companyService.getCompanyBackUserByCompanyId(bUserAccountVO.getCompanyId());
            if (bindingCount > 0 && companyBackDO != null && !companyBackDO.getBackUserAccountId().equals(bUserAccountVO.getId())) {
                return ResultBody.error(ResultEnum.FRANCHISEE_ACCOUNT_MORE_THAN_ONE_ERROR);
            }
        }
        backUserAccountDao.insertBackUserAccount(backUserAccountDO);
        bUserAccountVO.setId(backUserAccountDO.getId());
        // 添加角色
        roleDao.insertUserRoleRel(backUserAccountDO.getId(), bUserAccountVO.getRoleId());
        // 添加单位信息
        if (bUserAccountVO.getCompanyId() != null) {
            CompanyBackUserDO companyBackUserDO = new CompanyBackUserDO();
            companyBackUserDO.setBackUserAccountId(backUserAccountDO.getId());
            companyBackUserDO.setCompanyInfoId(bUserAccountVO.getCompanyId());
            companyService.addCompanyBackUser(companyBackUserDO);
        }
        return ResultBody.success();
    }

    @Transactional
    @Override
    public ResultBody updateBAccount(BUserAccountVO bUserAccountVO, LoginSuccessDTO loginSuccessDTO) {
        // 判断账号是否重复
        if (!StringUtils.isEmpty(bUserAccountVO.getAccountNo())) {
            // 如果传入的名字不为空，就查找数据库，看名字是否重复
            int count = backUserAccountDao.countUserAccountNo(bUserAccountVO.getId(), bUserAccountVO.getAccountNo());
            if (count > 0) {
                throw new BizException(ResultEnum.UPDATE_USER_ACCOUNT_REPEAT);
            }
        }
        // 当前角色不是超级管理员，则不能修改为管理员账号
        RoleInfoDO roleInfoDO = roleDao.getRoleInfoByUserId(bUserAccountVO.getId());
        if (!roleInfoDO.getId().equals(RoleEnums.ADMIN.getId()) && bUserAccountVO.getRoleId().equals(RoleEnums.ADMIN.getId())) {
            return ResultBody.error(ResultEnum.ONLY_ONE_ADMIN_ERROR);
        }
        // 不能修改自己的角色
        if (loginSuccessDTO.getUserAccountId().toString().equals(bUserAccountVO.getId().toString())
                && !bUserAccountVO.getRoleId().toString().equals(roleInfoDO.getId())) {
            return ResultBody.error(ResultEnum.UPDATE_OWNER_ROLE_ERROR);
        }
        // 不能修改admin账号的角色
        if (bUserAccountVO.getId().equals(1) && !bUserAccountVO.getRoleId().equals(RoleEnums.ADMIN.getId())) {
            return ResultBody.error(ResultEnum.UPDATE_ADMIN_ROLE_ERROR);
        }
        ResultBody<CompanyInfoVO> companyInfoVOResultBody = companyService.getCompanyInfoById(bUserAccountVO.getCompanyId());
        CompanyInfoVO companyInfoVO = companyInfoVOResultBody.getResult();
        if (companyInfoVO != null && companyInfoVO.getCompanyType().equals(CompanyTypeEnums.FRANCHISEE.getType())) {
            // 绑定企业为加盟公司，不能生成多个账号
            int bindingCount = companyService.countCompanyBackUser(companyInfoVO.getId());
            CompanyBackUserDO companyBackDO = companyService.getCompanyBackUserByCompanyId(bUserAccountVO.getCompanyId());
            if (bindingCount > 0 && companyBackDO != null && !companyBackDO.getBackUserAccountId().equals(bUserAccountVO.getId())) {
                return ResultBody.error(ResultEnum.FRANCHISEE_ACCOUNT_MORE_THAN_ONE_ERROR);
            }
        }
        BackUserAccountDO userAccountDO = new BackUserAccountDO(bUserAccountVO);
        backUserAccountDao.updateBackUserAccount(userAccountDO);
        // 修改单位信息
        if (bUserAccountVO.getCompanyId() != null) {
            CompanyBackUserDO companyBackUserDO = new CompanyBackUserDO();
            companyBackUserDO.setBackUserAccountId(userAccountDO.getId());
            companyBackUserDO.setCompanyInfoId(bUserAccountVO.getCompanyId());
            companyService.updateCompanyBackUser(companyBackUserDO);
        }
        roleDao.updateUserRoleRel(bUserAccountVO.getId(), bUserAccountVO.getRoleId());
        return ResultBody.success();
    }

    @Transactional
    @Override
    public ResultBody disableBAccount(Integer accountId, LoginSuccessDTO loginSuccessDTO) {
        CompanyInfoVO companyInfoVO = companyService.getCompanyInfoByBackUserAccountId(accountId);
        if (!loginSuccessDTO.getRoleInfo().getSuperAdmin().equals(RoleEnums.ADMIN.getId())) {
            return ResultBody.error(ResultEnum.NO_RIGHT_UPDATE_ERROR);
        }
        BackUserAccountDO backUserAccountDO = backUserAccountDao.getBackUserAccountDO(accountId);
        RoleInfoDO roleInfoDO = roleDao.getRoleInfoByUserId(accountId);
        if (roleInfoDO.getSuperAdmin().equals(RoleEnums.ADMIN.getId())) {
            return ResultBody.error(ResultEnum.DELETE_ADMIN_ERROR);
        }
        if (accountId.toString().equals(loginSuccessDTO.getUserAccountId().toString())) {
            return ResultBody.error(ResultEnum.DELETE_YOURSELF_ERROR);
        }
        if (companyInfoVO != null && companyInfoVO.getCompanyType().equals(CompanyTypeEnums.FRANCHISEE.getType())) {
            // 加盟企业的账号，需要把对应的成员和后台账号解绑
            companyService.unbindingAllUsers(companyInfoVO.getId());
        }
        String accountNo = "DISABLE_" + backUserAccountDO.getAccountNo() + RandomStringUtils.randomAlphanumeric(3);
        backUserAccountDao.disableBackUserAccountDO(accountId, accountNo);
        pmsClient.removeMallGoods(accountId, companyInfoVO.getId(), null);
        return ResultBody.success();
    }

    @Override
    public ResultBody<BackUserAccountVO> listBAccountPage(BUserAccountQO param, LoginSuccessDTO loginSuccessDTO) {
        if (loginSuccessDTO.getCompanyInfoVO().getCompanyType().equals(CompanyTypeEnums.FRANCHISEE.getType())) {
            param.setCompanyInfoId(loginSuccessDTO.getCompanyInfoVO().getId());
        }
        int count = backUserAccountDao.countListBackUserAccount(param);
        if (count == 0) {
            return ResultBody.success(PageResult.buildPage(param.getPageNo(), param.getPageSize(), count));
        }
        Integer pageNo = param.getPageNo();
        param.buildCurrentPage();
        List<BackUserAccountDO> users = backUserAccountDao.listBackUserAccount(param);
        List<Integer> backUserIds = users.stream().map(BackUserAccountDO::getId).collect(Collectors.toList());
        List<BackUserAccountVO> collect = users.stream().map(BackUserAccountDO::buildBackUserAccountVO).collect(Collectors.toList());
        List<CompanyInfoDO> companyInfoDOList = companyService.listCompanyInfoByUID(backUserIds);
        if (!companyInfoDOList.isEmpty()) {
            Map<Integer, CompanyInfoDO> userCompanyNameMap = companyInfoDOList.stream().collect(Collectors.toMap(CompanyInfoDO::getBackUserAccountId, k -> k, (v1, v2) -> v2));
            collect.forEach(d -> {
                CompanyInfoDO companyInfoDO = userCompanyNameMap.get(d.getId());
                if (companyInfoDO != null) {
                    d.setCompanyName(companyInfoDO.getCompanyName());
                    d.setCompanyInfoVO(companyInfoDO.buildCompanyInfoVO());
                }
            });
        }
        return ResultBody.success(PageResult.buildPage(pageNo, param.getPageSize(), count, collect));
    }

    @Override
    public List<BackUserAccountVO> feignListBAccountPage(BUserAccountQO bUserAccountQO) {
        List<BackUserAccountDO> list = backUserAccountDao.feignListBackUserAccount(bUserAccountQO);
        if (list == null) {
            return null;
        }
        List<BackUserAccountVO> accountSimpleDTOS = list.stream().map(BackUserAccountDO::buildBackUserAccountVO).collect(Collectors.toList());
        List<CompanyInfoVO> companyInfoVOS = companyService.listCompanyInfoByBUIds(bUserAccountQO.getUserIds());
        if (!CollectionUtils.isEmpty(companyInfoVOS)) {
            Map<Integer, CompanyInfoVO> userCom = companyInfoVOS.stream().collect(Collectors.toMap(CompanyInfoVO::getBackUserAccountId, v -> v, (v1, v2) -> v2));
            for (BackUserAccountVO accountSimpleDTO : accountSimpleDTOS) {
                if (userCom.containsKey(accountSimpleDTO.getId())) {
                    accountSimpleDTO.setCompanyName(userCom.get(accountSimpleDTO.getId()).getCompanyName());
                }
            }
        }
        return accountSimpleDTOS;
    }

    @Override
    public ResultBody updatePassword(BUserAccountVO account, LoginSuccessDTO loginSuccessDTO) {
        if (loginSuccessDTO.getAppUserAccountId() != null) {
            CompanyInfoVO appCompanyInfoUId = companyService.getAppCompanyInfoUId(loginSuccessDTO.getAppUserAccountId());
            if (!appCompanyInfoUId.getLeader().equals(1)) {
                return ResultBody.error(ResultEnum.NO_RIGHT_UPDATE_ERROR);
            }
        }
        if (!account.getPassWord().equals(account.getAlertPwd())) {
            return ResultBody.error(ResultEnum.PASSWORD_INCONSISTENT);
        }
        try {
            account.setPassWord(PwdUtil.securityPwd(account.getPassWord()));
            backUserAccountDao.updatePassword(account.getId(), account.getPassWord());
        } catch (NoSuchAlgorithmException e) {
            return ResultBody.error(ResultEnum.PWD_CONPARED_ERROR);
        }
        return ResultBody.success();
    }

    @Override
    public ResultBody feignAuthUserPwd(Integer id, String authPwd) {
        BackUserAccountDO account = backUserAccountDao.getAuthUserPwd(id);
        if (account == null) {
            return ResultBody.error(ResultEnum.LOGIN_ACCOUNT_NOT_EXIT_ERROR);
        }
        String pwd = "";
        try {
            pwd = PwdUtil.securityPwd(authPwd);
        } catch (NoSuchAlgorithmException e) {
            return ResultBody.error(ResultEnum.PWD_CREATE_ERROR);
        }
        if (!pwd.equals(account.getPassword())) {
            return ResultBody.error(ResultEnum.PWD_CONPARED_ERROR);
        }
        return ResultBody.success();
    }

    @Override
    public BackUserAccountDO getUserLoginInfo(String accountNo, String passWord) {
        BackUserAccountDO userLoginInfo = backUserAccountDao.getUserLoginInfo(accountNo, passWord);
        return userLoginInfo;
    }

    @Override
    public BackUserAccountVO getBackUserAccountById(Integer backUserAccountId) {
        BackUserAccountDO backUserAccountDO = backUserAccountDao.getBackUserAccountDO(backUserAccountId);
        if (backUserAccountDO != null) {
            CompanyInfoVO companyInfoVO = companyService.getCompanyInfoByBackUserAccountId(backUserAccountId);
            BackUserAccountVO backUserAccountVO = backUserAccountDO.buildBackUserAccountVO();
            backUserAccountVO.setCompanyInfoVO(companyInfoVO);
            return backUserAccountVO;
        }
        return null;
    }

    @Override
    public ResultBody getMessage() {
        NewMessageVO newMessageVO = new NewMessageVO();
        newMessageVO.setPilotMessage(certificationDao.getPilotAuditSum(0));
        newMessageVO.setJoinApplyMessage(cooperationDao.getAuditSum(0));

        List<Integer> list = (List<Integer>) omsClient.getCountNewOrder();
        newMessageVO.setOrderMessage(list.get(0));
        newMessageVO.setPointsMallMessage(list.get(1));
        newMessageVO.setDynamicMessage(imsClient.getDynamicMessageSum());

        String stringNumber = stringRedisTemplate.opsForValue().get(GeneralConstant.PARTNER_NOT_VIEWED);
        if(stringNumber == null){
            stringNumber = "0";
        }
        newMessageVO.setUserStateMessage(stringNumber);
        return ResultBody.success(newMessageVO);
    }

    @Override
    public ResultBody insertCompanySuggestion(BackUserSuggestionDO backUserSuggestionDO,Integer backUserId) {
        backUserSuggestionDO.setBackUserId(backUserId);
        if(backUserSuggestionDO.getId() != null) {
            backUserSuggestionDao.updateByPrimaryKeySelective(backUserSuggestionDO);
            return ResultBody.success();
        }
        backUserSuggestionDao.insertSelective(backUserSuggestionDO);
        return ResultBody.success();
    }

    @Override
    public ResultBody getSuggestion(Integer backUserId) {
        List<BackUserSuggestionDO> backUserSuggestionDO = backUserSuggestionDao.selectByPrimaryKey(backUserId);
        return ResultBody.success(backUserSuggestionDO);
    }

    @Override
    public ResultBody deleteSuggestion(Integer id) {
        backUserSuggestionDao.deleteByPrimaryKey(id);
        return ResultBody.success();
    }

}
