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

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.mmc.iuav.auth.JwtConstant;
import com.mmc.iuav.response.ResultBody;
import com.mmc.iuav.response.ResultEnum;
import com.mmc.iuav.user.auth.AuthHandler;
import com.mmc.iuav.user.auth.PwdUtil;
import com.mmc.iuav.user.client.PayClient;
import com.mmc.iuav.user.constant.WxConstant;
import com.mmc.iuav.user.dao.CompanyAuthDao;
import com.mmc.iuav.user.dao.RealNameAuthDao;
import com.mmc.iuav.user.dao.RoleDao;
import com.mmc.iuav.user.entity.*;
import com.mmc.iuav.user.enums.UserAccountStatus;
import com.mmc.iuav.user.model.dto.LoginSuccessDTO;
import com.mmc.iuav.user.model.qo.LoginUserQO;
import com.mmc.iuav.user.model.vo.*;
import com.mmc.iuav.user.service.*;
import com.mmc.iuav.user.service.wallet.PayWalletService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.TimeUnit;

/**
 * @author: zj
 * @Date: 2023/5/16 13:51
 */
@Slf4j
@Service
public class AuthServiceImpl implements AuthService {

    @Autowired
    private WxService wxService;

    @Autowired
    private UserAccountService userAccountService;

    @Autowired
    private BackUserAccountService backUserAccountService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private CompanyAuthDao companyAuthDao;

    @Autowired
    private RoleDao roleDao;

    @Autowired
    private RealNameAuthDao realNameAuthDao;

    @Autowired
    private CompanyService companyService;

    @Autowired
    private PayClient payClient;

    @Autowired
    private AuthHandler authHandler;

    @Resource
    private PayWalletService payWalletService;

    @Transactional
    @Override

    public ResultBody appletLogin(WxLoginVO wxLoginVO) {
        String unionId;
        String openId;
        String sessionKey;
        if (wxLoginVO.getFromPort().toString().equals(WxConstant.APP.toString())) {
            //调用小程序登录接口，里面包含unionId
            String appWxJson = wxService.appLogin(wxLoginVO);
            if (StringUtils.isBlank(appWxJson)) {
                return ResultBody.error(ResultEnum.APPLET_PORT_TYPE_ERROR);
            }
            log.info("wx appLogin msg==>" + JSONObject.toJSONString(appWxJson));
            JSONObject json = JSON.parseObject(appWxJson);
            if (!json.containsKey(WxConstant.OPEN_ID) || !json.containsKey(WxConstant.SESSION_KEY)) {
                log.error("wx appLogin error==>" + JSONObject.toJSONString(json));
                return ResultBody.error(ResultEnum.APPLET_LOGIN_ERROR, json);
            }
            unionId = json.getString(WxConstant.UNION_ID);
            openId = json.getString(WxConstant.OPEN_ID);
            sessionKey = json.getString(WxConstant.SESSION_KEY);
        } else {
            return ResultBody.error(ResultEnum.PARAM_ERROR);
        }
        //数据库查询用户信息
        UserAccountVO userAccountVO = userAccountService.getUserAccountInfoByUnionId(unionId);
        Integer companyAuthStatus = 0;
        if (userAccountVO == null) {
            UserAccountDO userAccountDO = new UserAccountDO();
            userAccountDO.setUnionId(unionId);
            userAccountDO.setOpenId(openId);
            userAccountDO.setPortType(100);
            userAccountDO.setSource(wxLoginVO.getSource());
            userAccountService.insertUserAccount(userAccountDO);
            userAccountVO = userAccountDO.buildUserAccountVO();
            // 创建用户钱包
            payWalletService.initPayWallet(userAccountDO.getId());
            payClient.createWallet(userAccountDO.getId());
            // 查询之前有没有实名过
            RealNameAuthDO nameAuthByUnionId = realNameAuthDao.getRealNameAuthBakByUnionId(unionId);
            if (nameAuthByUnionId != null) {
                nameAuthByUnionId.setUserAccountId(userAccountDO.getId());
                nameAuthByUnionId.setId(null);
                realNameAuthDao.addRealNameAuth(nameAuthByUnionId);
            }
        } else {
            CompanyAuthDO companyAuthDO = companyAuthDao.getCompanyAuth(userAccountVO.getId());
            companyAuthStatus = companyAuthDO == null ? 0 : 1;
        }
        AppUserSucVO appUserSucVO = authHandler.addAppLoginCache(userAccountVO);
        appUserSucVO.setAuthStatus(companyAuthStatus);
        appUserSucVO.setSessionKey(sessionKey);
        return ResultBody.success(appUserSucVO);
    }

    @Override
    public ResultBody backEndLogin(LoginUserQO param) {
        //查询用户信息
        BackUserAccountDO user = backUserAccountService.getUserLoginInfo(param.getAccountNo(), param.getPassWord());
        if (user == null) {
            return ResultBody.error(ResultEnum.LOGIN_ACCOUNT_NOT_EXIT_ERROR);
        }
        if (user.getAccountStatus().equals(UserAccountStatus.DISABLE.getAccountStatus())) {
            return ResultBody.error(ResultEnum.FORBID_USE_ERROR);
        }
        String loginPwd = "";
        try {
            loginPwd = PwdUtil.securityPwd(param.getPassWord());
        } catch (NoSuchAlgorithmException e) {
            return ResultBody.error(ResultEnum.PWD_CONPARED_ERROR);
        }
        if (!loginPwd.equals(user.getPassword())) {
            return ResultBody.error(ResultEnum.LOGIN_PASSWORD_ERROR);
        }
        BackUserAccountVO backUserAccountVO = user.buildBackUserAccountVO();
        LoginSuccessDTO loginSuccessDTO = authHandler.addPcLoginCache(backUserAccountVO);
        return ResultBody.success(loginSuccessDTO);
    }

    @Override
    public ResultBody testAppletLogin(String unionId) {
        UserAccountVO userAccountVO = userAccountService.getUserAccountInfoByUnionId(unionId);
        if (userAccountVO != null) {
            AppUserSucVO appUserSucVO = authHandler.addAppLoginCache(userAccountVO);
            return ResultBody.success(appUserSucVO);
        }
        return ResultBody.error(ResultEnum.APPLET_LOGIN_ERROR);
    }

    @Override
    public ResultBody tempConfirmLogin(LoginSuccessDTO loginSuccessDTO, Integer port, String randomLoginCode) {

        if (port.equals(1)) {
            // 返回所属公司后台账号token
            CompanyInfoVO companyInfoVO = companyService.getAppCompanyInfoUId(loginSuccessDTO.getUserAccountId());
            if (companyInfoVO == null) {
                return ResultBody.error(ResultEnum.NOT_BINDING_COMPANY_ERROR);
            }
            // 查询所属单位
            CompanyBackUserDO companyBackUserDO = companyService.getCompanyBackUserByCompanyId(companyInfoVO.getId());
            if (companyBackUserDO == null) {
                return ResultBody.error(ResultEnum.NOT_BINDING_COMPANY_ERROR);
            }
            BackUserAccountVO backUserAccountVO = backUserAccountService.getBackUserAccountById(companyBackUserDO.getBackUserAccountId());
            if (backUserAccountVO.getDisable().equals(1)) {
                return ResultBody.error(ResultEnum.LOGIN_ACCOUNT_NOT_EXIT_ERROR);
            }
            LoginSuccessDTO backLoginSuccessDTO = authHandler.addPcLoginCache(backUserAccountVO);
            backLoginSuccessDTO.setAppUserAccountId(loginSuccessDTO.getUserAccountId());
            // 设置用户是否是管理员
            backLoginSuccessDTO.getCompanyInfoVO().setLeader(companyInfoVO.getLeader());
            // 设置后台账号token，key为randomLoginCode
            stringRedisTemplate.opsForValue().set(
                    randomLoginCode, JSONObject.toJSONString(backLoginSuccessDTO),
                    JwtConstant.EXPIRATION, TimeUnit.MILLISECONDS);
            // 重新设置后台账号token
            stringRedisTemplate.opsForValue().set(
                    backLoginSuccessDTO.getToken(), JSONObject.toJSONString(backLoginSuccessDTO),
                    JwtConstant.EXPIRATION, TimeUnit.MILLISECONDS);
        } else {
            stringRedisTemplate.opsForValue().set(
                    randomLoginCode, JSONObject.toJSONString(loginSuccessDTO),
                    JwtConstant.TEMP_EXPIRATION, TimeUnit.MILLISECONDS);
        }
        return ResultBody.success();
    }

    @Override
    public ResultBody getLoginInfo(String randomLoginCode) {
        String json = stringRedisTemplate.opsForValue().get(randomLoginCode);
        if (StringUtils.isBlank(json)) {
            return ResultBody.error(ResultEnum.APPLET_LOGIN_ERROR);
        }
        LoginSuccessDTO loginSuccessDTO = JSONObject.parseObject(json, LoginSuccessDTO.class);
        // 获取成功后删除
        stringRedisTemplate.delete(randomLoginCode);
        return ResultBody.success(loginSuccessDTO);
    }
}
