package com.ruoyi.controller;


import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.exception.enums.CoreExceptionEnum;
import com.ruoyi.controller.req.LoginReqVo;
import com.ruoyi.enums.LoginEnums;
import com.ruoyi.enums.sms.SmsEnums;
import com.ruoyi.response.ResponseData;
import com.ruoyi.utils.BusinessUtil;
import com.ruoyi.utils.JudgeLogicUtil;
import com.ruoyi.vo.UserVo;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.crypto.Cipher;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

/**
 * 登陆类
 * @author liwenlong
 */
@Slf4j
@CrossOrigin
@RestController
@RequestMapping("/api")
@Api(tags = "登录类")
public class ApiLoginController {


    @Value("${decryptPhone.url}")
    private String url;

    @Value("${decryptPhone.app_key}")
    private String app_key;

    @Value("${decryptPhone.master_Key}")
    private String master_Key;

    @Value("${decryptPhone.private_key}")
    private String private_key;


    @Autowired
    private BusinessUtil businessUtil;

    @Autowired
    private JudgeLogicUtil judgeLogicUtil;

    @Autowired
    private StringRedisTemplate redisTemplate;


    /**
     * 登陆
     *
     * @return
     */
    @PostMapping("/login")
    public ResponseData login(@RequestBody LoginReqVo loginReqVo) {

        //登录方式  1 验证码 2 密码 3 一键登录 4 微信登录 5 小程序登录 6 苹果登录
        switch (LoginEnums.getLoginEnums(loginReqVo.getType())) {
            case code_login:
                return codeLogin(loginReqVo);
            case pwd_login:
                return pwdLogin(loginReqVo);
            case one_click_login:
                return oneClickLogin(loginReqVo);
            case wechat_login:
                return wxChatOpenidLogin(loginReqVo);
            case applet_login:
                return wechatAppletOpenid(loginReqVo);
            case apple_login:
                return appleOpenidLogin(loginReqVo);
            default:
                return ResponseData.error(CoreExceptionEnum.ERROR_PARAM);
        }
    }

    /**
     * 验证码登入
     *
     * @param loginReqVo
     * @return
     */
    private ResponseData codeLogin(LoginReqVo loginReqVo) {

        //验证码——验证
        businessUtil.checkCode(loginReqVo.getCode(), SmsEnums.LOGIN, loginReqVo.getAreaCode(),loginReqVo.getAccount(), loginReqVo.getUserType());

        //验证登入账号
        Long userId = judgeLogicUtil.checkLoginUser(loginReqVo);

        return businessUtil.getToken(userId, loginReqVo.getUserType());
    }


    /**
     * 密码
     *
     * @param loginReqVo
     * @return
     */
    private ResponseData pwdLogin(LoginReqVo loginReqVo) {
        //验证登入账号
        Long userId = judgeLogicUtil.checkLoginUser(loginReqVo);

        //验证密码
        if (!businessUtil.loginPwdTrue(new UserVo(loginReqVo.getUserType(),userId), loginReqVo.getPassword())) {
            return ResponseData.error(CoreExceptionEnum.PWD_ERROR);
        }
        return businessUtil.getToken(userId, loginReqVo.getUserType());
    }


    /**
     * 一键登入
     *
     * @param loginReqVo
     * @return
     */
    private ResponseData oneClickLogin(LoginReqVo loginReqVo) {

        // 获取并解密手机号
        String phone = decryptPhone(loginReqVo.getLoginToken());
        loginReqVo.setMobile(phone);

        //验证登入账号
        Long userId = judgeLogicUtil.checkLoginUser(loginReqVo);

        return businessUtil.getToken(userId, loginReqVo.getUserType());
    }


    /**
     * 微信登入
     *
     * @param loginReqVo
     * @return
     */
    private ResponseData wxChatOpenidLogin(LoginReqVo loginReqVo) {

        if (ObjectUtil.isNotEmpty(loginReqVo.getCode())) {
            //验证码——验证
            businessUtil.checkCode(loginReqVo.getCode(), SmsEnums.WX_LOGIN_BIND, loginReqVo.getAreaCode(),loginReqVo.getMobile(), loginReqVo.getUserType());
        }

        //验证登入账号,
        Long userId = judgeLogicUtil.checkLoginUser(loginReqVo);

        return businessUtil.getToken(userId, loginReqVo.getUserType());
    }

    /**
     * 微信小程序登入
     *
     * @param loginReqVo
     * @return
     */
    private ResponseData wechatAppletOpenid(LoginReqVo loginReqVo) {

        if (ObjectUtil.isNotEmpty(loginReqVo.getAccount())) {
            //验证码——验证
            businessUtil.checkCode(loginReqVo.getCode(), SmsEnums.WX_APPLET_LOGIN_BIND, loginReqVo.getAreaCode(),loginReqVo.getMobile(), loginReqVo.getUserType());
        }

        //验证登入账号,
        Long userId = judgeLogicUtil.checkLoginUser(loginReqVo);

        return businessUtil.getToken(userId, loginReqVo.getUserType());
    }

    /**
     * 苹果登入
     *
     * @param loginReqVo
     * @return
     */
    private ResponseData appleOpenidLogin(LoginReqVo loginReqVo) {

        if (ObjectUtil.isNotEmpty(loginReqVo.getAccount())) {
            //验证码——验证
            businessUtil.checkCode(loginReqVo.getCode(), SmsEnums.LOGIN, loginReqVo.getAreaCode(),loginReqVo.getMobile(), loginReqVo.getUserType());
        }

        //验证登入账号,
        Long userId = judgeLogicUtil.checkLoginUser(loginReqVo);



        return businessUtil.getToken(userId, loginReqVo.getUserType());
    }


    /**
     * 获取并解密手机号
     *
     * @param loginToken
     * @return
     */
    private String decryptPhone(String loginToken) {
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("loginToken", loginToken);
            JSONObject jsonObject1 = JSONObject.parseObject((doPostForJpush(jsonObject.toString())));
            System.out.println("code==" + jsonObject1.getInteger("code"));
            System.out.println("phone==" + jsonObject1.getString("phone"));
            if (8000 == jsonObject1.getInteger("code")) {
                PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(private_key));
                PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec);
                Cipher cipher = Cipher.getInstance("RSA");
                cipher.init(Cipher.DECRYPT_MODE, privateKey);
                byte[] b = Base64.getDecoder().decode(jsonObject1.getString("phone"));
                System.out.println("解密后phone==" + new String(cipher.doFinal(b)));
                return new String(cipher.doFinal(b));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    private String doPostForJpush(String JSONBody) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("Authorization", "Basic " + new String(Base64.getEncoder().encode((app_key + ":" + master_Key).getBytes())));
        StringEntity entity = new StringEntity(JSONBody, "UTF-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(httpPost);
            StatusLine status = response.getStatusLine();
            int state = status.getStatusCode();
            if (state == HttpStatus.SC_OK) {
                HttpEntity responseEntity = response.getEntity();
                String jsonString = EntityUtils.toString(responseEntity, "UTF-8");
                return jsonString;
            } else {
                HttpEntity responseEntity = response.getEntity();
                String jsonString = EntityUtils.toString(responseEntity);
                System.out.println(jsonString);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

}