package com.cweb.controller;

import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.hfkj.common.alipay.AlipayUtils;
import com.hfkj.common.exception.ErrorCode;
import com.hfkj.common.exception.ErrorHelp;
import com.hfkj.common.exception.SysCode;
import com.hfkj.common.pay.util.SignatureUtil;
import com.hfkj.common.security.UserCenter;
import com.hfkj.common.utils.HttpsUtils;
import com.hfkj.common.utils.MemberValidateUtil;
import com.hfkj.common.utils.RedisUtil;
import com.hfkj.common.utils.ResponseMsgUtil;
import com.hfkj.config.CommonSysConst;
import com.hfkj.config.WxMaConfiguration;
import com.hfkj.entity.BsAgentApiParam;
import com.hfkj.entity.BsDiscountUser;
import com.hfkj.model.ResponseData;
import com.hfkj.model.SecUserSessionObject;
import com.hfkj.model.UserSessionObject;
import com.hfkj.service.agent.BsAgentApiParamService;
import com.hfkj.service.discount.BsDiscountUserService;
import com.hfkj.service.user.BsUserService;
import com.hfkj.sysenum.discount.DiscountUserStatusEnum;
import com.hfkj.sysenum.user.UserLoginPlatform;
import com.hfkj.sysenum.user.UserLoginType;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

/**
 * @className: BsUserController
 * @author: HuRui
 * @date: 2024/6/11
 **/
@Controller
@RequestMapping(value = "/user")
@Api(value = "登录业务")
public class BsUserController {
    private static Logger log = LoggerFactory.getLogger(BsUserController.class);
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private UserCenter userCenter;
    @Resource
    private BsAgentApiParamService agentApiParamService;
    @Resource
    private BsDiscountUserService discountUserService;
    @Resource
    private BsUserService userService;

    @RequestMapping(value = "/autoLogin", method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value = "自动登录并注册")
    public ResponseData autoLogin(@RequestBody JSONObject body) {
        try {
            if (body == null
                    || StringUtils.isBlank(body.getString("appid"))
                    || StringUtils.isBlank(body.getString("phone"))
                    || StringUtils.isBlank(body.getString("sign"))
            ) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.REQ_PARAMS_ERROR, "");
            }
            // 接入appid
            BsAgentApiParam agentApiParam = agentApiParamService.getParamByAppId(body.getString("appid"));

            // 验证签名
            BsAgentApiParam apiParam = agentApiParamService.getParamByAppId(agentApiParam.getAppId());
            if (!SignatureUtil.checkSign(body.getString("sign"), body, apiParam.getAppSecret())) {
                throw ErrorHelp.genException(SysCode.OpenApi, ErrorCode.OPEN_API_SIGN_ERR, "");
            }
            String phone = body.getString("phone");

            Map<String, Object> other = new HashMap<>();
            other.put("agentAppid", agentApiParam.getAppId());
            other.put("userSpreadParentId", body.getString("userSpreadParentId"));
            other.put("wxMpOpenId", body.getString("wxMpOpenId"));
            other.put("wxMaOpenId", body.getString("wxMaOpenId"));
            return ResponseMsgUtil.success(userService.login(UserLoginPlatform.TRIPARTITE, UserLoginType.TRIPARTITE, phone, other));

        } catch (Exception e) {
            log.error("LoginController --> autoLogin() error!", e);
            return ResponseMsgUtil.exception(e);
        }
    }

    @RequestMapping(value = "/login", method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value = "登录并注册")
    public ResponseData login(@RequestBody JSONObject body) {
        try {
            if (body == null
                    || StringUtils.isBlank(body.getString("platform"))
                    || StringUtils.isBlank(body.getString("type"))
                    || StringUtils.isBlank(body.getString("phone"))
            ) {
                log.error("LoginController --> phone() error!", "请求参数校验失败");
                throw ErrorHelp.genException(SysCode.System, ErrorCode.REQ_PARAMS_ERROR, "");
            }
            String phone = body.getString("phone");

            // 客户端
            UserLoginPlatform platform = UserLoginPlatform.getDataByType(body.getString("platform"));
            if (platform == null) {
                log.error("LoginController --> phone() error!", "未知客户端");
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知客户端");
            }
            // 校验手机号格式
            if (!MemberValidateUtil.validatePhone(phone)) {
                log.error("LoginController --> phone() error!", "请输入正确的手机号");
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "请输入正确的手机号");
            }
            // 登录类型
            UserLoginType loginType = UserLoginType.getDataByType(body.getString("type"));
            if (loginType == null) {
                log.error("LoginController --> phone() error!", "未知登录类型；" + body.getString("type"));
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知登录类型");
            }

            // 账户密码登录
            if (body.getString("type").equals(UserLoginType.SMS.getCode())) {
                if (StringUtils.isBlank(body.getString("smsCode"))) {
                    log.error("LoginController --> phone() error!", "请输入短信验证码");
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "请输入短信验证码");
                }
                // 手机号的验证码
                Object phoneCodeObject = redisUtil.get("SMS_CODE:" + phone);
                if (phoneCodeObject == null) {
                    log.error("LoginController --> phone() error!", "短信验证码错误");
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "短信验证码错误");
                }
                if (!body.getString("smsCode").equals(phoneCodeObject.toString())) {
                    log.error("LoginController --> phone() error!", "短信验证码错误");
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "短信验证码错误");
                }
                redisUtil.del("SMS_CODE:" + phone);

                Map<String, Object> other = new HashMap<>();
                other.put("userSpreadParentId", body.getString("userSpreadParentId"));
                other.put("wxMpOpenId", body.getString("wxMpOpenId"));
                other.put("wxMaOpenId", body.getString("wxMaOpenId"));
                return ResponseMsgUtil.success(userService.login(platform, loginType, phone, other));
            }

            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "登录失败");

        } catch (Exception e) {
            log.error("LoginController --> phone() error!", e);
            return ResponseMsgUtil.exception(e);
        }
    }

    @RequestMapping(value = "/wxMaHandleCode", method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value = "微信小程序code解析")
    public ResponseData wxMaHandleCode(@RequestBody JSONObject body) {
        try {
            if (body == null|| StringUtils.isBlank(body.getString("code"))) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.REQ_PARAMS_ERROR, "");
            }
            //请求微信api，获取用户session_key以及openId
            WxMaJscode2SessionResult session = WxMaConfiguration.getMaService().jsCode2SessionInfo(body.getString("code"));
            //保存小程序用户登录的openId及sessionKey信息
            redisUtil.hset("WX_OPENID_SESSION_REDIS", session.getOpenid(), session);
            JSONObject jo = new JSONObject();
            jo.put("openId", session.getOpenid());
            return ResponseMsgUtil.success(jo);
        } catch (Exception e) {
            return ResponseMsgUtil.exception(e);
        }
    }

    @RequestMapping(value = "/wxMaLogin", method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value = "微信小程序手机号的登录")
    public ResponseData wxMaLogin(@RequestBody JSONObject body) {
        try {
            if (body == null
                    || StringUtils.isBlank(body.getString("encryptedData"))
                    || StringUtils.isBlank(body.getString("iv"))
                    || StringUtils.isBlank(body.getString("openId"))) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.REQ_PARAMS_ERROR, "");
            }
            String encryptedData = body.getString("encryptedData").replace(" ", "+");
            String iv = body.getString("iv").replace(" ", "+");

            //请求微信api，获取用户session_key以及openId
            Object skObject = redisUtil.hget("WX_OPENID_SESSION_REDIS", body.getString("openId"));
            if (skObject == null) {
                throw ErrorHelp.genException(SysCode.MiniProgram, ErrorCode.WECHAT_LOGIN_ERROR);
            }
            WxMaJscode2SessionResult session = (WxMaJscode2SessionResult) skObject;
            WxMaPhoneNumberInfo phoneNoInfo = WxMaConfiguration.getMaService().getUserService().getPhoneNoInfo(session.getSessionKey(), encryptedData, iv);

            if (phoneNoInfo == null || StringUtils.isEmpty(phoneNoInfo.getPurePhoneNumber())) {
                throw ErrorHelp.genException(SysCode.MiniProgram, ErrorCode.WECHAT_DECRYPT_ERROR, "登录失败! 用户手机号解析失败");
            }
            Map<String, Object> other = new HashMap<>();
            other.put("wxMaOpenId", session.getOpenid());
            other.put("userSpreadParentId", body.getString("userSpreadParentId"));
            return ResponseMsgUtil.success(userService.login(UserLoginPlatform.H5, UserLoginType.WECHAT_MA_PHONE, phoneNoInfo.getPhoneNumber(), other));

        } catch (Exception e) {
            return ResponseMsgUtil.exception(e);
        }
    }

    @RequestMapping(value = "/queryUser", method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value = "查询用户信息")
    public ResponseData queryUser() {
        try {
            UserSessionObject userSessionObject = userCenter.getSessionModel(UserSessionObject.class);
            JSONObject data = JSONObject.parseObject(JSONObject.toJSONString(userSessionObject), JSONObject.class);

            int totalDiscountCoupon = 0;
            // 加油优惠券数量
            Map<String,Object> param = new HashMap<>();
            param.put("userId", userSessionObject.getUser().getId());
            param.put("status", DiscountUserStatusEnum.type1.getCode());
            totalDiscountCoupon += discountUserService.getUserDiscountList(param).size();

            // 非油优惠券数量
            try {
                param.clear();
                param.put("appid", CommonSysConst.getSysConfig().getPhgAppid());
                param.put("phone", userSessionObject.getUser().getPhone());
                param.put("status", 1); // 状态 0:已过期 1：未使用 2：已使用
                param.put("sign", SignatureUtil.createSign(param, CommonSysConst.getSysConfig().getPhgAppSecret()));
                JSONObject response = HttpsUtils.doPost(CommonSysConst.getSysConfig().getPhgReqUrl()+"/crest/output/getListUserDiscount", JSONObject.toJSONString(param));
                if (response.getString("return_code").equals("000000")) {
                    totalDiscountCoupon += response.getJSONArray("return_data").size();
                };
            } catch (Exception e) {}
            data.put("couponNum", totalDiscountCoupon);
            return ResponseMsgUtil.success(data);

        } catch (Exception e) {
            log.error("LoginController --> queryUser() error!", e);
            return ResponseMsgUtil.exception(e);
        }
    }

    @RequestMapping(value = "/bindOtherId", method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value = "绑定其他平台id")
    public ResponseData bindOtherId(@RequestBody JSONObject body) {
        try {
            if (body == null
                    || body.getInteger("type") == null
                    || StringUtils.isBlank(body.getString("id"))) {
                throw ErrorHelp.genException(SysCode.MiniProgram, ErrorCode.REQ_PARAMS_ERROR);
            }
            // 用户登录信息
            UserSessionObject session = userCenter.getSessionModel(UserSessionObject.class);
            if (session == null) {
                throw ErrorHelp.genException(SysCode.MiniProgram, ErrorCode.ACCOUNT_LOGIN_NOT);
            }
            userService.bindOtherId(body.getInteger("type"), body.getString("id"), session.getUser().getId());

            return ResponseMsgUtil.success("绑定成功");

        } catch (Exception e) {
            log.error("LoginController --> bindOtherId() error!", e);
            return ResponseMsgUtil.exception(e);
        }
    }

    @RequestMapping(value="/loginOut",method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value = "退出登录")
    public ResponseData loginOut(HttpServletRequest request) {
        try {
            UserSessionObject session = userCenter.getSessionModel(UserSessionObject.class);
            if (session != null) {
                userCenter.remove(request);
            }
            return ResponseMsgUtil.success("退出成功");

        } catch (Exception e) {
            log.error("error!",e);
            return ResponseMsgUtil.exception(e);
        }
    }

    @RequestMapping(value = "/getH5AccessToken", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "【H5】获取AccessToken")
    public ResponseData getH5AccessToken(@RequestParam(value = "code", required = true) String code) {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("appid", "wxa075e8509802f826");
            params.put("secret", "0e606fc1378d35e359fcf3f15570b2c5");
            params.put("code", code);
            params.put("grant_type", "authorization_code");
            return ResponseMsgUtil.success(HttpsUtils.doGet("https://api.weixin.qq.com/sns/oauth2/access_token", params));

        } catch (Exception e) {
            return ResponseMsgUtil.exception(e);
        }
    }

    @RequestMapping(value="/getAlipayUserId",method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "获取支付宝用户id")
    public ResponseData getAlipayUserId(@RequestParam(value = "code", required = true) String code) {
        try {
            AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
            request.setGrantType("authorization_code");
            request.setCode(code);
            AlipaySystemOauthTokenResponse response = AlipayUtils.initClient().certificateExecute(request);
            if(response.isSuccess()){
                return ResponseMsgUtil.success(response);
            }
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "获取失败");

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResponseMsgUtil.exception(e);
        }
    }
}
