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.controller.userpoints.config.NumberOfUserPoints;
import com.mmc.iuav.user.controller.userpoints.config.UserPointsEnum;
import com.mmc.iuav.user.dao.*;
import com.mmc.iuav.user.dao.userpoints.UserPointsDao;
import com.mmc.iuav.user.dao.userpoints.UserPointsDetailsDao;
import com.mmc.iuav.user.entity.*;
import com.mmc.iuav.user.entity.userpoints.UserPointsDO;
import com.mmc.iuav.user.entity.userpoints.UserPointsDetails;
import com.mmc.iuav.user.enums.UserAccountStatus;
import com.mmc.iuav.user.model.dto.LoginSuccessDTO;
import com.mmc.iuav.user.model.qo.webLogin.LoginUserQO;
import com.mmc.iuav.user.model.vo.*;
import com.mmc.iuav.user.model.vo.userpoints.UserPointsVO;
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.Map;
import java.util.concurrent.TimeUnit;

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

    @Autowired
    private UserServiceDao userServiceDao;
    @Autowired
    private CooperationDao cooperationDao;
    @Autowired
    private ActivityService activityService;
    @Autowired
    private UserPointsDao userPointsDao;
    @Autowired
    private UserPointsDetailsDao userPointsDetailsDao;
    @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;
        log.info("登录信息:{}",   wxLoginVO);
        log.info("上级推荐人:{}",   wxLoginVO.getRcdUserId());
        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;
        Boolean isNewPilot = true;
        if (userAccountVO == null) {
            UserAccountDO userAccountDO = new UserAccountDO();
            userAccountDO.setUnionId(unionId);
            userAccountDO.setOpenId(openId);
            userAccountDO.setPortType(100);
            userAccountDO.setSource(wxLoginVO.getSource());
//            userAccountService.insertUserAccount(userAccountDO);
            userServiceDao.insertUserAccount(userAccountDO);
            userAccountVO = userAccountDO.buildUserAccountVO();
            // 创建用户钱包
            payWalletService.initPayWallet(userAccountDO.getId());

            payClient.createWallet(userAccountDO.getId());
            // 查询之前有没有实名过
            RealNameAuthDO nameAuthByUnionId = realNameAuthDao.getRealNameAuthByUnionId(unionId);
            if (nameAuthByUnionId != null) {
                nameAuthByUnionId.setUserAccountId(userAccountDO.getId());
//                nameAuthByUnionId.setId(null);
                realNameAuthDao.updateRealNameAuth(nameAuthByUnionId);
            }
            log.info("用户的id是=====》{}",userAccountDO.getId());
        } else {
            CompanyAuthDO companyAuthDO = companyAuthDao.getCompanyAuth(userAccountVO.getId());
            companyAuthStatus = companyAuthDO == null ? 0 : 1;
            isNewPilot = false;
        }
        AppUserSucVO appUserSucVO = authHandler.addAppLoginCache(userAccountVO);
        appUserSucVO.setAuthStatus(companyAuthStatus);
        appUserSucVO.setSessionKey(sessionKey);
        log.info("判断是不是新用户 =====》 {}",isNewPilot);
        //判断是不是新用户只有新用户才会执行添加积分代码
        if(!isNewPilot) {
            return ResultBody.success(appUserSucVO);
        }

        Integer id = appUserSucVO.getUserAccountId();
        Integer rcdUserId = wxLoginVO.getRcdUserId();
        Integer countUser = userServiceDao.getCountUser(rcdUserId);

        if (countUser != null && countUser !=0) {
//        if (rcdUserId != null) {
            UserRcdDO userRcd = new UserRcdDO();
            userRcd.setUserAccountId(id);
            userRcd.setRcdUserId(rcdUserId);
            userServiceDao.insertUserRcd(userRcd);
        }

        /**
         * 积分
         */
        extracted(id);
        RealNameAuthDO realNameAuthByUId = realNameAuthDao.getRealNameAuthByUId(id);
        if (realNameAuthByUId != null && realNameAuthByUId.getCheckStatus() == 1) {
            realNameextracted(id);
        }
        // 奖励邀请人
        if (rcdUserId != null) {
            activityService.participateActivity(0, rcdUserId, id);
        }

        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);
        }
        Integer tagId = cooperationDao.selectTagIdByBackUserId(user.getId());
        BackUserAccountVO backUserAccountVO = user.buildBackUserAccountVO();
        backUserAccountVO.setCooperationTagId(tagId);
        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);
    }

    @Override
    public ResultBody webRegister(WebRegisterVO webRegisterVO) {
        Map<Object, Object> redisData = stringRedisTemplate.opsForHash().entries(webRegisterVO.getCode() + webRegisterVO.getPhoneNum());
        if (redisData.isEmpty()) {
            return ResultBody.error("验证码错误,请重新输入");
        }
        String code = redisData.get("verifyCode").toString();
        String phoneNum = redisData.get("phoneNum").toString();
        // 验证码错误则修改失败，并提醒
        if (!code.equals(webRegisterVO.getCode())) {
            return ResultBody.error("验证码错误,请重新输入");
        }
        UserAccountDO userAccountDO = userServiceDao.getUserByPhoneNum(phoneNum);
        // 小程序未登录过或者未绑定过手机号
        if (userAccountDO == null){
            userAccountDO = new UserAccountDO();
            userAccountDO.setPhoneNum(webRegisterVO.getPhoneNum());
            try {
                userAccountDO.setPassword(PwdUtil.securityPwd(webRegisterVO.getPassword()));
            } catch (NoSuchAlgorithmException e) {
                return ResultBody.error(ResultEnum.PWD_CREATE_ERROR);
            }
            userServiceDao.insertUserAccount1(userAccountDO);
            userAccountDO.setNickName("云享飞用户_"+ userAccountDO.getId());
            userAccountDO.setUserImg("https://file.iuav.com/file/sharefly-logo-2024.png");
            userServiceDao.update(userAccountDO);
        }else if(userAccountDO.getPassword() == null){
            //小程序登录过且绑定过手机号
            try {
                userAccountDO.setPassword(PwdUtil.securityPwd(webRegisterVO.getPassword()));
            } catch (NoSuchAlgorithmException e) {
                return ResultBody.error(ResultEnum.PWD_CREATE_ERROR);
            }
            userServiceDao.update(userAccountDO);
        }else{
            return ResultBody.error("已经注册过，请直接登录");
        }
        return ResultBody.success();
    }

    @Override
    public ResultBody webLogin(LoginUserQO param) {
        UserAccountVO user = userAccountService.getUserAccountInfoByPhoneNum(param.getAccountNo());
        //查询用户信息
//        BackUserAccountDO user = backUserAccountService.getUserLoginInfo(param.getAccountNo(), param.getPassWord());
        if (user == null) {
            return ResultBody.error(ResultEnum.LOGIN_ACCOUNT_NOT_EXIT_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);
        }
        WebUserSucVO webUserSucVO = authHandler.addWebLoginCache(user);
        return ResultBody.success(webUserSucVO);
    }

    @Override
    public ResultBody updatePassword(WebRegisterVO webRegisterVO){
        Map<Object, Object> redisData = stringRedisTemplate.opsForHash().entries(webRegisterVO.getCode() + webRegisterVO.getPhoneNum());
        String code = redisData.get("verifyCode").toString();
        String phoneNum = redisData.get("phoneNum").toString();
        UserAccountVO user = userAccountService.getUserAccountInfoByPhoneNum(phoneNum);
        String oldPassword = user.getPassword();
        String newPassword = "";
        UserAccountDO userAccountDO = userServiceDao.getUserByPhoneNum(phoneNum);
        if(userAccountDO == null || oldPassword == null){
            return ResultBody.error("未注册过，请先注册");
        }
        try {
            newPassword = PwdUtil.securityPwd(webRegisterVO.getPassword());
        }catch (NoSuchAlgorithmException e) {
            return ResultBody.error(ResultEnum.PWD_CONPARED_ERROR);
        }
        if (redisData.isEmpty()) {
            return ResultBody.error("验证码错误,请重新输入");
        }
        if(oldPassword.equals(newPassword)) {
            return ResultBody.error(ResultEnum.PWD_NOT_SAME_ERROR);
        }


        // 验证码错误则修改失败，并提醒
        if (!code.equals(webRegisterVO.getCode())) {
            return ResultBody.error("验证码错误,请重新输入");
        }
        UserAccountDO updatePasswordDO = new UserAccountDO();
        updatePasswordDO.setPassword(newPassword);
        updatePasswordDO.setId(userAccountDO.getId());;
        userServiceDao.update(updatePasswordDO) ;

        return ResultBody.success();
    }


    private void extracted(Integer id) {
        UserPointsVO userPointsVO = new UserPointsVO(id, NumberOfUserPoints.match(0).getMessage());
        //积分
        UserPointsDO pointsDO = userPointsDao.selectUserPoints(userPointsVO.getUserAccountId());
        UserPointsDO points = null;
        if (pointsDO != null) {
            Integer totalPoints = userPointsVO.getTotalPoints();
            Integer totalPoints1 = pointsDO.getTotalPoints();
            totalPoints += totalPoints1;
            userPointsVO.setTotalPoints(totalPoints);
            points = new UserPointsDO(userPointsVO);
            userPointsDao.updatePoints(points);
        } else if (pointsDO == null) {
            points = new UserPointsDO(userPointsVO);
            userPointsDao.insertPoints(points);
        }
        UserPointsDetails userPointsDetails = new UserPointsDetails(id, NumberOfUserPoints.match(0).getMessage(), UserPointsEnum.match(0).getMessage());
        userPointsDetailsDao.insertPointsDetails(userPointsDetails);
    }

    private void realNameextracted(Integer id) {
        UserPointsVO userPointsVO = new UserPointsVO(id, NumberOfUserPoints.match(1).getMessage());
        //积分
        UserPointsDO pointsDO = userPointsDao.selectUserPoints(userPointsVO.getUserAccountId());
        UserPointsDO points = null;
        if (pointsDO != null) {
            Integer totalPoints = userPointsVO.getTotalPoints();
            Integer totalPoints1 = pointsDO.getTotalPoints();
            totalPoints += totalPoints1;
            userPointsVO.setTotalPoints(totalPoints);
            points = new UserPointsDO(userPointsVO);
            userPointsDao.updatePoints(points);
        } else if (pointsDO == null) {
            points = new UserPointsDO(userPointsVO);
            userPointsDao.insertPoints(points);
        }
        UserPointsDetails userPointsDetails = new UserPointsDetails(id, NumberOfUserPoints.match(1).getMessage(), UserPointsEnum.match(1).getMessage());
        userPointsDetailsDao.insertPointsDetails(userPointsDetails);
    }
}
