package ink.wgink.service.user.controller.resources;

import ink.wgink.annotation.CheckRequestBodyAnnotation;
import ink.wgink.common.base.DefaultBaseController;
import ink.wgink.exceptions.ParamsException;
import ink.wgink.interfaces.consts.ISystemConstant;
import ink.wgink.interfaces.manager.ISystemConfigManager;
import ink.wgink.pojo.ListPage;
import ink.wgink.pojo.dtos.user.UserDTO;
import ink.wgink.pojo.result.ErrorResult;
import ink.wgink.pojo.result.SuccessResult;
import ink.wgink.pojo.result.SuccessResultData;
import ink.wgink.pojo.result.SuccessResultList;
import ink.wgink.pojo.vos.IdsVO;
import ink.wgink.pojo.vos.UpdatePasswordVO;
import ink.wgink.service.user.pojo.vos.UserVO;
import ink.wgink.service.user.service.IUserService;
import ink.wgink.util.ReflectUtil;
import ink.wgink.util.RegexUtil;
import io.swagger.annotations.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

/**
 * When you feel like quitting. Think about why you started
 * 当你想要放弃的时候，想想当初你为何开始
 *
 * @ClassName: UserController
 * @Description: 用户
 * @Author: WangGeng
 * @Date: 2021/1/24 17:10
 * @Version: 1.0
 **/
@Api(tags = ISystemConstant.API_TAGS_RESOURCE_PREFIX + "用户")
@RestController
@RequestMapping(ISystemConstant.RESOURCE_PREFIX + "/user")
public class UserResourceController extends DefaultBaseController {

    @Autowired
    private IUserService userService;

    @ApiOperation(value = "新增默认用户", notes = "新增默认用户接口")
    @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
    @PostMapping("save-default-user")
    public SuccessResultData<String> save(@RequestBody UserVO userVO) {
        String userId = userService.saveDefaultUserAndReturnId(userVO.getUserUsername(), userVO.getUserName(), userVO.getUserState(), userVO.getUserType());
        return new SuccessResultData<>(userId);
    }

    @ApiOperation(value = "修改密码", notes = "修改密码接口")
    @ApiImplicitParams({@ApiImplicitParam(name = "userId", value = "用户ID", paramType = "path"),})
    @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
    @PutMapping("update-password/{userId}")
    @CheckRequestBodyAnnotation
    public SuccessResult updatePassword(@PathVariable("userId") String userId, @RequestBody UpdatePasswordVO updatePasswordVO) throws ReflectUtil.ReflectException {
        ISystemConfigManager systemConfigManager = ReflectUtil.getSingleInstance("ink.wgink.login.base.manager.ConfigManager", ISystemConfigManager.class);
        if (systemConfigManager != null) {
            checkUpdatePasswordParams(systemConfigManager.getConfig(), updatePasswordVO);
        }
        userService.updatePasswordByUserId(userId, updatePasswordVO);
        return new SuccessResult();
    }

    /**
     * 修改密码参数校验
     *
     * @param config
     * @param updatePasswordVO
     */
    private void checkUpdatePasswordParams(Map<String, String> config, UpdatePasswordVO updatePasswordVO) {
        if (config.get(IUserService.PASSWORD_STRENGTH) != null) {
            String passwordStrength = config.get(IUserService.PASSWORD_STRENGTH);
            if (StringUtils.equals(IUserService.PASSWORD_STRENGTH_MIDDLE, passwordStrength) && !RegexUtil.isPasswordMiddle(updatePasswordVO.getNewPassword())) {
                throw new ParamsException(String.format("密码应该%d到%d位，包含数字、字母、特殊字符，其中的任意两种，特殊字符包括%s", RegexUtil.PASSWORD_LENGTH_MIN, RegexUtil.PASSWORD_LENGTH_MAX, RegexUtil.SPECIAL_CHARACTERS));
            } else if (StringUtils.equals(IUserService.PASSWORD_STRENGTH_STRONG, passwordStrength) && !RegexUtil.isPasswordStrong(updatePasswordVO.getNewPassword())) {
                throw new ParamsException(String.format("密码应该%d到%d位，必须全部包含数字、字母、特殊字符三种，特殊字符包括%s", RegexUtil.PASSWORD_LENGTH_MIN, RegexUtil.PASSWORD_LENGTH_MAX, RegexUtil.SPECIAL_CHARACTERS));
            } else if (!RegexUtil.isPasswordWeek(updatePasswordVO.getNewPassword())) {
                throw new ParamsException(String.format("密码应该%d到%d位，仅包含数字，字母，特殊字符，其中的一种，特殊字符包括%s", RegexUtil.PASSWORD_LENGTH_MIN, RegexUtil.PASSWORD_LENGTH_MAX, RegexUtil.SPECIAL_CHARACTERS));
            }
        } else if (!RegexUtil.isPasswordWeek(updatePasswordVO.getNewPassword())) {
            throw new ParamsException(String.format("密码应该%d到%d位，仅包含数字，字母，特殊字符，其中的一种，特殊字符包括%s", RegexUtil.PASSWORD_LENGTH_MIN, RegexUtil.PASSWORD_LENGTH_MAX, RegexUtil.SPECIAL_CHARACTERS));
        }
    }

    @ApiOperation(value = "用户列表", notes = "用户列表接口")
    @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
    @GetMapping("list")
    public List<UserDTO> list() {
        Map<String, Object> params = requestParams();
        return userService.list(params);
    }

    @ApiOperation(value = "用户分页列表", notes = "用户分页列表接口")
    @ApiImplicitParams({@ApiImplicitParam(name = "page", value = "当前页码", paramType = "query", dataType = "int", defaultValue = "1"), @ApiImplicitParam(name = "rows", value = "显示数量", paramType = "query", dataType = "int", defaultValue = "20"), @ApiImplicitParam(name = "keywords", value = "关键字", paramType = "query", dataType = "String"), @ApiImplicitParam(name = "startTime", value = "开始时间", paramType = "query", dataType = "String"), @ApiImplicitParam(name = "endTime", value = "结束时间", paramType = "query", dataType = "String")})
    @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
    @GetMapping("listpage")
    public SuccessResultList<List<UserDTO>> listPage(ListPage page) {
        Map<String, Object> params = requestParams();
        page.setParams(params);
        return userService.listPage(page);
    }

    @ApiOperation(value = "用户详情", notes = "用户详情接口")
    @ApiImplicitParams({@ApiImplicitParam(name = "userId", value = "用户ID", paramType = "path")})
    @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
    @GetMapping("get/{userId}")
    public UserDTO getUser(@PathVariable("userId") String userId) {
        return userService.get(userId);
    }

    @ApiOperation(value = "用户详情", notes = "用户详情接口")
    @ApiImplicitParams({@ApiImplicitParam(name = "userId", value = "用户ID", paramType = "path")})
    @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
    @GetMapping("get/username/{username}")
    public UserDTO getByUsername(@PathVariable("username") String username) {
        return userService.getByUsername(username);
    }

    @ApiOperation(value = "通过ID列表获取用户列表", notes = "通过ID列表获取用户列表接口")
    @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
    @PostMapping("list/ids")
    public List<UserDTO> listByIds(@RequestBody IdsVO idsVO) {
        if (idsVO.getIds().isEmpty()) {
            throw new ParamsException("id列表不能为空");
        }
        return userService.listByUserIds(idsVO.getIds());
    }

    @ApiOperation(value = "通过ID列表获取用户列表", notes = "通过ID列表获取用户列表接口")
    @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
    @PostMapping("list/username")
    public List<UserDTO> listByUsernames(@RequestBody IdsVO idsVO) {
        if (idsVO.getIds().isEmpty()) {
            throw new ParamsException("用户名列表不能为空");
        }
        return userService.listByUsernames(idsVO.getIds());
    }

    @ApiOperation(value = "通过手机号列表获取用户列表", notes = "通过手机号列表获取用户列表接口")
    @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
    @PostMapping("list/phones")
    public List<UserDTO> listByPhones(@RequestBody IdsVO idsVO) {
        if (idsVO.getIds().isEmpty()) {
            throw new ParamsException("手机号列表不能为空");
        }
        return userService.listByUserPhones(idsVO.getIds());
    }

    @ApiOperation(value = "获取密码状态", notes = "获取密码状态接口")
    @ApiImplicitParams({@ApiImplicitParam(name = "userId", value = "用户ID", paramType = "path"),})
    @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
    @GetMapping("get-password-status/{userId}")
    public SuccessResultData<String> getPasswordStatus(@PathVariable("userId") String userId) throws ReflectUtil.ReflectException {
        return userService.getPasswordStatus(userId);
    }

    @ApiOperation(value = "统计用户", notes = "统计用户接口")
    @ApiImplicitParams({@ApiImplicitParam(name = "startDate", value = "开始时间", paramType = "path"), @ApiImplicitParam(name = "endDate", value = "结束时间", paramType = "path")})
    @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
    @GetMapping("count-date-range/{startDate}/{endDate}")
    public SuccessResultData<Integer> countDateRange(@PathVariable("startDate") String startDate, @PathVariable("endDate") String endDate) {
        int count = userService.countDateRange(startDate, endDate);
        return new SuccessResultData<>(count);
    }

    @ApiOperation(value = "统计用户", notes = "统计用户接口")
    @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
    @GetMapping("count")
    public SuccessResultData<Integer> count() {
        int count = userService.count();
        return new SuccessResultData<>(count);
    }

    @ApiOperation(value = "统计类型用户", notes = "统计类型用户接口")
    @ApiImplicitParams({@ApiImplicitParam(name = "type", value = "用户类型", paramType = "path"),})
    @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
    @GetMapping("count-type/{type}")
    public SuccessResultData<Integer> countType(@PathVariable("type") Integer type) {
        int count = userService.countType(type);
        return new SuccessResultData<>(count);
    }

    @ApiOperation(value = "统计错误类型用户", notes = "统计用户接口")
    @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
    @GetMapping("count-error-type")
    public SuccessResultData<Integer> countErrorType() {
        int count = userService.countErrorType();
        return new SuccessResultData<>(count);
    }

    @ApiOperation(value = "统计错误类型用户", notes = "统计用户接口")
    @ApiImplicitParams({@ApiImplicitParam(name = "state", value = "用户状态", paramType = "path"),})
    @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
    @GetMapping("count-state/{state}")
    public SuccessResultData<Integer> countState(@PathVariable("state") Integer state) {
        int count = userService.countState(state);
        return new SuccessResultData<>(count);
    }

}
