package com.xkrs.controller;

import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.xkrs.common.config.RedisUtil;
import com.xkrs.common.encapsulation.PromptMessageEnum;
import com.xkrs.common.tool.TokenUtil;
import com.xkrs.dao.SysUserDao;
import com.xkrs.model.entity.SysUserEntity;
import com.xkrs.model.qo.SysUserQo;
import com.xkrs.model.qo.UserUpdate;
import com.xkrs.model.validation.SysUserQoInsert;
import com.xkrs.model.validation.SysUserQoUpdate;
import com.xkrs.model.vo.SysUserVo;
import com.xkrs.service.SysUserService;
import com.xkrs.utils.RandomUtil;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.xkrs.common.encapsulation.OutputEncapsulation.outputEncapsulationErrorList;
import static com.xkrs.common.encapsulation.OutputEncapsulation.outputEncapsulationObject;
import static com.xkrs.utils.AliYunSmsUtils.sendSms;
import static com.xkrs.utils.EncryptDecryptUtil.encry256;

/**
 * 系统用户Controller
 * @author tajocehn
 */
@RestController
@RequestMapping(value = "/api/user")
public class SysUserController {

    @Resource
    private SysUserService sysUserService;

    @Resource
    private SysUserDao sysUserDao;

    @Resource
    private RedisUtil redisUtil;

    /**
     * 登录用户Token验证
     * @return
     */
    @RequestMapping(value = "/logged/check",method = RequestMethod.POST)
    public String loginUserTokenCheck(){
        Locale locale = LocaleContextHolder.getLocale();
        return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"",locale);
    }

    @RequestMapping(value = "/check/duplicate", method = RequestMethod.POST)
    public String checkDuplicate(@RequestParam(value="userName", required=false) String userName){
        // 获取区域信息
        Locale locale = LocaleContextHolder.getLocale();
        // 验证用户名是否重复
        if(!sysUserService.checkUserName(userName)){
            return outputEncapsulationObject(PromptMessageEnum.PARAM_ILLEGAL,"",locale);
        }
        return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"OK",locale);
    }


    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public String addUser(@Validated({SysUserQoInsert.class}) @RequestBody SysUserQo userQo,
                          BindingResult bindingResult){
        // 获取区域信息
        Locale locale = LocaleContextHolder.getLocale();
        // 验证数据合法性
        if(bindingResult.hasErrors()){
            return outputEncapsulationErrorList(bindingResult.getFieldErrors(),locale);
        }
        // 验证用户名是否重复
        if(!sysUserService.checkUserName(userQo.getUserName())){
            return outputEncapsulationObject(PromptMessageEnum.PARAM_ILLEGAL,"该账号已注册，请勿重复注册！",locale);
        }
        // 添加新用户
        sysUserService.addUser(userQo);
        return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"OK",locale);
    }


    /*@RequestMapping(value="/get/all", method = RequestMethod.GET)
    @PreAuthorize("hasAnyAuthority('auth_system_manager','auth_administor')")
    public String getAllSysUser(){
        // 获取区域信息
        Locale locale = LocaleContextHolder.getLocale();
        Iterable<SysUserVo> sysUserDtoList = sysUserService.getAllSysUser();
        return outputEncapsulationObject(PromptMessageEnum.SUCCESS,sysUserDtoList,locale);
    }*/

    /**
     * 软删除指定id的普通用户
     * @param id
     * @return
     */
    @RequestMapping(value = "/general/delete", method = RequestMethod.DELETE)
    @PreAuthorize("hasAnyAuthority('auth_system_manager','auth_general_user')")
    public String deleteCustomUser(@RequestParam(value="userId", required=false) int id){
        // 获取区域信息
        Locale locale = LocaleContextHolder.getLocale();
        // 验证数据合法性
        int res = sysUserService.softDeleteGeneralUser(id);
        if(res==1){
            return outputEncapsulationObject(PromptMessageEnum.PROCESS_FAIL,"",locale);
        } else {
            return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"",locale);
        }
    }

    @RequestMapping(value = "/update", method = RequestMethod.POST)
    @PreAuthorize("hasAnyAuthority('auth_system_manager','auth_administor')")
    public String updateUser(@Validated({SysUserQoUpdate.class}) @RequestBody SysUserQo userQo,
                          BindingResult bindingResult){
        // 获取区域信息
        Locale locale = LocaleContextHolder.getLocale();
        // 验证数据合法性
        if(bindingResult.hasErrors()){
            return outputEncapsulationErrorList(bindingResult.getFieldErrors(),locale);
        }
        // 修改用户
        sysUserService.updateSysUser(userQo);
        return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"OK",locale);
    }

    /**
     * 绑定手机号
     * @param map
     * @param token
     * @return
     */
    @PostMapping("/bindPhone")
    public String bindPhone(@RequestBody Map map,@RequestHeader(value="Authorization") String token){
        Locale locale = LocaleContextHolder.getLocale();
        String phone = (String) map.get("phone");
        String verificationCode = (String) map.get("verificationCode");
        // 验证token
        String tokenUserName = TokenUtil.getTokenUserName(token);
        SysUserEntity sysUserEntity = sysUserDao.selectByUserName(tokenUserName);
        if(sysUserEntity == null){
            return outputEncapsulationObject(PromptMessageEnum.USER_LOGIN_ERROR,"您还没有注册登录，请先注册登录",locale);
        }
        String o = (String) redisUtil.get(phone);
        if("".equals(o) || o == null){
            return outputEncapsulationObject(PromptMessageEnum.DATA_WRONG,"请先发送验证码！",locale);
        }
        if(!redisUtil.get(phone).equals(verificationCode)){
            return outputEncapsulationObject(PromptMessageEnum.DATA_WRONG,"验证码错误，请重新输入！",locale);
        }
        return sysUserService.bindPhone(sysUserEntity.getId(),phone);
    }

    /**
     * 发送手机号
     * @param phone
     * @return
     * @throws ClientException
     */
    @GetMapping("/verificationCode")
    public String verificationCode(@RequestParam("phone") String phone) throws ClientException {
        // 获取区域信息
        Locale locale = LocaleContextHolder.getLocale();
        String optCode = String.valueOf(RandomUtil.returnCode());
        redisUtil.set(phone,optCode,60*10);
        SendSmsResponse response =sendSms(phone,optCode);
        return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"",locale);    }

    /**
     * 手机号登录
     * @param map
     * @return
     */
    @PostMapping("/loginByPhone")
    public String loginByPhone(@RequestBody Map map){
        String phone = (String) map.get("phone");
        String verificationCode = (String) map.get("verificationCode");
        return sysUserService.loginByPhone(phone,verificationCode);
    }

    /**
     * 填写手机号发送验证码，用于用户忘记密码
     * @param phone
     * @return
     * @throws ClientException
     */
    @GetMapping("/verificationCodeUpdate")
    public String verificationCodeUpdate(@RequestParam("phone") String phone) throws ClientException {
        // 获取区域信息
        Locale locale = LocaleContextHolder.getLocale();
        SysUserVo sysUserVo = sysUserDao.selectUserByUserName(phone);
        if(sysUserVo == null){
            return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"手机号错误，请使用您注册的手机号",locale);
        }
        String optCode = String.valueOf(RandomUtil.returnCode());
        redisUtil.set(phone,optCode,60*10);
        SendSmsResponse response =sendSms(phone,optCode);
        return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"",locale);
    }

    /**
     * 输入验证码进行判断
     * @param phone
     * @param verificationCode
     * @return
     */
    @GetMapping("/getVerificationCode")
    public String getVerificationCode(@RequestParam("phone") String phone, @RequestParam("verificationCode") String verificationCode){
        Locale locale = LocaleContextHolder.getLocale();
        String o = (String) redisUtil.get(phone);
        if("".equals(o) || o == null){
            return outputEncapsulationObject(PromptMessageEnum.DATA_WRONG,"请先发送验证码！",locale);
        }
        if(!redisUtil.get(phone).equals(verificationCode)){
            return outputEncapsulationObject(PromptMessageEnum.DATA_WRONG,"验证码错误，请重新输入！",locale);
        }
        return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"true",locale);
    }

    /**
     * 用户完善信息
     * @param
     * @param
     * @param token
     * @return
     */
    @PostMapping("/updateUserByUserId")
    public String updateUserByUserId(@RequestBody Map map, @RequestHeader(value="Authorization") String token) throws IOException {
        Locale locale = LocaleContextHolder.getLocale();
        String avatar = (String) map.get("avatar");
        String nickName = (String) map.get("nickName");
        if(nickName != null){
            SysUserEntity byNickName = sysUserDao.findByNickName(nickName);
            if(byNickName != null){
                return outputEncapsulationObject(PromptMessageEnum.FILE_EXISTS,"该昵称已存在！",locale);
            }
        }
        String tokenUserName = TokenUtil.getTokenUserName(token);
        SysUserEntity sysUserEntity = sysUserDao.selectByUserName(tokenUserName);
        return sysUserService.updateUserByUserId(avatar,nickName,sysUserEntity.getId());
    }

    /**
     * 管理员进行启用禁用的操作
     * @param map
     * @param token
     * @return
     */
    @PostMapping("/operateActiveFlag")
    @PreAuthorize("hasAnyAuthority('auth_administor')")
    public String operateActiveFlag(@RequestBody Map map,@RequestHeader(value="Authorization") String token){
        Integer userId = (Integer) map.get("userId");
        String keepType = (String) map.get("keepType");
        // 获取区域信息
        Locale locale = LocaleContextHolder.getLocale();
        // 验证token
        String tokenUserName = TokenUtil.getTokenUserName(token);
        SysUserEntity sysUserEntity = sysUserDao.selectByUserName(tokenUserName);
        if(sysUserEntity == null){
            return outputEncapsulationObject(PromptMessageEnum.USER_LOGIN_ERROR,"您还没有注册登录，请先注册登录",locale);
        }
        // 如果keepType等于1进行启用操作
        if("1".equals(keepType)){
            sysUserService.updateEnable(userId);
            return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"启用成功",locale);
        }else {
            sysUserService.updateDisable(userId);
            return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"禁用成功",locale);
        }
    }

    /**
     * 判断用户名是否存在
     * @param userName
     * @return
     */
    @GetMapping("/booleanUserName")
    public String booleanUserName(@RequestParam("userName") String userName){
        // 获取区域信息
        Locale locale = LocaleContextHolder.getLocale();
        Map map = new HashMap(3);
        SysUserEntity sysUserEntity = sysUserDao.selectByUserName(userName);
        if(sysUserEntity == null){
            map.put("status",0);
            return outputEncapsulationObject(PromptMessageEnum.SUCCESS,map,locale);
        }else {
            map.put("status",1);
            return outputEncapsulationObject(PromptMessageEnum.SUCCESS,map,locale);
        }
    }

    /**
     * 管理员查看全部的用户信息
     * @return
     */
    @GetMapping("/selectAllUser")
    @PreAuthorize("hasAnyAuthority('auth_administor')")
    public String selectAllUser(@RequestHeader(value="Authorization") String token){
        Locale locale = LocaleContextHolder.getLocale();
        List<Map<String, Object>> maps = sysUserDao.selectAllUser();
        if(maps == null || maps.size() == 0){
            return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"暂时没有任何用户数据！",locale);
        }
        return outputEncapsulationObject(PromptMessageEnum.SUCCESS,maps,locale);
    }

    /**
     * 用户修改账号密码
     * @param map
     * @param token
     * @return
     */
    @PostMapping("/updatePassword")
    public String updatePassword(@RequestBody Map map,@RequestHeader(value="Authorization") String token){
        // 获取区域信息
        Locale locale = LocaleContextHolder.getLocale();
        String userName = (String) map.get("userName");
        String oldPassword = (String) map.get("oldPassword");
        String newPassword = (String) map.get("newPassword");
        String confirmPassword = (String) map.get("confirmPassword");
        // 验证token
        String tokenUserName = TokenUtil.getTokenUserName(token);
        SysUserEntity sysUserEntity = sysUserDao.selectByUserName(tokenUserName);
        if(sysUserEntity == null){
            return outputEncapsulationObject(PromptMessageEnum.USER_LOGIN_ERROR,"您还没有注册登录，请先注册登录",locale);
        }
        if(oldPassword == null || "".equals(oldPassword)){
            return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"旧密码不能为空！",locale);
        }
        if(newPassword == null || "".equals(newPassword)){
            return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"新密码不能为空！",locale);
        }
        if(userName == null || "".equals(userName)){
            return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"账号不能为空！",locale);
        }
        return sysUserService.updatePassword(oldPassword,newPassword,confirmPassword,userName,sysUserEntity);
    }


    /**
     * 用户忘记密码
     * @param map
     * @return
     */
    @Transactional(rollbackFor=Exception.class)
    @PostMapping("/updateRememberPassword")
    public String updateRememberPassword(@RequestBody Map map){
        // 获取区域信息
        Locale locale = LocaleContextHolder.getLocale();
        String phone = (String) map.get("phone");
        String verificationCode = (String) map.get("verificationCode");
        String newPassword = (String) map.get("newPassword");
        String confirmPassword = (String) map.get("confirmPassword");
        SysUserEntity byTelephone = sysUserDao.findByTelephone(phone);
        if(byTelephone == null){
            return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"您未绑定该手机号！",locale);
        }
        if(!newPassword.equals(confirmPassword)){
            return outputEncapsulationObject(PromptMessageEnum.PROCESS_FAIL,"两次密码输入不一致",locale);
        }
        String newAfterPassword = encry256(newPassword + byTelephone.getSalt());

        String o = (String) redisUtil.get(phone);
        if("".equals(o) || o == null){
            return outputEncapsulationObject(PromptMessageEnum.DATA_WRONG,"请先发送验证码！",locale);
        }
        if(!redisUtil.get(phone).equals(verificationCode)){
            return outputEncapsulationObject(PromptMessageEnum.DATA_WRONG,"验证码错误，请重新输入！",locale);
        }
        sysUserDao.updateRememberPassword(phone,newAfterPassword);
        return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"密码修改成功",locale);
    }

}
