package com.fs.app.controller.store;


import cn.hutool.core.date.DateTime;
import com.fs.app.controller.AppBaseController;
import com.fs.app.param.FsUserEditPhoneParam;
import com.fs.app.param.FsUserEditPwdParam;
import com.fs.app.param.FsUserLoginByWeChatParam;
import com.fs.app.param.FsUserLoginParam;
import com.fs.app.utils.WxUtil;
import com.fs.common.annotation.RepeatSubmit;
import com.fs.common.core.domain.R;
import com.fs.common.core.redis.RedisCache;
import com.fs.common.utils.sign.Md5Utils;
import com.fs.hisStore.domain.FsUserScrm;
import com.fs.hisStore.param.FsUserRegisterParam;
import com.fs.hisStore.service.IFsUserScrmService;
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.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
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;
import java.util.concurrent.TimeUnit;

@Api("app登录接口")
@RestController
@RequestMapping(value="/store/app/app")
public class AppLoginScrmController extends AppBaseController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private IFsUserScrmService userService;

    private static final String APP_ID = "wx703c4bd07bbd1695";
    private static final String APP_SECRET = "034f5cc8d9b5151f9d25da9628541e35";

    @Autowired
    private RedisCache redisCache;
    @ApiOperation("注册app用户")
    @PostMapping("/register")
    @RepeatSubmit
    public R registerDoctor(@Validated @RequestBody FsUserRegisterParam param){

        FsUserScrm fsUser= userService.selectFsUserByPhone(param.getPhone());
        if (fsUser!=null&&StringUtils.isNotEmpty(fsUser.getPassword())){
            return R.error("此账号已经注册");
        }
        FsUserScrm user=new FsUserScrm();
        if(fsUser!=null){
            user.setUserId(fsUser.getUserId());
            user.setPassword(Md5Utils.hash(param.getPassword()));
            user.setUpdateTime(new DateTime());
            userService.updateFsUser(user);
            return R.ok("注册成功");
        } else{
            user.setPhone(param.getPhone());
            user.setNickname("app用户"+param.getPhone().substring(param.getPhone().length()-4));
            user.setStatus(1);
            user.setPassword(Md5Utils.hash(param.getPassword()));
            user.setCreateTime(new Date());
            if(userService.insertFsUser(user)>0){
                return R.ok("注册成功");
            }else{
                return R.error("注册失败");
            }
        }
    }

    @ApiOperation("登录")
    @PostMapping("/login")
    @Transactional
    public R login(@Validated @RequestBody FsUserLoginParam param) {
        int loginType = param.getLoginType();
        switch (loginType) {
            case 1:
                return handleLoginType1(param);
            case 3:
                return handleLoginType3(param);
            default:
                return R.error("请选择正确的登陆类型！");
        }
    }

    @ApiOperation("找回密码")
    @PostMapping("/editPwd")
    public R login(@Validated @RequestBody FsUserEditPwdParam param) {
        FsUserScrm user = userService.selectFsUserByPhone(param.getPhone());
        if (user==null){
            return R.error("用户不存在");
        }
        String code = redisCache.getCacheObject(user.getPhone());
        if(StringUtils.isEmpty(code)){
            return R.error("验证码已过期");
        }
        if(!code.equals(param.getCode())){
            return R.error("验证码不正确");
        }
        FsUserScrm userMap=new FsUserScrm();
        userMap.setUserId(user.getUserId());
        userMap.setPassword(Md5Utils.hash(param.getPassword()));
        if (userService.updateFsUser(userMap)>0){
            return R.ok("新密码设置成功");
        }
        return R.error("新密码设置失败，请稍后再试！");
    }


    @ApiOperation("微信登录")
    @PostMapping("/loginByWeChat")
    @Transactional
    public R loginByWeChat(@Validated @RequestBody FsUserLoginByWeChatParam param) {
        try {
            if (StringUtils.isBlank(param.getCode())) {
                return R.error("code不存在");
            }
            logger.info("zyp app微信登录，param:{}", param);
            Map result = WxUtil.getAccessToken(param.getCode(),APP_ID,APP_SECRET);
            String accessToken = result.get("access_token").toString();
            String unionid = result.get("unionid").toString();
            logger.info("zyp 获取unionid成功，unionid:{}", unionid);
            String openid = result.get("openid").toString();
            logger.info("zyp 开始获取用户信息，AccessToken:{}", accessToken);
            Map userInfo = WxUtil.getUserInfo(accessToken, openid);
            logger.info("zyp 获取用户信息结束，userInfo:{}", userInfo);
            String nickname = userInfo.get("nickname").toString();
            Integer sex = (Integer) userInfo.get("sex");
            String avatar = userInfo.get("headimgurl").toString();
            FsUserScrm user = userService.selectFsUserByUnionId(unionid);

            Map<String, Object> map = new HashMap<>();
            if (user == null) {
                user = new FsUserScrm();
                user.setNickname(nickname);
                user.setAvatar(avatar);
                if (sex!=0){
                    user.setSex(sex);
                }
                user.setUnionId(unionid);
                user.setCreateTime(new Date());
                user.setStatus(1);
                if (StringUtils.isNotEmpty(param.getJpushId())) {
                    user.setJpushId(param.getJpushId());
                }
                userService.insertFsUser(user);
                map.put("isNew", true);
                map.put("unionid",unionid);
                return R.ok(map);
            } else {
                if (StringUtils.isNotEmpty(param.getJpushId())) {
                    updateExistingUserJpushId(user, param.getJpushId());
                }
                if (StringUtils.isEmpty(user.getPhone())) {
                    map.put("isNew", true);
                    map.put("unionid",user.getUnionId());
                }
            }
            String token = jwtUtils.generateToken(user.getUserId());
            redisCache.setCacheObject("userToken:" + user.getUserId(), token, 604800, TimeUnit.SECONDS);
            map.put("token", token);
            map.put("user", user);
            return R.ok(map);
        }catch (Exception e){
            logger.error("zyp 登录失败", e);
            return R.error("登录失败");
        }

    }

    @ApiOperation("绑定手机号")
    @PostMapping("/setPhone")
    public R setPhone(@Validated @RequestBody FsUserEditPhoneParam param) {
        FsUserScrm user = userService.selectFsUserByUnionId(param.getUnionId());
        if (user==null){
            return R.error("用户数据不存在");
        }
        FsUserScrm userMap = userService.selectFsUserByPhone(param.getPhone());
//        if (userMap!=null){
//            return R.error("该手机号已绑定其他账号");
//        }
        user.setPhone(param.getPhone());
        userMap = new FsUserScrm();
        userMap.setUserId(user.getUserId());
        userMap.setPhone(param.getPhone());
        if (userService.updateFsUser(userMap)>0){
            return generateTokenAndReturn(user);
        }
        return R.error("绑定手机号失败");
    }

    private void updateExistingUserJpushId(FsUserScrm user, String jpushId) {
        FsUserScrm userMap = new FsUserScrm();
        userMap.setUserId(user.getUserId());
        userMap.setJpushId(jpushId);
        userService.updateFsUser(userMap);
    }

    private R generateTokenAndReturn(FsUserScrm user) {
        String token = jwtUtils.generateToken(user.getUserId());
        redisCache.setCacheObject("userToken:" + user.getUserId(), token, 604800, TimeUnit.SECONDS);

        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("user", user);
        return R.ok(map);
    }

    private R handleLoginType1(FsUserLoginParam param) {
        if (StringUtils.isEmpty(param.getPhone()) || StringUtils.isEmpty(param.getPassword())) {
            return R.error("账号或密码不能为空");
        }
        FsUserScrm user = userService.selectFsUserByPhone(param.getPhone());
        if (user == null || user.getStatus() == 0) {
            return R.error("账号不存在或已停用");
        }
        if (user.getPassword() == null) {
            return R.error("账号不存在，请先注册账号");
        }

        if (StringUtils.isNotEmpty(param.getJpushId())) {
            updateExistingUserJpushId(user,param.getJpushId());
        }

        if (!Md5Utils.hash(param.getPassword()).equals(user.getPassword())) {
            return R.error("密码不正确");
        }
        return generateTokenAndReturn(user);
    }

    private R handleLoginType3(FsUserLoginParam param) {
        if (StringUtils.isEmpty(param.getPhone())) {
            return R.error("获取手机号失败");
        }
        FsUserScrm user = userService.selectFsUserByPhone(param.getPhone());
        if (user == null) {
            user = createNewUser(param);
        } else {
            if (StringUtils.isNotEmpty(param.getJpushId())) {
                updateExistingUserJpushId(user, param.getJpushId());
            }
        }
        return generateTokenAndReturn(user);
    }

    private FsUserScrm createNewUser(FsUserLoginParam param) {
        FsUserScrm newUser = new FsUserScrm();
        newUser.setNickname("匿名用户**");
        if (StringUtils.isNotEmpty(param.getOpenId())) {
            newUser.setMaOpenId(param.getOpenId());
        } else if (StringUtils.isNotEmpty(param.getPhone())) {
            newUser.setPhone(param.getPhone());
        }
        newUser.setCreateTime(new Date());
        newUser.setStatus(1);
        newUser.setAvatar("https://hos-1309931967.cos.ap-chongqing.myqcloud.com/fs/20230725/a848605591384ec29d49773dd58d9345.jpg");
        if (StringUtils.isNotEmpty(param.getJpushId())) {
            newUser.setJpushId(param.getJpushId());
        }
        userService.insertFsUser(newUser);
        return newUser;
    }

}
