package com.seer.teach.user.app.auth.service.strategy;

import cn.dev33.satoken.stp.StpUtil;
import com.seer.teach.common.enums.ResultCodeEnum;
import com.seer.teach.common.exception.CommonException;
import com.seer.teach.common.utils.AssertUtils;
import com.seer.teach.common.utils.CommonUtils;
import com.seer.teach.mp.api.WechatOfficialAccountApi;
import com.seer.teach.mp.api.resp.WxOAuth2AccessTokenDTO;
import com.seer.teach.user.app.auth.LoginType;
import com.seer.teach.user.app.auth.request.LoginParam;
import com.seer.teach.user.app.auth.service.LoginStrategy;
import com.seer.teach.user.app.auth.service.LoginUser;
import com.seer.teach.user.entity.UserAuthEntity;
import com.seer.teach.user.entity.UserEntity;
import com.seer.teach.user.service.IUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Objects;

/**
 * 账号密码登录策略
 * 实现传统的用户名/手机号和密码登录，并生成token
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class OfficialOauthWithAccountLoginStrategy extends AbstractLoginStrategy implements LoginStrategy {

    private final IUserService userService;
    
    @Autowired
    private WechatOfficialAccountApi wechatOfficialAccountApi;

    @Override
    public LoginType getType() {
        return LoginType.WECHAT_OAUTH_WITH_ACCOUNT;
    }

    @Override
    public LoginUser authenticate(LoginParam request) {
        UserEntity accountUser = null;
        if (request.getUserName() != null && !request.getUserName().isEmpty()) {
            accountUser = userService.getOneByUserName(request.getUserName());
        } else if (request.getPhoneNumber() != null && !request.getPhoneNumber().isEmpty()) {
            accountUser = userService.getOneByMobile(request.getPhoneNumber());
        }
        AssertUtils.notNull(accountUser, ResultCodeEnum.USERNAME_OR_PASSWORD_IS_ERROR);
        String password = CommonUtils.encryptPassword(request.getPassword());
        if (password.equals(accountUser.getPassword())) {
            WxOAuth2AccessTokenDTO wxOAuth2AccessToken = wechatOfficialAccountApi.getUserWxOAuth2AccessToken(request.getAppId(), request.getJsCode());
            log.debug("获取用户信息：{}",wxOAuth2AccessToken);
            AssertUtils.notNull(wxOAuth2AccessToken, ResultCodeEnum.WX_OAUTH_USED_ERROR);
            String userOpenId = wxOAuth2AccessToken.getOpenId();
            UserAuthEntity userAuth = userAuthService.getOneByOpenId(userOpenId);
            StpUtil.login(accountUser.getId());
            if(Objects.isNull(userAuth)){
                boolean userAuthSaved = saveUserAuth(getType().getCode(), accountUser.getId(), wxOAuth2AccessToken, request.getAppId());
                log.info("保存用户授权信息：{}", userAuthSaved);
            }else{
                userAuth.setAppId(request.getAppId());
                updateUserAuth(userAuth);
            }
            log.info("用户[{}]账号密码登录成功", accountUser.getId());
            return new LoginUser(accountUser.getId());
        }else{
            log.info("用户[{}]账号密码登录失败", accountUser.getId());
            throw new CommonException(ResultCodeEnum.USERNAME_OR_PASSWORD_IS_ERROR);
        }

    }
}