package com.fs.app.controller;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import cn.hutool.core.date.DateTime;
import com.alibaba.fastjson.JSON;
import com.fs.app.annotation.Login;
import com.fs.app.utils.JwtUtils;
import com.fs.common.core.domain.R;
import com.fs.common.core.redis.RedisCache;
import com.fs.common.param.LoginParam;
import com.fs.common.utils.DateUtils;
import com.fs.common.utils.IpUtil;
import com.fs.company.domain.CompanyUser;
import com.fs.core.config.WxMaConfiguration;
import com.fs.core.config.WxMpConfiguration;
import com.fs.his.config.FsSysConfig;
import com.fs.his.domain.FsAgreementConfig;
import com.fs.his.domain.FsStoreSysConfig;
import com.fs.his.domain.FsUser;
import com.fs.his.domain.FsUserLoginLog;
import com.fs.his.mapper.FsUserLoginLogMapper;
import com.fs.his.service.IFsUserService;
import com.fs.his.utils.ConfigUtil;
import com.fs.system.domain.SysConfig;
import com.fs.system.mapper.SysConfigMapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.Synchronized;
import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.WxMpUserService;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.fs.his.utils.PhoneUtil.encryptPhone;

/**
 * 微信小程序用户接口
 *
 */
@Api("微信接口")
@RestController
@RequestMapping(value="/app/wx")
public class WxUserController extends AppBaseController{
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private ConfigUtil configUtil;
    @Autowired
    private IFsUserService userService;
    @Autowired
    FsUserLoginLogMapper fsUserLoginLogMapper;
    @Autowired
    private SysConfigMapper sysConfigMapper;
    @Autowired
    JwtUtils jwtUtils;
    @Autowired
    RedisCache redisCache;

    @Autowired
    private WxMpService wxMpService;




    /**
     * 登陆接口
     */
    /**
     * 登陆接口
     */
    @ApiOperation("登录")
    @PostMapping("/login")
    @Transactional
    public R login( @RequestBody LoginParam param) {
        if (StringUtils.isBlank(param.getCode())) {
            return R.error("code不存在");
        }
        FsSysConfig con = configUtil.getSysConfig();
        final WxMaService wxService = WxMaConfiguration.getMaService(con.getAppid());
        try {
            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(param.getCode());
            this.logger.info(session.getSessionKey());
            this.logger.info(session.getOpenid());
            // 解密
            WxMaPhoneNumberInfo phoneNoInfo = wxService.getUserService().getPhoneNoInfo(session.getSessionKey(), param.getEncryptedData(), param.getIv());
            //三端用户同步，先用unionid查询
            FsUser user = new FsUser();
            if (session.getUnionid()!=null){
                user = userService.selectFsUserByUnionid(session.getUnionid());
                if (user==null){
                    user = userService.selectFsUserByOpenId(session.getOpenid());
                }
            }else {
                user = userService.selectFsUserByOpenId(session.getOpenid());
            }

            if(user==null){
                //新用户
                String phoneNumber = phoneNoInfo.getPhoneNumber();


                //查询手机号是否存在，如果存在，更新
                FsUser checkPhone=userService.selectFsUserByPhone(encryptPhone(phoneNumber));
                if (checkPhone==null){
                    checkPhone=userService.selectFsUserByPhone(phoneNumber);
                }
                if(checkPhone!=null){
                    user=checkPhone;
                    FsUser userMap=new FsUser();
                    userMap.setMaOpenId(session.getOpenid());
                    userMap.setUserId(checkPhone.getUserId());
                    userMap.setUpdateTime(new DateTime());
                    if(session.getUnionid()!=null){
                        userMap.setUnionId(session.getUnionid());
                    }
                    userService.updateFsUser(userMap);
                }
                else{
                    //写入
                    user=new FsUser();
                    user.setPhone(phoneNoInfo.getPhoneNumber());
                    user.setNickName("微信用户"+phoneNoInfo.getPhoneNumber().substring(phoneNoInfo.getPhoneNumber().length()-4));
                    user.setAvatar("https://hos-1309931967.cos.ap-chongqing.myqcloud.com/fs/20230725/a848605591384ec29d49773dd58d9345.jpg");
                    user.setStatus(1);
                    user.setMaOpenId(session.getOpenid());
                    user.setCreateTime(new Date());
                    if(session.getUnionid()!=null){
                        user.setUnionId(session.getUnionid());
                    }
                    userService.insertFsUser(user);
                }
            }
            else{
                if(user.getStatus().equals(0)){

                    return R.error("此会员已禁用");
                }
                FsUser userMap=new FsUser();
                userMap.setUserId(user.getUserId());
                if(session.getUnionid()!=null){
                    userMap.setUnionId(session.getUnionid());
                }
                userMap.setMaOpenId(session.getOpenid());
                userMap.setPhone(phoneNoInfo.getPhoneNumber());
                userMap.setUpdateTime(new DateTime());
                userService.updateFsUser(userMap);
            }
            String token = jwtUtils.generateToken(user.getUserId());
//            redisCache.setCacheObject("token:"+user.getUserId(),token,365, TimeUnit.DAYS);
            Map<String,Object> map=new HashMap<>();
            map.put("token",token);
            user.setPhone(encryptPhone(phoneNoInfo.getPhoneNumber()));
            map.put("user",user);
            FsUserLoginLog log = new FsUserLoginLog();
            log.setCode(param.getCode());
            log.setLoginJson(JSON.toJSONString(param));
//            log.setUserRegisterJson(JSON.toJSONString(jsonMap));
            log.setStatus(1);
            log.setUserId(user.getUserId());
            log.setPhone(user.getPhone());
            log.setMaOpenId(user.getMaOpenId());
            log.setCreateTime(DateUtils.getNowDate());
            fsUserLoginLogMapper.insertFsUserLoginLog(log);
            return R.ok(map);
        } catch (WxErrorException e) {
            //this.logger.error(e.getMessage(), e);
            return R.error("授权失败,"+e.getMessage());
        }
    }

    @ApiOperation("彩虹汇医看课登录")
    @PostMapping("/courseLogin")
    @Transactional
    public R courseLogin( @RequestBody LoginParam param) {
        if (StringUtils.isBlank(param.getCode())) {
            return R.error("code不存在");
        }
        SysConfig storeConfig = sysConfigMapper.selectConfigByConfigKey("store.config");
        FsStoreSysConfig config = JSON.parseObject(storeConfig.getConfigValue(), FsStoreSysConfig.class);
        final WxMaService wxService = WxMaConfiguration.getMaService(config.getAppid());
        try {
            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(param.getCode());
            this.logger.info("获取彩虹汇医Session：{}",session);
            FsUser user=userService.selectFsUserByUnionid(session.getUnionid());
            if(user!=null){
                FsUser userMap=new FsUser();
                userMap.setUserId(user.getUserId());
                userMap.setCourseMaOpenId(session.getOpenid());
                userMap.setUpdateTime(new DateTime());
                userService.updateFsUser(userMap);
            }
            else{
                //写入
                user=new FsUser();
                user.setNickName("微信用户");
                user.setAvatar("https://hos-1309931967.cos.ap-chongqing.myqcloud.com/fs/20230725/a848605591384ec29d49773dd58d9345.jpg");
                user.setStatus(1);
                user.setCourseMaOpenId(session.getOpenid());
                user.setUnionId(session.getUnionid());
                user.setCreateTime(new Date());
                userService.insertFsUser(user);
            }
            String token = jwtUtils.generateToken(user.getUserId());
            Map<String,Object> map=new HashMap<>();
            map.put("token",token);
            map.put("user",user);
            logger.info("zyp \n 【点播彩虹惠医登录】：{}",user.getUserId());
            return R.ok(map);
        }
        catch (WxErrorException e){
            logger.error("授权失败：{}",e.getMessage(),e);
            return R.error("授权失败,"+e.getMessage());
        }
    }

    @ApiOperation("商城小程序登录")
    @PostMapping("/storeLogin")
    @Transactional
    public R storeLogin( @RequestBody LoginParam param) {
        if (StringUtils.isBlank(param.getCode())) {
            return R.error("code不存在");
        }
        SysConfig storeConfig = sysConfigMapper.selectConfigByConfigKey("store.config");
        FsStoreSysConfig config = JSON.parseObject(storeConfig.getConfigValue(), FsStoreSysConfig.class);
        final WxMaService wxService = WxMaConfiguration.getMaService(config.getAppid());
        try {
            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(param.getCode());
            this.logger.info(session.getSessionKey());
            this.logger.info(session.getOpenid());
            // 解密
            WxMaPhoneNumberInfo phoneNoInfo = wxService.getUserService().getPhoneNoInfo(session.getSessionKey(), param.getEncryptedData(), param.getIv());
            FsUser user=userService.selectFsUserByOpenId(session.getOpenid());
            if(user==null){
                //新用户
                //查询手机号是否存在，如果存在，更新
                FsUser checkPhone=userService.selectFsUserByPhone(phoneNoInfo.getPhoneNumber());
                if(checkPhone!=null){
                    user=checkPhone;
                    FsUser userMap=new FsUser();
                    userMap.setStoreOpenId(session.getOpenid());
                    userMap.setUserId(checkPhone.getUserId());
                    userMap.setUpdateTime(new DateTime());
                    if(session.getUnionid()!=null){
                        userMap.setUnionId(session.getUnionid());
                    }
                    userService.updateFsUser(userMap);
                }
                else{
                    //写入
                    user=new FsUser();
                    user.setPhone(phoneNoInfo.getPhoneNumber());
                    user.setNickName("微信用户"+phoneNoInfo.getPhoneNumber().substring(phoneNoInfo.getPhoneNumber().length()-4));
                    user.setAvatar("https://hos-1309931967.cos.ap-chongqing.myqcloud.com/fs/20230725/a848605591384ec29d49773dd58d9345.jpg");
                    user.setStatus(1);
                    user.setStoreOpenId(session.getOpenid());
                    user.setCreateTime(new Date());
                    if(session.getUnionid()!=null){
                        user.setUnionId(session.getUnionid());
                    }
                    userService.insertFsUser(user);
                }
            }
            else{
                FsUser userMap=new FsUser();
                if (user.getStoreOpenId()==null&&user.getStoreOpenId()==""){
                     user.setStoreOpenId(session.getOpenid());
                     userMap.setStoreOpenId(session.getOpenid());
                 }
                userMap.setUserId(user.getUserId());
                if(session.getUnionid()!=null){
                    userMap.setUnionId(session.getUnionid());
                }
                userMap.setPhone(phoneNoInfo.getPhoneNumber());
                userMap.setUpdateTime(new DateTime());
                userService.updateFsUser(userMap);
            }
            String token = jwtUtils.generateToken(user.getUserId());
//            redisCache.setCacheObject("token:"+user.getUserId(),token,365, TimeUnit.DAYS);
            Map<String,Object> map=new HashMap<>();
            map.put("token",token);
            map.put("user",user);
            FsUserLoginLog log = new FsUserLoginLog();
            log.setCode(param.getCode());
            log.setLoginJson(JSON.toJSONString(param));
//            log.setUserRegisterJson(JSON.toJSONString(jsonMap));
            log.setStatus(1);
            log.setUserId(user.getUserId());
            log.setPhone(user.getPhone());
            log.setMaOpenId(user.getStoreOpenId());
            log.setCreateTime(DateUtils.getNowDate());
            fsUserLoginLogMapper.insertFsUserLoginLog(log);
            return R.ok(map);
        } catch (WxErrorException e) {
            //this.logger.error(e.getMessage(), e);
            return R.error("授权失败,"+e.getMessage());
        }
    }

    public static String genCode() {
        String year = new SimpleDateFormat("yy").format(new Date());
        String day = String.format("%tj", new Date());
        double random = Math.random() * 10000000;
        while (random < 1000000) {
            random = Math.random() * 10000000;
        }
        int intRandom = Double.valueOf(random).intValue();
        String verifyCode = year + day + intRandom;
        return verifyCode;
    }

    @ApiOperation("小程序登录")
    @PostMapping("/loginByMiniApp")
    @Synchronized
    public R loginByMiniApp( @RequestBody LoginParam param) {
        if (StringUtils.isBlank(param.getCode())) {
            return R.error("code不存在");
        }
        FsSysConfig con = configUtil.getSysConfig();
        final WxMaService wxService = WxMaConfiguration.getMaService(con.getAppid());
        try {
            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(param.getCode());
            // 解密
//            WxMaPhoneNumberInfo phoneNoInfo = wxService.getUserService().getPhoneNoInfo(session.getSessionKey(), param.getEncryptedData(), param.getIv());
            FsUser user=userService.selectFsUserByOpenId(session.getOpenid());
            String ip = IpUtil.getRequestIp();
            if(user==null){
                //写入
                String code=genCode();
                user=new FsUser();
                user.setPhone(code);
                user.setNickName("微信用户"+code);
                user.setAvatar("https://hos-1309931967.cos.ap-chongqing.myqcloud.com/fs/20230725/a848605591384ec29d49773dd58d9345.jpg");
                user.setStatus(1);
                user.setMaOpenId(session.getOpenid());
                user.setCreateTime(new Date());
                userService.insertFsUser(user);
            }
            else{
                FsUser userMap=new FsUser();
                userMap.setUserId(user.getUserId());
                userMap.setUpdateTime(new DateTime());
                userService.updateFsUser(userMap);
            }
            String token = jwtUtils.generateToken(user.getUserId());
            redisCache.setCacheObject("token:"+user.getUserId(),token,604800, TimeUnit.SECONDS);
            Map<String,Object> map=new HashMap<>();
            map.put("token",token);
            map.put("user",user);

            FsUserLoginLog log = new FsUserLoginLog();
            log.setCode(param.getCode());
            log.setLoginJson(JSON.toJSONString(param));
//            log.setUserRegisterJson(JSON.toJSONString(jsonMap));
            log.setStatus(1);
            log.setUserId(user.getUserId());
            log.setPhone(user.getPhone());
            log.setMaOpenId(user.getMaOpenId());
            log.setCreateTime(DateUtils.getNowDate());
            fsUserLoginLogMapper.insertFsUserLoginLog(log);
            return R.ok(map);
        } catch (WxErrorException e) {
            //this.logger.error(e.getMessage(), e);
            return R.error("授权失败,"+e.getMessage());
        }
    }


    @ApiOperation("公众号登录")
    @PostMapping("/loginByMp")
    public R loginByMp( @RequestBody LoginParam param) {
        if (StringUtils.isBlank(param.getCode())) {
            return R.error("code不存在");
        }
        try{
            WxOAuth2AccessToken wxMpOAuth2AccessToken = wxMpService.getOAuth2Service().getAccessToken(param.getCode());
            WxOAuth2UserInfo wxMpUser = wxMpService.getOAuth2Service().getUserInfo(wxMpOAuth2AccessToken, null);
            FsUser user=userService.selectFsUserByUnionid(wxMpUser.getUnionId());
            if(user!=null){
                FsUser userMap=new FsUser();
                userMap.setUserId(user.getUserId());
                userMap.setNickName(wxMpUser.getNickname());
                userMap.setAvatar(wxMpUser.getHeadImgUrl());
                userMap.setMpOpenId(wxMpUser.getOpenid());
                userMap.setUpdateTime(new DateTime());
                userService.updateFsUser(userMap);
            }
            else{
                //写入
                String code=genCode();
                user=new FsUser();
                user.setNickName(wxMpUser.getNickname());
                user.setAvatar(wxMpUser.getHeadImgUrl());
                user.setStatus(1);
                user.setSex(wxMpUser.getSex());
                user.setMpOpenId(wxMpUser.getOpenid());
                user.setUnionId(wxMpUser.getUnionId());
                user.setCreateTime(new Date());
                userService.insertFsUser(user);
            }
            String token = jwtUtils.generateToken(user.getUserId());
            redisCache.setCacheObject("token:"+user.getUserId(),token,604800, TimeUnit.SECONDS);
            Map<String,Object> map=new HashMap<>();
            map.put("token",token);
            map.put("user",user);

            FsUserLoginLog log = new FsUserLoginLog();
            log.setCode(param.getCode());
            log.setLoginJson(JSON.toJSONString(param));
//            log.setUserRegisterJson(JSON.toJSONString(jsonMap));
            log.setStatus(1);
            log.setUserId(user.getUserId());
            log.setPhone(user.getPhone());
            log.setMaOpenId(user.getMaOpenId());
            log.setCreateTime(DateUtils.getNowDate());
            fsUserLoginLogMapper.insertFsUserLoginLog(log);
            return R.ok(map);
        }
        catch (WxErrorException e){
            if(e.getError().getErrorCode()==40163){
                return R.error(40163,e.getError().getErrorMsg());
            }
            else{
                return R.error("授权失败,"+e.getMessage());
            }
        }

    }

    /**
     * <pre>
     * 获取微信用户信息
     * </pre>
     */
    @Login
    @ApiOperation("获取微信小程序用户信息")
    @PostMapping("/getWeixinInfo")
    public R getWeixinInfo(@RequestBody LoginParam param) {
        FsSysConfig con = configUtil.getSysConfig();
        final WxMaService wxService = WxMaConfiguration.getMaService(con.getAppid());
        try {
            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(param.getCode());
            // 用户信息校验
            if (!wxService.getUserService().checkUserInfo(session.getSessionKey(), param.getRawData(), param.getSignature())) {
                return R.error("user check failed");
            }
            // 解密用户信息
            WxMaUserInfo userInfo = wxService.getUserService().getUserInfo(session.getSessionKey(), param.getEncryptedData(), param.getIv());
            FsUser user=userService.selectFsUserByUserId(Long.parseLong(getUserId()));
            user.setNickName(userInfo.getNickName());
            user.setAvatar(userInfo.getAvatarUrl());
            user.setIsWeixinAuth(1);
            userService.updateFsUser(user);
            return R.ok();
        } catch (WxErrorException e) {
            e.printStackTrace();
        }
        return R.ok("授权成功");
    }


    @GetMapping("/loginTest")
    @Synchronized
    public R loginByMp(String phone) {
        //如果开启了UnionId
        FsUser user=userService.selectFsUserByMpOpenId(phone);
        String token = jwtUtils.generateToken(user.getUserId());
        return R.ok("登录成功").put("token",token).put("user", user);
    }

}
