package com.iformall.controller;


import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import com.iformall.annotation.AuthIgnore;
import com.iformall.common.ErrorCode;
import com.iformall.common.Result;
import com.iformall.common.ResultData;
import com.iformall.domain.po.*;
import com.iformall.enums.EnumMallUserStatus;
import com.iformall.exception.MallinkException;
import com.iformall.service.MallRolePermissionService;
import com.iformall.service.MallUserInfoService;
import com.iformall.service.MallUserRoleService;
import com.iformall.service.WxAppinfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author gongbiao
 */
@RestController
@Api(description = "微信相关")
@RequestMapping("/api/wx")
public class WxInfoController extends BaseController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    WxAppinfoService wxAppinfoService;

    @Autowired
    MallUserInfoService mallUserInfoService;

    @Autowired
    MallUserRoleService mallUserRoleService;

    @Autowired
    MallRolePermissionService mallRolePermissionService;

    @ApiOperation("获取OPENID")
    @PostMapping("getOpenId")
    public ResultData getOpenId(@RequestBody Map<String,String> param) {
        String appId  = param.get("appId");
        String code  = param.get("code");
        if (StringUtils.isBlank(appId)) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "appId不能为空");
        }
        if (StringUtils.isBlank(code)) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "code不能为空");
        }
        try {
            Map<String, String> returnMap = new HashMap<>();
            Map<String, String> retMap = getOpenIdInfo(appId, code);
            returnMap.put("openId", retMap.get("openId"));
            return new ResultData(returnMap);
        } catch (Exception e) {
            return new ResultData(Result.ERROR, "解密异常");
        }
    }

    @AuthIgnore
    @ApiOperation("获取超管OPENID")
    @PostMapping("getSuperOpenId")
    public ResultData getSuperOpenId(@RequestBody Map<String,String> param) {
        String appId  = param.get("appId");
        String code  = param.get("code");
        if (StringUtils.isBlank(appId)) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "appId不能为空");
        }
        if (StringUtils.isBlank(code)) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "code不能为空");
        }

        WxAppinfo wxAppinfo = getAppInfo(appId);
        try {
            Map<String, String> retMap = getOpenIdInfo(appId, code);
            String openId = retMap.get("openId");
            MallUserInfo user = mallUserInfoService.getByBOpenId(openId, wxAppinfo.getTenantId());
            if(user == null) {
                return new ResultData(ErrorCode.USER_NO_PERMISSION, retMap);
            }
            if(user.getStatus().equals(EnumMallUserStatus.NOT_VALID.getCode())) {
                logger.error(ErrorCode.USER_IS_LOCKED.getMessage());
                return new ResultData(ErrorCode.USER_IS_LOCKED);
            }

            if(!mallUserRoleService.checkIsMobileAdmin(user)) {
                return new ResultData(ErrorCode.USER_NO_PERMISSION, retMap);
            }

            retMap.put("phone", user.getPhone());
            retMap.put("msg", "领导来了,欢迎");

            return new ResultData(retMap);
        } catch (Exception e) {
            return new ResultData(Result.ERROR, "解密异常");
        }
    }

    private Map<String,String> getOpenIdInfo(String appId, String code) {
        WxAppinfo wxAppinfo = getAppInfo(appId);
        WxMaService wxMaService = getWeappServiceByAppInfo(wxAppinfo);

        if(StringUtils.isBlank(wxAppinfo.getAccessToken())) {
            // 如果没有accessToken,主动获取保存到数据库中，下次访问可以拿来使用
            try {
                String accessToken = wxMaService.getAccessToken(true);
                wxAppinfo.setAccessToken(accessToken);
                wxAppinfo.setLastTokenTime(new Date());
                wxAppinfo.setExpiresIn(7200);
                wxAppinfoService.saveOrUpdate(wxAppinfo);
            } catch (WxErrorException e) {
                logger.error(e.getMessage());
            } catch (Exception e) {
                logger.error(e.getMessage());
            }

            wxMaService = getWeappServiceByAppInfo(wxAppinfo);

        } else {
            // 检查token是否已过期, 小时就重新获取
            Date curDate = new Date();
            if(curDate.getTime() > wxAppinfo.getLastTokenTime().getTime() + 3600000) {
                try {
                    String accessToken = wxMaService.getAccessToken(true);
                    wxAppinfo.setAccessToken(accessToken);
                    wxAppinfo.setLastTokenTime(new Date());
                    wxAppinfo.setExpiresIn(7200);
                    wxAppinfoService.saveOrUpdate(wxAppinfo);
                } catch (WxErrorException e) {
                    logger.error(e.getMessage());
                } catch (Exception e) {
                    logger.error(e.getMessage());
                }
                wxMaService = getWeappServiceByAppInfo(wxAppinfo);
            }
        }

        try {
            WxMaJscode2SessionResult session = wxMaService.jsCode2SessionInfo(code);
            //获取会话密钥（session_key）
            String session_key = session.getSessionKey();
            String openId = session.getOpenid();
            logger.info("openId: " + openId);

            // update admin user by
            Map<String,String> resultMap=new HashMap<>();
            resultMap.put("openId",openId);
            resultMap.put("session_key", session_key);
            return resultMap;
        } catch (WxErrorException e) {
            logger.error(e.getMessage(), e);
            throw new MallinkException(ErrorCode.SESSION_KEY_DECODE_ERR.getCode(), e.getMessage());
        }
    }

    /**
     * 授权后获取用户的手机号等信息
     * @param map
     * @return
     */
    @AuthIgnore
    @PostMapping("/getUserPhone")
    @ApiOperation(value = "授权后获取用户的手机号", notes="{\"appId\":\"string\",\"encryptedData\":\"string\",\"iv\":\"string\",\"openId\":\"string\",\"session_key\":\"string\"}")
    public ResultData getUserPhone(@RequestBody Map<String, String> map) {
        logger.debug(map.toString());
        Map resultMap = new HashMap();
        String appId = map.get("appId");
        String encryptedData = map.get("encryptedData");
        String iv = map.get("iv");
        String openId = map.get("openId");
        String session_key = map.get("session_key");

        //登录凭证不能为空
        if (StringUtils.isBlank(encryptedData)) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "encryptedData 不能为空");
        }
        if (StringUtils.isBlank(iv)) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "iv 不能为空");
        }
        if (StringUtils.isBlank(openId)) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "openId 不能为空");
        }

        WxMaService wxMaService = getWeappService(appId);

        WxAppinfo wxAppinfo = getAppInfo(appId);
        try {
            // 解密
            WxMaPhoneNumberInfo phoneNoInfo =  wxMaService.getUserService().getPhoneNoInfo(session_key, encryptedData, iv);
            if (null != phoneNoInfo) {
                logger.debug(phoneNoInfo.toString());
                String phone = phoneNoInfo.getPhoneNumber();
                resultMap.put("phone", phone);

                MallUserInfo user = mallUserInfoService.getByPhone(phone, wxAppinfo.getTenantId());
                if(user == null) {
                    return new ResultData(ErrorCode.USER_NO_PERMISSION, resultMap);
                }
                if (mallUserRoleService.checkIsMobileAdmin(user)) {
                    resultMap.put("phone", user.getPhone());
                    resultMap.put("admin", "1");

                    user.setBopenId(openId);
                    mallUserInfoService.saveOrUpdate(user);

                    return new ResultData(resultMap);
                } else {
                    return new ResultData(ErrorCode.USER_NO_PERMISSION, resultMap);
                }
            } else {
                return new ResultData(ErrorCode.PHONE_DECODE_ERR, resultMap);
            }
        } catch (Exception e) {
            this.logger.error(e.getMessage(), e);
            return new ResultData(ErrorCode.DB_FAIL.getCode(), "解密并保存出错", resultMap);
        }
    }

}
