package tech.glinfo.enbao.modules.appuser.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import tech.glinfo.enbao.common.annotation.ApiLog;
import tech.glinfo.enbao.common.annotation.Login;
import tech.glinfo.enbao.common.annotation.LoginUser;
import tech.glinfo.enbao.common.controller.AbstractController;
import tech.glinfo.enbao.common.exception.RRException;
import tech.glinfo.enbao.common.utils.*;
import tech.glinfo.enbao.common.validator.Assert;
import tech.glinfo.enbao.common.validator.ValidatorUtils;
import tech.glinfo.enbao.modules.appuser.dto.AppUserDto;
import tech.glinfo.enbao.modules.appuser.entity.AppUserEntity;
import tech.glinfo.enbao.modules.appuser.form.*;
import tech.glinfo.enbao.modules.appuser.service.OtherAppUserService;
import tech.glinfo.enbao.modules.sh.entity.ShFamilyEntity;
import tech.glinfo.enbao.modules.sh.entity.ShFamilyMemberEntity;
import tech.glinfo.enbao.modules.sh.service.OtherShFamilyService;
import tech.glinfo.enbao.modules.sh.service.ShFamilyMemberService;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


/**
 * APP用户
 *
 * @author linzhenjie
 * @email linzhenjie@gltech.com
 * @date 2019-11-14 16:06:47
 */
@RestController
@RequestMapping("/user")
@Api(value = "APP用户接口",description="APP用户相关信息接口")
public class AppUserController extends AbstractController {

    @Autowired
    private OtherAppUserService otherAppUserService;

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private OtherShFamilyService otherShFamilyService;

    @Autowired
    private ShFamilyMemberService shFamilyMemberService;

    @PostMapping("register")
    @ApiOperation("用户注册")
    @ApiLog("用户注册")
    public R register(@RequestBody WxRegisterForm form){

        //表单校验
        ValidatorUtils.validateEntity(form);
        AppUserEntity userEntity = otherAppUserService.queryByPhone(form.getPhone());
        if (userEntity != null) {
            return R.error("手机号码已经注册过了");
        }

       /* String vcode = redisUtils.get(Constant.VCODE_KEY + Constant.VcodeType.REG.getValue() + "_" + form.getPhone());
        if(!form.getVcode().equals(vcode)) {
            throw new RRException("验证码输入不正确");
        }*/

        AppUserEntity user = new AppUserEntity();
        user.setPhone(form.getPhone());
        user.setNickname(form.getNickname());
        user.setOpenId(form.getOpenId());
        user.setHeadImgUrl(form.getHeadImgUrl());
        user.setPassword(DigestUtils.sha256Hex("123456"));
        otherAppUserService.save(user);
        ShFamilyEntity family = new ShFamilyEntity();
        family.setName("我的家");
        family.setUserId(user.getId());
        otherShFamilyService.save(family);
        //新增家庭成员
        ShFamilyMemberEntity member = new ShFamilyMemberEntity();
        member.setFamilyId(family.getId());
        member.setUserId(user.getId());
        member.setIsAdmin(1);//管理员
        shFamilyMemberService.save(member);
        String token = jwtUtils.generateToken(user.getId() +"#"+user.getPhone());
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("expire", jwtUtils.getExpire());
        map.put("user", user);
        return R.ok(map);
    }

    @PostMapping("update")
    @ApiOperation("用户信息修改")
//    @ApiLog("用户信息修改")
    public R update(@RequestBody UpdateForm form){

        AppUserEntity user = new AppUserEntity();
        AppUserEntity user1 = otherAppUserService.getById(form.getId());

        //修改手机号码
        if(StringUtils.isNotEmpty(form.getPhone())) {
            AppUserEntity userEntity = otherAppUserService.queryByPhone(form.getPhone());
            if (userEntity != null) {
                throw new RRException("手机号码已经注册过了");
            }
            String vcode1 = redisUtils.get(Constant.VCODE_KEY + Constant.VcodeType.OTHERS.getValue() + "_" + form.getOphone());
            if(!form.getVcode1().equals(vcode1)) {
                throw new RRException("原手机号码验证码输入不正确");
            }
            String vcode2 = redisUtils.get(Constant.VCODE_KEY + Constant.VcodeType.OTHERS.getValue() + "_" + form.getPhone());
            if(!form.getVcode2().equals(vcode2)) {
                throw new RRException("新手机号码验证码输入不正确");
            }

        }

        //修改密码走忘记密码接口
        try {
            BeanUtils.copyProperties(user, form);
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }

        otherAppUserService.updateById(user);
        return R.ok();
    }

    /**
     * 登录
     */
    @PostMapping("login")
    @ApiOperation("用户登录")
    @ApiLog("用户登录")
    public R login(@RequestBody LoginForm form) {
        //表单校验
        ValidatorUtils.validateEntity(form);

        //用户登录
        AppUserEntity user = otherAppUserService.login(form);
       /* String openId = null;
        if (StringUtils.isNotBlank(form.getCode())) {
            if (StringUtils.isBlank(form.getKey())) {
                return R.error("登录失败！key为空");
            }
            try {
                openId = getOpenId(form.getCode(), form.getKey());
            } catch (IOException e) {
                return R.error("登录失败， 请重试！");
            }
        }*/
        Map<String, Object> map = genTokenAndGetData(user, form.getClientId(), form.getRole());

//        map.put("openId", openId);
        return R.ok(map);
    }
    /**
     * 忘记密码
     */
    @PostMapping("forget")
    @ApiOperation("忘记密码/修改密码")
    @ApiLog("忘记密码/修改密码")
    public R forget(@RequestBody ForgetForm form){
        //表单校验
        ValidatorUtils.validateEntity(form);

        String vcode = redisUtils.get(Constant.VCODE_KEY + Constant.VcodeType.FORGET.getValue() + "_" + form.getPhone());
        if(!form.getVcode().equals(vcode)) {
            throw new RRException("验证码输入不正确");
        }

        //用户登录
        AppUserEntity user = otherAppUserService.queryByPhone(form.getPhone());

        Assert.isNull(user, "手机号码不存在");

        AppUserEntity user1 = new AppUserEntity();
        user1.setId(user.getId());
        user1.setPassword(DigestUtils.sha256Hex(form.getPassword()));

        boolean result = otherAppUserService.updateById(user1);

        return result?R.ok():R.error("操作失败");
    }
    /**
     * 快捷登录
     */
    @PostMapping("quick_login")
    @ApiOperation("快捷登录")
    @ApiLog("用户快捷登录")
    public R quickLogin(@RequestBody QuickLoginForm form) throws IOException {
        //表单校验
        ValidatorUtils.validateEntity(form);

        String vcode = redisUtils.get(Constant.VCODE_KEY + Constant.VcodeType.LOGIN.getValue() + "_" + form.getPhone());
        if(!form.getVcode().equals(vcode)) {
            throw new RRException("验证码输入不正确");
        }

        //用户登录
        AppUserEntity user = otherAppUserService.quickLogin(form);
        if(user == null) {
            AppUserEntity user1 = new AppUserEntity();
            logger.info("手机号码不存在，直接注册：{}", form.getPhone());
            user1.setPhone(form.getPhone());
            String password = StringUtils.random(6, StringUtils.RandomType.INT);
            user1.setNickname("暂未设置");
            user1.setPassword(DigestUtils.sha256Hex(password));
            otherAppUserService.save(user1);
            return R.ok(genTokenAndGetData(user1, form.getClientId(), form.getRole()));
        }
        /*String openId = null;
        if (StringUtils.isNotBlank(form.getCode())) {
            if (StringUtils.isBlank(form.getKey())) {
                return R.error("登录失败！key为空");
            }
            openId = getOpenid(form.getCode(), form.getKey());
        }*/
        Map<String, Object> map = genTokenAndGetData(user, form.getClientId(), form.getRole());
//        map.put("openId", openId);
        return R.ok(map);
    }
    /**
     * 快捷登录
     */
    @PostMapping("wxOrAppleLogin")
    @ApiOperation("微信登录")
    @ApiLog("用户微信登录")
    public R wxOrAppleLogin(@RequestBody Map<String, Object> params) {

        String unionid = (String) params.get("unionid");
        String openid = (String) params.get("openid");
        String clientId = (String) params.get("clientId");
        Integer role = (Integer) params.get("role");

        if (StringUtils.isNotEmpty(unionid)) {//苹果登录
            //open_id 存unionID
            AppUserEntity user = otherAppUserService.getOne(new QueryWrapper<AppUserEntity>().eq("unionid", unionid));
            if (user != null) {
//                map.put("openId", openId);
                return R.ok(genTokenAndGetData(user, clientId, role));
            } else {
                return R.error("当前Apple暂未绑定任何账号！");

            }
        } else if (StringUtils.isNotEmpty(openid)) {//微信登录
            //open_id 存unionID
            AppUserEntity user = otherAppUserService.getOne(new QueryWrapper<AppUserEntity>().eq("open_id", openid));
            if (user != null) {
                String token = jwtUtils.generateToken(user.getId() +"#"+user.getPhone());
                Map<String, Object> map = new HashMap<>();
                map.put("token", token);
                map.put("expire", jwtUtils.getExpire());
                map.put("user", user);
                return R.ok(map);
            } else {
                return R.ok("当前微信暂未绑定任何账号！");
            }
        } else {
            return R.error("缺少参数，请核查！");
        }
    }
    /**
     * 快捷登录
     */
    @PostMapping("bindPhone")
    @ApiOperation("微信绑定账户")
    @ApiLog("微信绑定账户")
    public R bindPhone(@RequestBody Map<String, Object> params) {

        String unionid = (String) params.get("unionid");
        String openid = (String) params.get("openid");
        String clientId = (String) params.get("clientId");
        String phone = (String) params.get("phone");
        String vcode = (String) params.get("vcode");
        Integer role = (Integer) params.get("role");

        if (StringUtils.isBlank(phone, vcode)) {
            return R.error("缺少参数，请核查！");
        }
        if(StringUtils.isEmpty(unionid) && StringUtils.isEmpty(openid)) {
            return R.error("缺少参数，请核查！");
        }

        String code = redisUtils.get(Constant.VCODE_KEY + Constant.VcodeType.OTHERS.getValue() + "_" + phone);
        if(!vcode.equals(code)) {
            throw new RRException("验证码输入不正确");
        }

        AppUserEntity _user = otherAppUserService.queryByPhone(phone);
        if (_user == null) {
            logger.info("手机号码不存在，直接注册：{}", phone);
            AppUserEntity user = new AppUserEntity();
            user.setPhone(phone);
            user.setNickname(StringUtils.isNotEmpty(unionid)?"微信用户":"苹果用户");
            if(StringUtils.isNotEmpty(unionid)) {
                user.setUnionId(unionid);
            }
            if(StringUtils.isNotEmpty(openid)) {
                user.setOpenId(openid);
            }
            //随机密码
            user.setPassword(DigestUtils.sha256Hex(StringUtils.random(6, StringUtils.RandomType.INT)));
            otherAppUserService.save(user);
            return R.ok(genTokenAndGetData(user, clientId, role));

        } else {
            AppUserEntity update = new AppUserEntity();
            update.setId(_user.getId());
            if(StringUtils.isNotEmpty(unionid)) {
                update.setUnionId(unionid);
            }
            if(StringUtils.isNotEmpty(openid)) {
                update.setOpenId(openid);
            }
            otherAppUserService.updateById(update);
        }

        return R.ok(genTokenAndGetData(_user, clientId, role));
    }

    private Map<String, Object> genTokenAndGetData(AppUserEntity user, String clientId, Integer role) {
        String token = jwtUtils.generateToken(user.getId() +"#"+user.getPhone());
        //重新取数据
        if(StringUtils.isEmpty(user.getHeadImgUrl())) {
            user = otherAppUserService.getById(user.getId());
        }
        String activeProfile = SpringContextUtils.getActiveProfile();
        logger.info("当前环境：{}", activeProfile);
        /*if (!"dev".equals(activeProfile) && user.getToken() != null&&!redisUtils.hasKey(AppContants.APP_NOTOKEN_EXPIRED+user.getPhone())) {
            redisUtils.set(AppContants.APP_TOKEN_EXPIRED+user.getToken(), "TokenExpired1", 60 * 60 * 24 * 7);
        }*/
        updateUser(null, clientId, user.getId(), token);
//        Map<String, Object> map = getLoginData(user, token);

        return null;
    }

    /**
     * 更新用户信息
     * @param openId
     * @param clientId
     * @param id
     */
    private void updateUser(String openId, String clientId, Integer id, String token) {
        AppUserEntity entity = new AppUserEntity();
        entity.setId(id);
        if(StringUtils.isNotBlank(clientId)) {
            entity.setThirdId(clientId);//客户端ID，用于消息推送
        }
        if(StringUtils.isNotBlank(openId)) {
            entity.setOpenId(openId);//微信openID
        }
        entity.setLastLoginTime(new Date());
//        entity.setToken(token);
        otherAppUserService.updateById(entity);

    }

    /**
     * 获取登录数据
     * @param user
     * @return
     */
    private Map<String, Object> getLoginData(AppUserEntity user, String token) {

        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("expire", jwtUtils.getExpire());
        AppUserDto data = new AppUserDto();
        try {
            BeanUtils.copyProperties(data, user);
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        map.put("data", data);
        return map;
    }

    @Login
    @GetMapping("/info")
    @ApiOperation("APP用户信息")
    @ApiLog("APP用户信息")
    public R info(@LoginUser AppUserEntity user) {
        AppUserDto data = new AppUserDto();
        try {
            BeanUtils.copyProperties(data, user);
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        return R.ok().put("data", data);
    }

    @Login
    @GetMapping("/getInfoById/{id}")
    @ApiOperation("通过ID获取APP用户信息")
    @ApiLog("通过ID获取APP用户信息")
    public R info(@PathVariable("id") Integer id) {
        AppUserEntity user = otherAppUserService.getById(id);
        if(user == null) {
            throw new RRException("用户不存在");
        }
        Map<String, Object> data = new HashMap<>();
        data.put("uid", user.getId());
        data.put("nickname", user.getNickname());
        data.put("headPortrait", user.getHeadImgUrl());
        return R.ok().put("data", data);
    }

    @Login
    @PostMapping("/closeAccount")
    @ApiOperation("注销账号")
    @ApiLog("注销账号")
    public R closeAccount(@LoginUser AppUserEntity user) {
        user.setPhone("0" + user.getPhone());
        user.setStatus(2);
        otherAppUserService.updateById(user);
        return R.ok();
    }

}
