package com.fs.app.controller;


import cn.hutool.core.date.DateTime;
import com.fs.app.annotation.Login;
import com.fs.app.param.*;
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.core.config.WxOpenProperties;
import com.fs.his.config.FsSysConfig;
import com.fs.his.domain.FsUser;
import com.fs.his.domain.FsUserNewTask;
import com.fs.his.mapper.FsUserMapper;
import com.fs.his.service.IFsUserNewTaskService;
import com.fs.his.service.IFsUserService;
import com.fs.his.utils.ConfigUtil;
import com.fs.his.vo.FsUserRegisterParam;
import com.fs.watch.domain.WatchDeviceSetup;
import com.fs.watch.domain.WatchUser;
import com.fs.watch.service.WatchUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
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.*;

import java.time.LocalDateTime;
import java.util.Calendar;
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("app登录接口")
@RestController
@RequestMapping(value="/app/app")
@Slf4j
public class AppLoginController extends AppBaseController{
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private IFsUserService userService;
    @Autowired
    private FsUserMapper userMapper;
    @Autowired
    private IFsUserNewTaskService userNewTaskService;
    @Autowired
    private WxOpenProperties openProperties;

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

//        if (fsUser == null) {
//            // 尝试使用加密后的手机号查询
//            fsUser = userService.selectFsUserByPhone(encryptPhone(param.getPhone()));
//        }

        if (fsUser != null && StringUtils.isNotEmpty(fsUser.getPassword())) {
            return R.error("此账号已经注册");
        }

        FsUser user = new FsUser();
        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.setAvatar("https://cos.his.cdwjyyh.com/fs/20240926/420728ee06e54575ba82665dedb4756b.png");
            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) {
        FsUser user = userService.selectFsUserByPhone(encryptPhone(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("验证码不正确");
        }
        FsUser userMap=new FsUser();
        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:{}，输出appid，{}，secret：{}", param, openProperties.getAppId(), openProperties.getSecret());
            Map result = WxUtil.getAccessToken(param.getCode(), openProperties.getAppId(), openProperties.getSecret());
            String accessToken = result.get("access_token").toString();
            String unionid = result.get("unionid").toString();

            String openid = result.get("openid").toString();

            Map userInfo = WxUtil.getUserInfo(accessToken, openid);

            String nickname = userInfo.get("nickname").toString();
            Integer sex = (Integer) userInfo.get("sex");
            String avatar = userInfo.get("headimgurl").toString();
            FsUser user = userService.selectFsUserByUnionid(unionid);

            Map<String, Object> map = new HashMap<>();
            if (user == null) {
                user = new FsUser();
                user.setLoginDevice(param.getLoginDevice()!=null ? param.getLoginDevice() : null);
                user.setSource(param.getSource()!=null ? param.getSource() : null);
                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());
                    return R.ok(map);
                }
            }
            int isFirstLogin = userNewTaskService.performTaskOne(user.getUserId());
            String token = jwtUtils.generateToken(user.getUserId());
            redisCache.setCacheObject("userToken:" + user.getUserId(), token, 604800, TimeUnit.SECONDS);
            map.put("token", token);
            map.put("user", user);
            map.put("isFirst",isFirstLogin);
            return R.ok(map);
        }catch (Exception e){
            logger.error("zyp 登录失败:{}", e.getMessage());
            return R.error("登录失败");
        }

    }

    @ApiOperation("绑定手机号")
    @PostMapping("/setPhone")
    public R setPhone(@Validated @RequestBody FsUserEditPhoneParam param) {
        logger.info("fcj 绑定手机号入参:{}", param);
        FsUser user = userService.selectFsUserByUnionid(param.getUnionId());
        if (user==null){
            return R.error("用户数据不存在");
        }
        FsUser userMap = findUserByPhone(param.getPhone());
//        if (userMap!=null){
//            return R.error("该手机号已绑定其他账号");
//        }
        user.setPhone(param.getPhone());
        user.setLoginDevice(param.getLoginDevice() != null ? param.getLoginDevice() : null );
        user.setSource(param.getSource()!= null ? param.getSource() : null);
        userMap = new FsUser();
        userMap.setLoginDevice(param.getLoginDevice());
        userMap.setSource(param.getSource());
        userMap.setUserId(user.getUserId());
        userMap.setPhone(param.getPhone());
        if (userService.updateFsUser(userMap)>0){
            return generateTokenAndReturn(user);
        }
        return R.error("绑定手机号失败");
    }

    @ApiOperation("绑定微信")
    @PostMapping("/bindWeChat")
    public R bindWeChat(@Validated @RequestBody FsUserEditUnionidParam param) {
        try {
            logger.info("zyp app绑定微信，param:{}", param);
            Map result = WxUtil.getAccessToken(param.getCode(), openProperties.getAppId(), openProperties.getSecret());
            String accessToken = result.get("access_token").toString();
            String unionid = result.get("unionid").toString();
            String openid = result.get("openid").toString();
            Map userInfo = WxUtil.getUserInfo(accessToken, openid);
            String nickname = userInfo.get("nickname").toString();
            Integer sex = (Integer) userInfo.get("sex");
            String avatar = userInfo.get("headimgurl").toString();
            FsUser user = findUserByPhone(param.getPhone());
            if (user!=null && StringUtils.isEmpty(user.getUnionId())){
                FsUser userByUnionId = userMapper.selectFsUserByUnionid(unionid);
//                if (userByUnionId!=null){
//                    return R.error("该微信已绑定其他用户,请勿重复绑定!");
//                }
                user.setSource(param.getSource() != null ? param.getSource() : null );
                user.setLoginDevice(param.getLoginDevice() != null ? param.getLoginDevice() : null);
                user.setNickName(nickname);
                user.setAvatar(avatar);
                user.setSex(sex);
                user.setUnionId(unionid);
                if (userService.updateFsUser(user)>0){
                    return generateTokenAndReturn(user);
                }
//                else {
//                    return R.error("绑定微信失败");
//                }
            }
            return R.error("数据参数异常！");
        }catch (Exception e){
            logger.error("zyp 登录失败:{}", e.getMessage());
            return R.error("登录失败");
        }
    }

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

    private R generateTokenAndReturn(FsUser user) {
        String token = jwtUtils.generateToken(user.getUserId());
        redisCache.setCacheObject("userToken:" + user.getUserId(), token, 604800, TimeUnit.SECONDS);
        int isFirstLogin = userNewTaskService.performTaskOne(user.getUserId());
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("user", user);
        map.put("isFirst",isFirstLogin);
        return R.ok(map);
    }

    private R handleLoginType1(FsUserLoginParam param) {
        if (StringUtils.isEmpty(param.getPhone()) || StringUtils.isEmpty(param.getPassword())) {
            return R.error("账号或密码不能为空");
        }

        FsUser user = findUserByPhone(param.getPhone());

        // 校验用户是否存在及账号状态
        if (user == null) {
            return R.error("账号不存在，请先注册账号");
        } else if (user.getStatus() == 0) {
            return R.error("账号已停用");
        } else if (StringUtils.isEmpty(user.getPassword())) {
            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("获取手机号失败");
        }
        // 根据手机号查询用户
        FsUser user = findUserByPhone(param.getPhone());
        if (user == null) {
            createNewUser(param);
            return R.ok().put("isNew",true).put("phone",encryptPhone(param.getPhone()));
        } else {
            if (user.getUnionId()==null){
                if (user.getPhone().length()<=11){
                    FsUser fsUser = new FsUser();
                    fsUser.setUserId(user.getUserId());
                    fsUser.setPhone(encryptPhone(param.getPhone()));
                    userMapper.updateFsUser(fsUser);
                    logger.info("zyp \n【手机加密】：{}",encryptPhone(param.getPhone()));
                }
                return R.ok().put("isNew",true).put("phone",encryptPhone(param.getPhone()));
            }
            if (StringUtils.isNotEmpty(param.getJpushId())) {
                updateExistingUserJpushId(user, param.getJpushId());
            }
        }
        return generateTokenAndReturn(user);
    }

    private FsUser createNewUser(FsUserLoginParam param) {
        FsUser newUser = new FsUser();
        newUser.setLoginDevice(param.getLoginDevice() != null ? param.getLoginDevice() : null);
        newUser.setSource(param.getSource() != null ? param.getSource() : null );
        newUser.setNickName("匿名用户**");
        newUser.setPhone(param.getPhone());
        newUser.setCreateTime(new Date());
        newUser.setStatus(1);
        newUser.setAvatar("https://cos.his.cdwjyyh.com/fs/20240926/420728ee06e54575ba82665dedb4756b.png");
        if (StringUtils.isNotEmpty(param.getJpushId())) {
            newUser.setJpushId(param.getJpushId());
        }
        userService.insertFsUser(newUser);
        return newUser;
    }

    private FsUser findUserByPhone(String phone) {
        // 先根据加密手机号查询用户
        String jiami = (encryptPhone(phone));
        FsUser user = userMapper.selectFsUserByPhoneLimitOne(jiami);

        // 如果没有找到用户，再根据手机号查询
        if (user == null) {
            user = userMapper.selectFsUserByPhoneLimitOne(phone);

        }
        return user;
    }

    @PostMapping("/loginTest")
    public R loginTest(@RequestBody String userId) {
        FsUser user = userMapper.selectFsUserByUserId(Long.parseLong(userId));
        if (user!=null){
            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);
        }
        return R.error("用户不存在！");
    }

    /**
     * 退出清除jpushId
     */
    @Login
    @GetMapping("/logout")
    public R logout() {
        String userId = getUserId();
        FsUser fsUser = new FsUser();
        fsUser.setUserId(Long.parseLong(userId));
        fsUser.setJpushId("");
        if (userMapper.updateFsUser(fsUser)>0) {
            return R.ok();
        } else {
            return R.error("用户不存在！");
        }
    }

    /**
     * 更新jpushId
     */
    @Login
    @GetMapping("/updatePushId")
    public R updatePushId(@Param("pushId") String pushId) {
        String userId = getUserId();
        FsUser fsUser = new FsUser();
        fsUser.setUserId(Long.parseLong(userId));
        fsUser.setJpushId(pushId);
        if (userMapper.updateFsUser(fsUser)>0) {
            return R.ok();
        } else {
            return R.error("用户不存在！");
        }
    }
}
