package com.sw.mes.auth.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sw.mes.auth.domain.AuthRole;
import com.sw.mes.auth.domain.AuthUser;
import com.sw.mes.auth.domain.AuthUserRole;
import com.sw.mes.auth.service.AuthRoleService;
import com.sw.mes.auth.service.AuthUserRoleService;
import com.sw.mes.auth.service.AuthUserService;
import com.sw.mes.auth.utils.ExcelUtil;
import com.sw.mes.core.annotation.TokenNotValidation;
import com.sw.mes.core.constant.Constants;
import com.sw.mes.core.context.BaseContextHandler;
import com.sw.mes.core.dto.auth.UserClassDto;
import com.sw.mes.core.dto.auth.UserDto;
import com.sw.mes.core.dto.auth.UserImportDto;
import com.sw.mes.core.enums.AuthRoleTypeEnum;
import com.sw.mes.core.response.ResponsePage;
import com.sw.mes.core.response.Result;
import com.sw.mes.core.response.ResultGenerator;
import com.sw.mes.core.utils.BeanUtil;
import com.sw.mes.core.utils.EasyExcelUtils;
import com.sw.mes.core.utils.RequestPage;
import com.sw.mes.auth.utils.PasswordUtil;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.modelmapper.ModelMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @Author
 * @Description：
 * @Date: Create in
 * @Modified By:
 */
@RestController
@RequestMapping("/user")
@Slf4j
@Api(description = "用户信息接口")
public class UserController {
    @Autowired
    ModelMapper modelMapper;

    @Autowired
    private AuthUserService authUserService;

    @Autowired
    private AuthRoleService authRoleService;

    @Autowired
    AuthUserRoleService authUserRoleService;

    @ApiOperation(value = "分页查询用户信息列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "rows", value = "行数", dataType = "integer", paramType = "query"),
            @ApiImplicitParam(name = "page", value = "页码", dataType = "integer", paramType = "query"),
            @ApiImplicitParam(name = "search_LIKE_loginName", value = "登录名称", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_LIKE_realName", value = "姓名", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_LIKE_workNo", value = "工号", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_LIKE_cardNumber", value = "卡号", dataType = "string", paramType = "query"),
    })
    @GetMapping("/listByPage")
    public Result<ResponsePage<UserDto>> listByPage(ServletRequest request, @ApiIgnore RequestPage requestPage) {
        LambdaQueryWrapper<AuthUser> queryWrapper = new LambdaQueryWrapper<>();
        if (request.getParameter("search_LIKE_loginName") != null) {
            queryWrapper.like(AuthUser::getLoginName, request.getParameter("search_LIKE_loginName"));
        }
        if (request.getParameter("search_LIKE_realName") != null) {
            queryWrapper.like(AuthUser::getRealName, request.getParameter("search_LIKE_realName"));
        }
        if (request.getParameter("search_LIKE_workNo") != null) {
            queryWrapper.like(AuthUser::getWorkNo, request.getParameter("search_LIKE_workNo"));
        }
        if (request.getParameter("search_LIKE_cardNumber") != null) {
            queryWrapper.like(AuthUser::getCardNumber, request.getParameter("search_LIKE_cardNumber"));
        }
        queryWrapper.orderByDesc(AuthUser::getId);
        Page<AuthUser> listPage = authUserService.page(new Page<>(requestPage.getPage(), requestPage.getRows()), queryWrapper);
        List<UserDto> dtos = listPage.getRecords().stream()
                .map(entity -> toLazyDto1(entity))
                .collect(Collectors.toList());
        ResponsePage responsePage = new ResponsePage(dtos, listPage.getTotal());
        return ResultGenerator.success(responsePage);
    }

    @ApiOperation(value = "下拉框查询用户信息列表")
    @GetMapping("/listAll")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "search_LIKE_realName", value = "真实姓名", paramType = "query", dataType = "string"),
    })
    public Result<List<UserDto>> listAll(ServletRequest request) {
        LambdaQueryWrapper<AuthUser> queryWrapper = new LambdaQueryWrapper<>();
        if (request.getParameter("search_LIKE_realName") != null) {
            queryWrapper.like(AuthUser::getRealName, request.getParameter("search_LIKE_realName"));
        }
        if (request.getParameter("search_LIKE_workNo") != null) {
            queryWrapper.like(AuthUser::getWorkNo, request.getParameter("search_LIKE_workNo"));
        }
        List<AuthUser> users = authUserService.list(queryWrapper);
        List<UserDto> userDtos = users.stream()
                .map(user -> toLazyDto(user))
                .collect(Collectors.toList());
        return ResultGenerator.success(userDtos);


    }

    @ApiOperation(value = "当前用户信息详细信息")
    @ApiImplicitParams({
    })
    @GetMapping("/getCurrentUserInfo")
    public Result<UserDto> get() {
        Integer userID = BaseContextHandler.getUserID();
        if (null == userID) {
            return ResultGenerator.fail("用户未登录");
        }
        AuthUser user = authUserService.getById(userID);
        return ResultGenerator.success(toEagerDto(user));
    }

    @ApiOperation(value = "用户信息详细信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "用户信息id", paramType = "path", dataType = "Integer"),
    })
    @GetMapping("/{id}")
    public Result<UserDto> get(@PathVariable Integer id) {
        AuthUser user = authUserService.getById(id);
        if (null == user) {
            return ResultGenerator.fail("该用户不存在");
        }
        return ResultGenerator.success(toEagerDto(user));
    }

    @ApiOperation(value = "创建用户信息")
    @PostMapping("/create")
    public Result create(HttpServletRequest request, @RequestBody @Valid @ApiParam(value = "用户信息对象") UserDto userDto, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        }
        if (StringUtils.isEmpty(userDto.getLoginName())) {
            return ResultGenerator.fail("登录名称不能为空");
        }
        if (StringUtils.isEmpty(userDto.getRealName())) {
            return ResultGenerator.fail("姓名不能为空");
        }
        if (StringUtils.isEmpty(userDto.getPassword())) {
            return ResultGenerator.fail("初始密码不能为空");
        }
        if (StringUtils.isEmpty(userDto.getWorkNo())) {
            return ResultGenerator.fail("工号不能为空");
        }
        if (StringUtils.isEmpty(userDto.getClassName())) {
            return ResultGenerator.fail("班次不能为空");
        }
        if (StringUtils.isEmpty(userDto.getClassTeam())) {
            return ResultGenerator.fail("班组不能为空");
        }
        if (StringUtils.isNotEmpty(userDto.getCardNumber())) {
            AuthUser card = authUserService.getByCardNumber(userDto.getCardNumber());
            if (card != null) {
                return ResultGenerator.fail("该卡号已存在！");
            }
        }

        AuthUser user = fromDto(userDto);
        AuthUser login = authUserService.findByLoginName(user.getLoginName());
        if (login != null) {
            return ResultGenerator.fail("登录名称已存在！");
        }
        try {
            PasswordUtil.HashPassword hashPassword = PasswordUtil.encryptPassword(user.getPassword());
            user.setSalt(hashPassword.salt);
            user.setPassword(hashPassword.password);
        } catch (Exception e) {
            e.printStackTrace();
        }
        user.setCreateTime(new Date());
        user.setStatus(Constants.USER_ORIGINAL);
        authUserService.saveOrUpdate(user);
        return ResultGenerator.success();
    }

    @ApiOperation(value = "更新用户信息")
    @PostMapping("/update")
    public Result update(@RequestBody @Valid @ApiParam(value = "用户信息") UserDto dto, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        }
        if (dto.getId() == null) {
            return ResultGenerator.fail("id不能为空");
        }
        if (StringUtils.isEmpty(dto.getLoginName())) {
            return ResultGenerator.fail("登录名称不能为空");
        }
        if (StringUtils.isEmpty(dto.getRealName())) {
            return ResultGenerator.fail("姓名不能为空");
        }
        if (StringUtils.isEmpty(dto.getWorkNo())) {
            return ResultGenerator.fail("工号不能为空");
        }
        if (StringUtils.isEmpty(dto.getClassName())) {
            return ResultGenerator.fail("班次不能为空");
        }
        if (StringUtils.isEmpty(dto.getClassTeam())) {
            return ResultGenerator.fail("班组不能为空");
        }
        AuthUser entity = authUserService.getById(dto.getId());
        if (entity == null) {
            return ResultGenerator.fail("原信息不存在");
        }

        AuthUser login = authUserService.findByLoginName(dto.getLoginName());
        if (login != null && !entity.getId().equals(login.getId())) {
            return ResultGenerator.fail("登录名称已存在！");
        }

        if (StringUtils.isNotBlank(dto.getCardNumber())) {
            AuthUser card = authUserService.getByCardNumber(dto.getCardNumber());
            if (card != null && !entity.getId().equals(card.getId())) {
                return ResultGenerator.fail("该卡号已存在！");
            }
        }

        try {
            AuthUser entityfromFto = fromDto(dto);
            //如果编辑的密码不为空
            if (!StringUtils.isBlank(entityfromFto.getPassword())) {
                PasswordUtil.HashPassword hashPassword = PasswordUtil.encryptPassword(entityfromFto.getPassword());
                entityfromFto.setSalt(hashPassword.salt);
                entityfromFto.setPassword(hashPassword.password);
            }

//            PropertyUtils.copyProperties(entity, entityfromFto);
            BeanUtils.copyProperties(entityfromFto, entity, BeanUtil.getIgnoreProperties(entityfromFto, null, null));
            authUserService.saveOrUpdate(entity);
            return ResultGenerator.success();
        } catch (Exception e) {
            return ResultGenerator.fail(e.getMessage());
        }
    }

    @ApiOperation(value = "更新用户密码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户Id", dataType = "integer", paramType = "query", required = false, readOnly = false),
            @ApiImplicitParam(name = "password", value = "密码", dataType = "integer", paramType = "query", required = false, readOnly = false),
    })
    @PostMapping("/updatePassword")
    public Result<String> updatePassword(Integer userId, String password) {
        if (null == userId) {
            return ResultGenerator.fail("userId不能为空");
        }
        if (StringUtils.isBlank(password)) {
            return ResultGenerator.fail("userId不能为空");
        }
        AuthUser user = authUserService.getById(userId);
        try {
            PasswordUtil.HashPassword hashPassword = PasswordUtil.encryptPassword(password);
            user.setSalt(hashPassword.salt);
            user.setPassword(hashPassword.password);
            authUserService.saveOrUpdate(user);
            return ResultGenerator.success();
        } catch (Exception e) {
            e.printStackTrace();
            return ResultGenerator.fail(e.getMessage());
        }
    }

    @GetMapping("/getRolesByUserId")
    @ApiOperation(value = "根据用户Id获取角色集合，返回为角色Id集合")
    public Result<String> getRolesByUserId(Integer userId) {
        List<AuthUserRole> byUserId = authUserRoleService.findByUserId(userId);
        List<String> ids = new ArrayList<>();
        byUserId.forEach(userRole -> {
            ids.add(userRole.getRoleId().toString());
        });
        return ResultGenerator.success(StringUtils.join(ids
                , ","));
    }

    @PostMapping("/getRolesByUserIds")
    @ApiOperation(value = "根据用户Id获取角色集合，返回为角色Id集合")
    public Result<List<Integer>> getRolesByUserIds(Integer userId,Integer type) {
        List<AuthUserRole> authUserRoles = authUserRoleService.findByUserIds(userId,type);
        List<Integer> authUserRolesIds = authUserRoles.stream().map(authUserRole -> {
            return authUserRole.getRoleId();
        }).collect(Collectors.toList());
        return ResultGenerator.success(authUserRolesIds);
    }

    @ApiOperation(value = "分配角色")
    @PostMapping("/editRole")
    public Result editRole(@ApiParam(value = "用户id") @RequestParam Integer userId, @ApiParam(value = "角色id集合,逗号分隔,如1,3") @RequestParam String roleIds) {
        if (userId == null) {
            return ResultGenerator.fail("用户Id不能为空");
        }
        if (StringUtils.isEmpty(roleIds)) {
            return ResultGenerator.fail("角色Id不能为空");
        }
        authUserRoleService.deleteByUserId(userId);
        String[] split = roleIds.split(",");

        for (String idstr : split) {
            Integer roleid = Integer.parseInt(idstr);
            AuthUserRole userRole = new AuthUserRole();
            userRole.setRoleId(roleid);
            userRole.setUserId(userId);
            authUserRoleService.saveOrUpdate(userRole);
        }
        return ResultGenerator.success();
    }

    @ApiOperation(value = "用户导入")
    @PostMapping("/importUser")
    public Result importUser(MultipartFile file) {

        try {
            Object objList = EasyExcelUtils.readExcel(file, new UserImportDto(), 1, 1);
            if (objList != null) {
                List<UserImportDto> users = (List<UserImportDto>) objList;
                authUserService.importUser(users);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("用户导入错误：", e);
            return ResultGenerator.fail(e.getMessage());
        }
        return ResultGenerator.success();
    }

    @ApiOperation(value = "用户导入模版下载")
    @PostMapping("/downloadUserTemplate")
    @TokenNotValidation
    public Result exportUserTemplate(HttpServletResponse response) {
        String path = "template/用户导入模版.xlsx";
        ExcelUtil.download1(path, response);
        return ResultGenerator.success();
    }

    @ApiOperation(value = "删除用户")
    @PostMapping("/delete")
    public Result remove(@ApiParam(value = "id集合,逗号分隔,如2,4", type = "query") @RequestParam Integer[] ids) {
        for (Integer id : ids) {
            authUserService.removeById(id);
        }
        return ResultGenerator.success();
    }


    @ApiOperation(value = "获取PC端系统在线人数")
    @GetMapping("/getOnLineUserCount")
    public Result<Integer> getOnLineUserCount() {
        return ResultGenerator.success(authUserService.getOnLineUserCount());
    }

    @ApiOperation(value = "根据权限获取用户")
    @PostMapping("/getByUser")
    public Result<List<UserDto>> getByUser(String name) {
        List<AuthUser> users = authUserService.getByUserName(name);
        if (null == users) {
            return ResultGenerator.fail("该用户不存在");
        }

        List<UserDto> userDtos = users.stream()
                .map(user -> toLazyDto(user))
                .collect(Collectors.toList());
        return ResultGenerator.success(userDtos);
    }


    public UserDto toLazyDto(AuthUser entity) {
        UserDto userDto = modelMapper.map(entity, UserDto.class);
        userDto.setPassword(null);
        return userDto;
    }

    public UserDto toLazyDto1(AuthUser entity) {
        UserDto userDto = modelMapper.map(entity, UserDto.class);
        userDto.setPassword(null);
        List<AuthUserRole> byUserId = authUserRoleService.findByUserId(entity.getId());
        List<String> ids = new ArrayList<>();
        byUserId.forEach(userRole -> {
            ids.add(userRole.getRoleId().toString());
        });
        if (ids.size() > 0) {
            List<AuthRole> list = authRoleService.findByids(ids);
            list.forEach(item -> {
                if (item.getType() == AuthRoleTypeEnum.FUNCTION_ROLE.getKey()) {
                    Map<Integer, List<AuthRole>> authRoleMap = list.stream().collect(Collectors.groupingBy(AuthRole::getType));
                    List<String> roleNameList = authRoleMap.get(item.getType()).stream().map(AuthRole::getName).collect(Collectors.toList());
                    userDto.setFunctionRoleNames(StringUtils.join(roleNameList, ","));
                } else {
                    Map<Integer, List<AuthRole>> authRoleMap = list.stream().collect(Collectors.groupingBy(AuthRole::getType));
                    List<String> roleNameList = authRoleMap.get(item.getType()).stream().map(AuthRole::getName).collect(Collectors.toList());
                    userDto.setDataRoleNames(StringUtils.join(roleNameList, ","));
                }
                userDto.setType(item.getType());
            });
        }
        return userDto;
    }

    public UserDto toEagerDto(AuthUser entity) {
        UserDto userDto = modelMapper.map(entity, UserDto.class);
        userDto.setPassword(null);
        return userDto;
    }

    public AuthUser fromDto(UserDto dto) {
        return modelMapper.map(dto, AuthUser.class);
    }


    /**
     * 根据工号查询用户信息
     */
    @PostMapping("/findByWorkNo")
    Result<UserDto> findByWorkNo(String receiverCode) {
        AuthUser user = authUserService.findByWorkNo(receiverCode);
        UserDto userDto = modelMapper.map(user, UserDto.class);
        return ResultGenerator.success(userDto);
    }


    /**
     * 根据工号查询用户信息
     */
    @PostMapping("/getUserById")
    Result<UserDto> getUserById(Integer userId) {
        AuthUser user = authUserService.getById(userId);
        UserDto userDto = modelMapper.map(user, UserDto.class);
        return ResultGenerator.success(userDto);
    }

    @PostMapping("/loginByCardNo")
    public Result<Map<String, Object>> loginByCardNo(String cardNo) {
        Result<Map<String, Object>> result = new Result<>();
        try {
            Map<String, Object> map = authUserService.loginByCardNo(cardNo);
            result.setData(map);
        } catch (Exception e) {
            result.setData(new HashMap<>());
        }
        return result;
    }

    @PostMapping("/loginByUsername")
    public Result<Map<String, Object>> loginByUsername(String username, String password) {
        Result<Map<String, Object>> result = new Result<>();
        try {
            Map<String, Object> map = authUserService.loginByUsername(username, password);
            result.setData(map);
        } catch (Exception e) {
            result.setData(new HashMap<>());
        }
        return result;
    }

    @PostMapping("/getPermissionByLoginName")
    public Result<Map<String, Object>> getPermissionByLoginName(String username, String password) {
        Result<Map<String, Object>> result = new Result<>();
        try {
            Map<String, Object> map = authUserService.getPermissionByLoginName(username, password);
            result.setData(map);
        } catch (Exception e) {
            result.setData(new HashMap<>());
        }
        return result;
    }

    @PostMapping("/findByUserName")
    public Result<List<UserDto>> findByUserName(String userName) {
        Result<List<UserDto>> result = new Result<>();
        List<UserDto> userDtoList = new ArrayList<>();
        try {
            List<AuthUser> byUserName = authUserService.findByUserName(userName);
            if (!CollectionUtils.isEmpty(byUserName)) {
                byUserName.stream().forEach((t) -> {
                    userDtoList.add(modelMapper.map(t, com.sw.mes.core.dto.auth.UserDto.class));
                });
            }
            result.setData(userDtoList);
        } catch (Exception e) {
            result.setData(userDtoList);
        }
        return result;
    }

    @PostMapping("/findByLoginName")
    public Result<UserDto> findByLoginName(String loginName) {
        AuthUser user = authUserService.findByLoginName(loginName);
        UserDto userDto = modelMapper.map(user, UserDto.class);
        return ResultGenerator.success(userDto);
    }

    @PostMapping("/findByLoginNameIn")
    public Result<List<UserDto>> findByLoginNameIn(List<String> userName) {
        Result<List<UserDto>> result = new Result<>();
        List<UserDto> userDtoList = new ArrayList<>();
        try {
            List<AuthUser> byUserName = authUserService.findByLoginNameIn(userName);
            if (!CollectionUtils.isEmpty(byUserName)) {
                byUserName.stream().forEach((t) -> {
                    userDtoList.add(modelMapper.map(t, com.sw.mes.core.dto.auth.UserDto.class));
                });
            }
            result.setData(userDtoList);
        } catch (Exception e) {
            result.setData(userDtoList);
        }
        return result;
    }


    @ApiOperation(value = "通过登录名获取班组/班次")
    @PostMapping("/findClassInfoByLoginName")
    public Result<UserClassDto> findClassInfoByLoginName(String loginName) {
        AuthUser user = authUserService.findByLoginName(loginName);
        UserClassDto userDto = new UserClassDto();
        userDto.setLoginName(loginName);
        if (null != user) {
            userDto.setClassName(user.getClassName());
            userDto.setClassTeam(user.getClassTeam());
        }
        return ResultGenerator.success(userDto);
    }

}
