package com.ruoyi.wechat.controller;

import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.UserStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.wechat.domain.AppletLoginForm;
import com.ruoyi.wechat.utils.HttpClientUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.impl.client.HttpClients;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;


/**
 * @author tjf
 * @Date: 2022/04/15/11:18
 */
@RestController
@RequestMapping("/weChat")
public class WeChatLoginController {
    private static final Logger LOGGER = LoggerFactory.getLogger(WeChatLoginController.class);
    @Autowired
    private ISysUserService userService;

    @Autowired
    private SysPermissionService permissionService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private RedisCache redisCache;

    private final static long EXPIRE_TIME = Constants.TOKEN_EXPIRE * 60;

    private final static long EXPIRE_TIME_QR = 3 * 60;

    private final static String ACCESS_TOKEN = Constants.LOGIN_TOKEN_KEY;

    protected static final long MILLIS_SECOND = 1000;

    @Value("${auth.wechat.access_token_url}")
    private String access_token_url;

    @Value("${auth.wechat.phone_number_url}")
    private String phone_number_url;


    @Value("${auth.wechat.appid}")
    private String appid;

    @Value("${auth.wechat.secret}")
    private String secret;

    /**
     * 投资商端小程序登录获取手机号
     *
     * @param loginCode
     * @return
     */
    @PostMapping("/getPhone")
    public AjaxResult getPhone(@RequestBody AppletLoginForm loginCode) {
        String code = loginCode.getCode();
        if (StringUtils.isBlank(code)){
            return AjaxResult.error("未获取到code");
        }
        //grant_type=client_credential&appid=APPID&secret=APPSECRET
        String param = "grant_type=client_credential&appid=" + appid + "&secret=" + secret;
        String jsonStr = null;
        try {
            jsonStr = HttpClientUtils.doGet(access_token_url, param);
        } catch (IOException e) {
            return AjaxResult.error("获取小程序ACCESS_TOKEN失败");
        }
        JSONObject result = JSONObject.parseObject(jsonStr);
        if (StringUtils.isEmpty(result.toString())) {
            return AjaxResult.error("获取小程序ACCESS_TOKEN失败");
        }
        String accessToken = result.getString("access_token");
        if (StringUtils.isEmpty(accessToken)) {
            return AjaxResult.error(result.getString("errmsg"));
        }
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("access_token",accessToken);
        paramMap.put("code",code);
        //调用phonenumber.getPhoneNumber
        try {
            String jsonPhone = HttpClientUtils.doPost(phone_number_url, paramMap);
            if (StringUtils.isEmpty(jsonPhone)){
                return AjaxResult.error("获取小程序手机号失败");
            }
            JSONObject resultPhone = JSONObject.parseObject(jsonPhone);
            if (StringUtils.isEmpty(resultPhone.toJSONString())){
                return AjaxResult.error("获取小程序手机号失败");
            }
            if ("0".equals(resultPhone.getString("errmsg"))){
                String phone = resultPhone.getJSONObject("phone_info").getString("phoneNumber");
                return AjaxResult.success().put(Constants.PHONENUMBER, phone);
            }
        } catch (IOException e) {
            return AjaxResult.error("获取小程序手机号失败");
        }
        return AjaxResult.error("获取小程序手机号失败");
    }




    /**
     * 投资商端小程序登录
     *
     * @param loginCode
     * @return
     */
    @PostMapping("/login")
    public AjaxResult login(@RequestBody AppletLoginForm loginCode) {
        String phoneNumber = loginCode.getPhoneNumber();
        if (StringUtils.isBlank(phoneNumber)){
            return AjaxResult.error("未获取到手机号");
        }
        SysUser sysUser = userService.getByPhone(phoneNumber);
        LoginUser loginUser = loadUserByUsername(sysUser);

        //记录登录信息
        recordLoginInfo(loginUser.getUserId());
        // 生成token
        String token = tokenService.createToken(loginUser);
        return AjaxResult.success().put(Constants.TOKEN, token);
    }

    /**
     * 校验用户账户
     * @param sysUser
     * @return
     * @throws UsernameNotFoundException
     */
    public LoginUser loadUserByUsername(SysUser sysUser) throws UsernameNotFoundException
    {
        String userName = sysUser.getUserName();

        if (UserStatus.DELETED.getCode().equals(sysUser.getDelFlag()))
        {
            LOGGER.info("登录用户：{} 已被删除.", userName);
            throw new ServiceException("对不起，您的账号：" + userName + " 已被删除");
        }
        else if (UserStatus.DISABLE.getCode().equals(sysUser.getStatus()))
        {
            LOGGER.info("登录用户：{} 已被停用.", userName);
            throw new ServiceException("对不起，您的账号：" + userName + " 已停用");
        }
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        return createLoginUser(sysUser);
    }

    public LoginUser createLoginUser(SysUser user)
    {
        return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));
    }

    /**
     * 记录登录信息
     *
     * @param userId 用户ID
     */
    public void recordLoginInfo(Long userId)
    {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
        sysUser.setLoginDate(DateUtils.getNowDate());
        userService.updateUserProfile(sysUser);
    }
}
