package com.fdkanfang.web.backend;

import cn.hutool.core.lang.Validator;
import com.fdkanfang.common.constant.MsgCode;
import com.fdkanfang.common.sms.SmsService;
import com.fdkanfang.common.util.PasswordUtils;
import com.fdkanfang.common.util.R;
import com.fdkanfang.domain.backend.UserEntity;
import com.fdkanfang.domain.dto.LoginDto;
import com.fdkanfang.domain.dto.RegisterDto;
import com.fdkanfang.service.backend.ResourceService2;
import com.fdkanfang.service.backend.UserService2;
import com.fdkanfang.service.backend.dto.ResourceTree;
import com.fdkanfang.web.aop.WebControllerLog;
import com.fdkanfang.web.shiro.JWTUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * Created by owen on 2020/2/19 0019 15:53
 */
//@Api(value = "IndexController",tags = "登录/退出")
@Api(value = "IndexController",tags = "登录管理")
@RestController
@Log4j2
public class IndexController extends BaseController{



    @Autowired
    private UserService2 userService2;

    @Autowired
    private ResourceService2 resourceService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

//    @Autowired
//    private SmsService smsService;

    @WebControllerLog(description = "用户管理-登录")
    @ApiOperation("登录")
    @PostMapping("admin/login")
    public R login(@RequestBody LoginDto param) throws Exception {
        // 1.获取用户
        UserEntity user = userService2.findByUserName(param.getUserName());
        if (user == null){
            log.error("用户不存在： {}", param.getUserName());
            return new R(MsgCode.e_ADMIN_4001, MsgCode.msg_ADMIN_4001);
        }

        // 验证密码
        Boolean isBoolean = PasswordUtils.decrypt(user.getPassword(), param.getPassword(), PasswordUtils.getStaticSalt());
        if (!isBoolean) {
            log.error("验证密码错误： {}", param.getPassword());
            return new R(MsgCode.e_ADMIN_4002, MsgCode.msg_ADMIN_4002);
        }

        // 检查账号是否启用
        if (user.getStatus() != 0) {
            log.error("账户已停用，不能登录： {}", param.getUserName());
            return new R(5100, "该账户已停用，请跟管理员联系");
        }

        // 获取用户菜单
        List<ResourceTree> resourcesTreeByUserPermission = resourceService.getResourcesTreeByUserPermission(user);

        // 获取用户角色
        Set<String> roles = userService2.findRoleByUserId(user.getId());


        // 创建新token
        HashMap<String, Object> tokenMap = new HashMap<>();
        tokenMap.put("userName", param.getUserName());
        tokenMap.put("id", user.getId());
        tokenMap.put("role", roles);

        String token = JWTUtil.sign(tokenMap, user.getPassword());

        HashMap<String, Object> result = new HashMap<>();
        result.put("user", user);
        result.put("token", token);
        result.put("permission", resourcesTreeByUserPermission);
        result.put("role", roles);


        // 更新到 redis, 有效期24h, 旧token无效
        redisTemplate.opsForValue().set(user.getUserName(), token, Long.parseLong("24"), TimeUnit.HOURS);
        return new R(MsgCode.SUCCESS_CODE, result);
    }

    @ApiOperation("退出")
    @GetMapping("admin/logout")
    public R logout() {
        log.info("run logout");

        String userName = JWTUtil.getUserName(getToken());
        String redisToken = redisTemplate.opsForValue().get(userName);
        // token username 一致，代表没有被踢出
        if (userName.equals(redisToken)) {
            redisTemplate.delete(userName);
        }

        log.info("end logout");
        return new R(MsgCode.SUCCESS_CODE, MsgCode.msg_SUCCESS);
    }

    @ApiOperation("用户注册/重置密码")
    @PostMapping("admin/register")
    public R register(@Valid @RequestBody RegisterDto param) {
        @NotBlank(message = "手机号不能为空") String phone = param.getPhone();
        if (!Validator.isMobile(phone)) {
            log.error("手机号有误： {}", phone);
            return new R(MsgCode.e_COMMON_3003, MsgCode.msg_COMMON_3003);
        }

        // 1.检查验证码
        String code = redisTemplate.opsForValue().get(phone);
        if (StringUtils.isAllBlank(code)) {
            log.error("验证码过期");
            return new R(MsgCode.e_COMMON_3001, "验证码过期");
        }

        if (!code.equals(param.getCode())) {
            log.error("验证码不正确");
            return new R(MsgCode.e_COMMON_3001, "验证码不正确");
        }

        // 2.检查密码一致性
        if (!param.getPassword().equals(param.getConfirmPassword())) {
            log.error("密码不一致");
            return new R(MsgCode.e_COMMON_3001, "密码不一致");
        }

        // 3.保存用户
        UserEntity user = userService2.findByPhone(phone);
         // 注册用户
        if (user == null) {
            user = new UserEntity();
            // 新用户，用户名就是手机号
            user.setUserName(phone);
            user.setPhone(phone);
            user.setRealName(phone);
            // 用户名不能修改，加密需要他，改了就密码就失效
            user.setPassword(PasswordUtils.encrypt(user.getUserName(), param.getPassword(), PasswordUtils.getStaticSalt()));
            userService2.save(user);
        } else {
            // 设置&重置密码
            user.setPassword(PasswordUtils.encrypt(user.getUserName(), param.getPassword(), PasswordUtils.getStaticSalt()));
            user.setUpdateTime(new Date());
            userService2.update(user);
        }


        return new R(MsgCode.SUCCESS_CODE, MsgCode.msg_SUCCESS);

    }

    @ApiOperation("获取验证码")
    @GetMapping("admin/getCode/{phone}")
    public R getCode(@PathVariable String phone) {

        if (!Validator.isMobile(phone)) {
            log.error("手机号有误： {}", phone);
            return new R(MsgCode.e_COMMON_3003, MsgCode.msg_COMMON_3003);
        }
        // 创建4位数的验证码
        int num = new Random().nextInt(9999);

        /**
         * 对接短信平台
         * 四维看房：SMS_184616399
         *
         */
        SmsService.sendSms(phone,"{\"code\":\"" + num + "\"}", "SMS_184616399");

        // 更新到 redis, 有效期5分钟, 旧token无效
        redisTemplate.opsForValue().set(phone, String.valueOf(num), Long.parseLong("360"), TimeUnit.SECONDS);

        return new R(MsgCode.SUCCESS_CODE, num);
    }

    @GetMapping("test")
    public String test(){
        return LocalDateTime.now().toString();
    }


    public static void main(String[] args) {
        System.out.println(Validator.isMobile("015015980188"));
    }

}