package com.fs.app.controller.store;

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.fs.app.annotation.Login;
import com.fs.app.controller.AppBaseController;
import com.fs.app.utils.JwtUtils;
import com.fs.common.OrderUtils;
import com.fs.common.core.domain.R;
import com.fs.common.exception.CustomException;
import com.fs.common.utils.IpUtil;
import com.fs.core.config.WxMaConfiguration;
import com.fs.core.config.WxMpProperties;
import com.fs.his.domain.FsUser;
import com.fs.his.utils.ConfigUtil;
import com.fs.hisStore.domain.FsUserScrm;
import com.fs.hisStore.enums.SysConfigEnum;
import com.fs.hisStore.param.LoginMpWxParam;
import com.fs.hisStore.param.LoginWxParam;
import com.fs.hisStore.service.IFsUserScrmService;
import com.fs.wx.miniapp.config.WxMaProperties;
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 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 static com.fs.his.utils.PhoneUtil.encryptPhone;

/**
 * 微信小程序用户接口
 *
 */
@Api("微信接口")
@RestController
@RequestMapping(value="/store/app/wx")
public class WxUserScrmController extends AppBaseController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private WxMaProperties maProperties;

    @Autowired
    private WxMpProperties mpProperties;
    @Autowired
    private WxMpService wxMpService;

    @Autowired
    private IFsUserScrmService userService;
    @Autowired
    JwtUtils jwtUtils;

    @Autowired
    private ConfigUtil configUtil;

    /**
     * 登陆接口
     */
    @ApiOperation("登录")
    @PostMapping("/login")
    public R login(@RequestBody LoginMpWxParam param) {
        if (StringUtils.isBlank(param.getCode())) {
            return R.error("code不存在");
        }

        final WxMaService wxService = WxMaConfiguration.getMaService(maProperties.getConfigs().get(1).getAppid());
        try {
            // 获取微信会话信息
            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(param.getCode());
            logger.info("获取微信会话信息成功 - openid: {}, sessionKey: {}", session.getOpenid(), session.getSessionKey());

            // 获取手机号信息
            WxMaPhoneNumberInfo phoneNoInfo = wxService.getUserService().getPhoneNoInfo(
                session.getSessionKey(),
                param.getEncryptedData(),
                param.getIv()
            );
            logger.info("获取手机号信息成功 - phone: {}", phoneNoInfo.getPhoneNumber());

            // 获取用户IP
            String ip = IpUtil.getRequestIp();

            // 查找或创建用户
            FsUserScrm user = findOrCreateUser(session, phoneNoInfo, ip, param.getUserCode());

            // 生成token
            String token = jwtUtils.generateToken(user.getUserId());

            // 记录登录日志
            logger.info("用户登录成功 - userId: {}, phone: {}", user.getUserId(), user.getPhone());

            return R.ok("登录成功")
                .put("token", token)
                .put("user", user);

        } catch (WxErrorException e) {
            logger.error("微信授权失败: {}", e.getMessage(), e);
            return R.error("授权失败: " + e.getMessage());
        } catch (CustomException e) {
            logger.error("业务处理异常: {}", e.getMessage(), e);
            return R.error(e.getMessage());
        } catch (Exception e) {
            logger.error("系统异常: {}", e.getMessage(), e);
            return R.error("系统异常，请稍后重试");
        }
    }

    /**
     * 查找或创建用户
     */
    private FsUserScrm findOrCreateUser(WxMaJscode2SessionResult session,
                                  WxMaPhoneNumberInfo phoneNoInfo,
                                  String ip,
                                  String userCode) {
        // 优先通过unionid查找用户
        FsUserScrm user = null;
        if (session.getUnionid() != null) {
            user = userService.selectFsUserByUnionid(session.getUnionid());
            if (user == null) {
                user = userService.selectFsUserByMaOpenId(session.getOpenid());
            }
        } else {
            user = userService.selectFsUserByMaOpenId(session.getOpenid());
        }

        if (user == null) {
            // 检查手机号是否已存在
            FsUserScrm checkPhone = userService.selectFsUserByPhone(phoneNoInfo.getPhoneNumber());
            if (checkPhone != null) {
                if (checkPhone.getMaOpenId() == null) {
                    // 更新已存在用户的信息
                    user = updateExistingUser(checkPhone, session, ip);
                } else {
                    throw new CustomException("此手机号已被其他微信账号绑定");
                }
            } else {
                // 创建新用户
                user = createNewUser(session, phoneNoInfo, ip, userCode);
            }
        } else {
            // 更新用户信息
            updateUserInfo(user, phoneNoInfo, ip);
        }

        return user;
    }

    /**
     * 更新已存在用户的信息
     */
    private FsUserScrm updateExistingUser(FsUserScrm existingUser, WxMaJscode2SessionResult session, String ip) {
        FsUserScrm userMap = new FsUserScrm();
        userMap.setMaOpenId(session.getOpenid());
        userMap.setUserId(existingUser.getUserId());
        userMap.setUpdateTime(new DateTime());
        userMap.setLastIp(ip);
        if (session.getUnionid() != null) {
            userMap.setUnionId(session.getUnionid());
        }
        userService.updateFsUser(userMap);
        return existingUser;
    }

    /**
     * 创建新用户
     */
    private FsUserScrm createNewUser(WxMaJscode2SessionResult session,
                               WxMaPhoneNumberInfo phoneNoInfo,
                               String ip,
                               String userCode) {
        FsUserScrm user = new FsUserScrm();

        // 处理推荐关系
        if (StringUtils.isNotEmpty(userCode)) {
            FsUserScrm tuiUser = userService.selectFsUserByUserCode(userCode);
            if (tuiUser != null) {
                user.setIsPromoter(1);
                user.setSpreadUserId(tuiUser.getUserId());
            }
        }

        // 设置用户基本信息
        user.setUserCode(OrderUtils.genUserCode());
        user.setPhone(phoneNoInfo.getPhoneNumber());
        user.setUsername(phoneNoInfo.getPhoneNumber());
        user.setNickname("微信用户");
        user.setStatus(1);
        user.setMaOpenId(session.getOpenid());
        user.setLastIp(ip);
        user.setIsWeixinAuth(0);
        user.setCreateTime(new Date());

        if (session.getUnionid() != null) {
            user.setUnionId(session.getUnionid());
        }

        userService.insertFsUser(user);
        return user;
    }

    /**
     * 更新用户信息
     */
    private void updateUserInfo(FsUserScrm user, WxMaPhoneNumberInfo phoneNoInfo, String ip) {
        FsUserScrm userMap = new FsUserScrm();
        userMap.setPhone(phoneNoInfo.getPhoneNumber());
        userMap.setUserId(user.getUserId());
        userMap.setUpdateTime(new DateTime());
        userMap.setLastIp(ip);
        userService.updateFsUser(userMap);
    }

    /**
     * <pre>
     * 获取微信用户信息
     * </pre>
     */
    @Login
    @ApiOperation("获取微信小程序用户信息")
    @PostMapping("/getWeixinInfo")
    public R getWeixinInfo(@RequestBody LoginMpWxParam param) {
        final WxMaService wxService = WxMaConfiguration.getMaService(maProperties.getConfigs().get(0).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());
            FsUserScrm user=userService.selectFsUserById(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("授权成功");
    }

    @ApiOperation("小程序登录")
    @PostMapping("/loginByMiniApp")
    @Synchronized
    public R loginByMiniApp( @RequestBody LoginMpWxParam param) {
        if (StringUtils.isBlank(param.getCode())) {
            return R.error("code不存在");
        }
        String courseMa_appId;

        System.out.println("appid"+param.getCode());
        logger.info("appid"+param.getCode());
        logger.info("appid"+param.getAppId());
        if(StringUtils.isNotEmpty(param.getAppId())){
            try {
                courseMa_appId = configUtil.generateConfigMiniByKey(SysConfigEnum.COURSE_MA_CONFIG.getKey(),param.getAppId()).getString("appid");
            } catch (Exception e) {
                courseMa_appId = param.getAppId();
            }
        }else{
            courseMa_appId = configUtil.generateConfigByKey(SysConfigEnum.COURSE_MA_CONFIG.getKey()).getString("appid");
        }

        final WxMaService wxService = WxMaConfiguration.getMaService(courseMa_appId);
        try {
            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(param.getCode());
            // 解密
            WxMaPhoneNumberInfo phoneNoInfo = wxService.getUserService().getPhoneNoInfo(session.getSessionKey(), param.getEncryptedData(), param.getIv());
            FsUserScrm user=new FsUserScrm();
            logger.info("===========用户unionid:{}，用户openid:{}",session.getUnionid(),session.getOpenid());
            if (session.getUnionid()!=null){
                user = userService.selectFsUserByUnionid(session.getUnionid());
                if (user==null){
                    user = userService.selectFsUserByOpenId(session.getOpenid());
                }
            }else {
                user = userService.selectFsUserByOpenId(session.getOpenid());
            }
            //FsUserScrm user=userService.selectFsUserByMaOpenId(session.getOpenid());
            String ip = IpUtil.getRequestIp();
            if(user==null){
                //新用户
                String phoneNumber = phoneNoInfo.getPhoneNumber();
                //查询手机号是否存在，如果存在，更新
                FsUserScrm checkPhone = null;
                if(StringUtils.isNotEmpty(phoneNumber)){
                    checkPhone=userService.selectFsUserByPhone(encryptPhone(phoneNumber));
                }

                if (checkPhone==null){
                    checkPhone=userService.selectFsUserByPhone(phoneNumber);
                }
                if(checkPhone!=null){
                    user=checkPhone;
                    FsUserScrm userMap=new FsUserScrm();
                    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 FsUserScrm();
                    user.setPhone(phoneNoInfo.getPhoneNumber());
                    user.setNickName(phoneNoInfo.getPhoneNumber() != null ? "微信用户" + 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("此会员已禁用");
                }
                FsUserScrm userMap=new FsUserScrm();
                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());
            return R.ok("登录成功").put("token",token).put("user", user);
        } catch (WxErrorException e) {
            //this.logger.error(e.getMessage(), e);
            return R.error("授权失败,"+e.getMessage());
        }
    }


    @ApiOperation("小程序Mall登录")
    @PostMapping("/loginByMiniMallApp")
    @Synchronized
    public R loginByMiniMallApp( @RequestBody LoginMpWxParam param) {
        if (StringUtils.isBlank(param.getCode())) {
            return R.error("code不存在");
        }
        final WxMaService wxService = WxMaConfiguration.getMaService(maProperties.getConfigs().get(1).getAppid());
        try {
            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(param.getCode());

            // 解密
            WxMaPhoneNumberInfo phoneNoInfo = wxService.getUserService().getPhoneNoInfo(session.getSessionKey(), param.getEncryptedData(), param.getIv());

            FsUserScrm user=userService.selectFsUserByPhone(phoneNoInfo.getPhoneNumber());

            //FsUserScrm user=userService.selectFsUserByMaOpenId(session.getOpenid());
            String ip = IpUtil.getRequestIp();
            if(user==null){
                //user=userService.selectFsUserByUnionId(session.getUnionid());
                user=userService.selectFsUserByMaOpenId(session.getOpenid());
                if(user!=null){
                    FsUserScrm userMap=new FsUserScrm();
                    userMap.setUserId(user.getUserId());
                    userMap.setPhone(phoneNoInfo.getPhoneNumber());
                    userMap.setUpdateTime(new DateTime());
                    user.setMaOpenId(session.getOpenid());
                    if(StringUtils.isNotEmpty(session.getUnionid())){
                        user.setUnionId(session.getUnionid());
                    }
                    userMap.setLastIp(ip);
                    userService.updateFsUser(userMap);
                }
                else{
                    //写入
                    user=new FsUserScrm();
//                    if(param.getTuiUserId()!=null&&param.getTuiUserId()>0){
//                        FsUserScrm tuiUser=userService.selectFsUserById(param.getTuiUserId());
//                        if(tuiUser!=null){
//                            user.setSpreadUserId(param.getTuiUserId());
//                        }
//                    }
                    user.setUsername("");
                    user.setPhone(phoneNoInfo.getPhoneNumber());
//                    user.setPhone("");
                    user.setNickname("微信用户");
                    user.setNickName("微信用户");
                    user.setStatus(1);
                    user.setMaOpenId(session.getOpenid());
                    user.setLastIp(ip);
                    user.setIsWeixinAuth(0);
                    user.setCreateTime(new Date());
                    if(StringUtils.isNotEmpty(session.getUnionid())){
                        user.setUnionId(session.getUnionid());
                    }
                    userService.insertFsUser(user);
                }
            }
            else{
                FsUserScrm userMap=new FsUserScrm();
                userMap.setUserId(user.getUserId());
                userMap.setUpdateTime(new DateTime());
                userMap.setPhone(phoneNoInfo.getPhoneNumber());
                userMap.setLastIp(ip);
                if(StringUtils.isNotEmpty(session.getUnionid())){
                    userMap.setUnionId(session.getUnionid());
                }
                userService.updateFsUser(userMap);
            }
            String token = jwtUtils.generateToken(user.getUserId());
            return R.ok("登录成功").put("token",token).put("user", user);
        } catch (WxErrorException e) {
            //this.logger.error(e.getMessage(), e);
            return R.error("授权失败,"+e.getMessage());
        }
    }



    @ApiOperation("公众号登录")
    @PostMapping("/loginByMp")
    @Synchronized
    public R loginByMp( @RequestBody LoginWxParam 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);
            //如果开启了UnionId
            FsUserScrm user=userService.selectFsUserByMpOpenId(wxMpUser.getOpenid());
            String ip = IpUtil.getRequestIp();
            if(user==null){
                user=userService.selectFsUserByPhone(wxMpUser.getUnionId());
                if(user!=null){
                    FsUserScrm userMap=new FsUserScrm();
                    userMap.setUserId(user.getUserId());
                    userMap.setUpdateTime(new DateTime());
                    userMap.setLastIp(ip);
                    user.setMpOpenId(wxMpUser.getOpenid());
                    userService.updateFsUser(userMap);
                }
                else{
                    user=new FsUserScrm();
                    user.setUsername("");
                    user.setNickname(wxMpUser.getNickname());
                    user.setStatus(1);
                    user.setMpOpenId(wxMpUser.getOpenid());
                    user.setLastIp(ip);
                    user.setCreateTime(new Date());
                    user.setAvatar(wxMpUser.getHeadImgUrl());
                    if(StringUtils.isNotEmpty(wxMpUser.getUnionId())){
                        user.setUnionId(wxMpUser.getUnionId());
                    }
                    userService.insertFsUser(user);
                }
            }
            else{
                FsUserScrm userMap=new FsUserScrm();
                userMap.setUserId(user.getUserId());
                userMap.setUpdateTime(new DateTime());
                userMap.setLastIp(ip);
                if(StringUtils.isNotEmpty(wxMpUser.getUnionId())){
                    userMap.setUnionId(wxMpUser.getUnionId());
                }
                userService.updateFsUser(userMap);
            }
            String token = jwtUtils.generateToken(user.getUserId());
            return R.ok("登录成功").put("token",token).put("user", user);
        }
        catch (WxErrorException e){
            if(e.getError().getErrorCode()==40163){
                return R.error(40163,e.getError().getErrorMsg());
            }
            else{
                return R.error("授权失败,"+e.getMessage());
            }
        }

    }

}
