package com.ozs.web.controller.system;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ozs.common.annotation.Log;
import com.ozs.common.constant.UserConstants;
import com.ozs.common.core.controller.BaseController;
import com.ozs.common.core.domain.AjaxResult;
import com.ozs.common.core.domain.entity.*;
import com.ozs.common.core.domain.model.LoginUser;
import com.ozs.common.core.domain.vo.SysDeptVo;
import com.ozs.common.core.domain.vo.SysUserVo;
import com.ozs.common.enums.BusinessType;
import com.ozs.common.utils.SecurityUtils;
import com.ozs.common.utils.StringUtils;
import com.ozs.common.utils.file.FileUtils;
import com.ozs.common.utils.poi.ExcelUtil;
import com.ozs.entity.BaseUser;
import com.ozs.framework.web.service.TokenService;
//import com.ozs.service.entity.BaseUser;
//import com.ozs.service.service.BaseUserService;
import com.ozs.service.BaseUserService;
import com.ozs.system.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户信息
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/system/user")
@Slf4j
public class SysUserController extends BaseController {
    public static final String PW_PATTERN = "^(?![A-Za-z0-9]+$)(?![a-z0-9\\W]+$)(?![A-Za-z\\W]+$)(?![A-Z0-9\\W]+$)[a-zA-Z0-9\\W]{8,20}$";
    @Autowired
    private ISysUserService userService;

    @Autowired
    private ISysRoleService roleService;

    @Autowired
    private ISysDeptService deptService;

    @Autowired
    private ISysPostService postService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private ISysRoleService iSysRoleService;
    @Value("${base.defaultPassword:yn5aq5Mt.106.tky}")
    private String defaultPassword;
    @Autowired
    private DataScoreUtil dataScoreUtil;
    @Autowired
    private ISysDictTypeService dictTypeService;
    @Resource
    private BaseUserService baseUserService;
//    /**
//     * 获取用户列表
//     */
//    @PreAuthorize("@ss.hasPermi('system:user:list')")
//    @PostMapping("/list")
//    public TableDataInfo list(@RequestBody SysUser user) {
//        startPage();
//        List<SysUser> list = userService.selectUserList(user);
//        return getDataTable(list);
//    }


    /**
     * 获取用户列表
     *
     * @param sysUserVo
     * @return
     */
    @PostMapping("/list")
    @PreAuthorize("@ss.hasPermi('system:user:list')")
    @Log(title = "用户管理", businessType = BusinessType.SELECT)
    public AjaxResult list(@RequestBody SysUserVo sysUserVo) {
        sysUserVo = (SysUserVo) dataScoreUtil.setDataScore(getUserId(), sysUserVo);
        IPage<SysUser> page = userService.queryPage(sysUserVo);
        page.setTotal(page.getTotal());
        page.setCurrent(page.getCurrent());
        page.setPages(page.getPages());

        if (!ObjectUtils.isEmpty(page) && page.getRecords().size() > 0) {
            List<SysUser> dto1 = page.getRecords().stream().map(o -> {
                List<Long> longs = new ArrayList<>();
                SysDept sysDept = deptService.selectDeptById(o.getDeptId());
                if (!ObjectUtils.isEmpty(sysDept)) {
                    o.setDeptName(sysDept.getDeptName());
                }
                if (SysUser.isAdmin(o.getId())) {
                    List<SysRole> roles = roleService.selectRoleAll();
                    List<SysRole> roLe = roles.stream().filter(r -> r.getRoleKey().equals("admin")).collect(Collectors.toList());
                    longs.add(roLe.get(0).getRoleId());
                } else {
                    longs = iSysRoleService.selectRoleListByUserId(o.getId());
                }
                Long[] objects = longs.toArray(new Long[]{});
                QueryWrapper<SysRole> wrapper = new QueryWrapper<>();
                wrapper.in("role_id", Arrays.asList(objects));
                List<SysRole> roles = roleService.list(wrapper);
                List<String> collect = roles.stream().map(SysRole::getRoleName).collect(Collectors.toList());
                o.setRoleNames(collect);
                o.setRoleIds(objects);
                return o;
            }).collect(Collectors.toList());
            page.setRecords(dto1);
        }
        return AjaxResult.success(page);
    }

    @Log(title = "用户管理", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('system:user:export')")
    @PostMapping("/export")
    public void export(HttpServletResponse response, @RequestBody SysUserVo sysUserVo) {
        List<Long> longs = new ArrayList<>();
        sysUserVo = (SysUserVo) dataScoreUtil.setDataScore(getUserId(), sysUserVo);
        List<SysUser> usetList = userService.usetList(sysUserVo);
        for (SysUser sysUser : usetList) {
            StringBuilder stringBuilder = new StringBuilder();
            if (SysUser.isAdmin(sysUser.getId())) {
                List<SysRole> roles = roleService.selectRoleAll();
                List<SysRole> roLe = roles.stream().filter(r -> r.getRoleKey().equals("admin")).collect(Collectors.toList());
                longs.add(roLe.get(0).getRoleId());
            } else {
                longs = roleService.selectRoleListByUserId(sysUser.getId());
            }
            for (Long aLong : longs) {
                SysRole sysRole = roleService.selectRoleById(aLong);
                stringBuilder.append(sysRole.getRoleName());
                stringBuilder.append(",");
                String name = stringBuilder.toString();
                sysUser.setRoleName(name.substring(0, name.length() - 1));
            }
            SysDept sysDept = deptService.selectDeptById(sysUser.getDeptId());
            if (!ObjectUtils.isEmpty(sysDept)) {
                sysUser.setDeptName(sysDept.getDeptName());
            }
        }
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        util.exportExcel(response, usetList, "用户数据");
    }

    @Log(title = "用户管理", businessType = BusinessType.IMPORT)
    @PreAuthorize("@ss.hasPermi('system:user:import')")
    @PostMapping("/importData")
    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception {
        String password = null;
        ExcelUtil<SysUsers> util = new ExcelUtil<SysUsers>(SysUsers.class);
        List<SysUsers> userList = util.importExcel(file.getInputStream());
        String userId = getUserId();
        List<SysDictData> data = dictTypeService.selectDictDataByType("default_password");
        if (!ObjectUtils.isEmpty(data.get(0).getDictValue())) {
            password = data.get(0).getDictValue();
        } else {
            password = defaultPassword;
        }
        String message = userService.importUser(userList, updateSupport, userId, password);
        return success(message);
    }

    @PostMapping("/importTemplate")
    @Log(title = "用户管理", businessType = BusinessType.SELECT)
    public void importTemplate(HttpServletResponse response) {
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        util.importTemplateExcel(response, "用户数据");
    }

    @GetMapping("/downloaExcel")
    @Log(title = "用户管理", businessType = BusinessType.OTHER)
    public void downloadZip(HttpServletResponse response) {
        try {
            InputStream resourceAsStream = this.getClass().getResourceAsStream("/template/SysUser.xlsx");
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, "用户管理信息模板.xlsx");
            FileUtils.writeBytesByInput(resourceAsStream, response.getOutputStream());
        } catch (Exception e) {
            log.error("下载文件失败", e);
        }
    }

    /**
     * 根据用户编号获取详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:user:query')")
    @GetMapping(value = {"/", "/{id}"})
    @Log(title = "用户管理", businessType = BusinessType.MESSAGE)
    public AjaxResult getInfo(@PathVariable(value = "id", required = false) Long id) {
//        userService.checkUserDataScope(id);
        AjaxResult ajax = AjaxResult.success();
        List<SysRole> roles = roleService.selectRoleAll();
        ajax.put("roles", SysUser.isAdmin(id) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
        if (StringUtils.isNotNull(id)) {
            SysUser sysUser = userService.selectUserById(id);
            ajax.put(AjaxResult.DATA_TAG, sysUser);
            if (SysUser.isAdmin(id)) {
                List<SysRole> roLe = roles.stream().filter(r -> r.getRoleKey().equals("admin")).collect(Collectors.toList());
                ajax.put("roleIds", roLe.stream().map(SysRole::getRoleId).collect(Collectors.toList()));
            } else {
                ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList()));
            }
        }
        return ajax;
    }

    /**
     * 新增用户
     */
    @PreAuthorize("@ss.hasPermi('system:user:add')")
    @Log(title = "用户管理", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    public AjaxResult add(@Validated @RequestBody SysUser user) {
        if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user))) {
            return error("新增用户'" + user.getUserName() + "'失败，登录账号已存在");
        } else if (StringUtils.isNotEmpty(user.getPhoneNum())
                && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) {
            return error("新增用户'" + user.getUserName() + "'失败，手机号码已存在");
        } else if (StringUtils.isNotEmpty(user.getEmail())
                && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) {
            return error("新增用户'" + user.getUserName() + "'失败，邮箱账号已存在");
        }
        user.setCreateBy(getUserId());
        user.setUpdateBy(getUserId());
        return toAjax(userService.saveUser(user));
    }

    /**
     * 修改用户
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/edit")
    public AjaxResult edit(@Validated @RequestBody SysUser user) {
//        userService.checkUserAllowed(user);
//        userService.checkUserDataScope(user.getId());
        BaseUser baseUser = baseUserService.getUserById(user.getId());
        if (baseUser.getUserName().equals("admin")) {
            return success("admin账号不能修改");
        }
        if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user))) {
            return error("修改用户'" + user.getUserName() + "'失败，登录账号已存在");
        } else if (StringUtils.isNotEmpty(user.getPhoneNum())
                && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) {
            return error("修改用户'" + user.getUserName() + "'失败，手机号码已存在");
        } else if (StringUtils.isNotEmpty(user.getEmail())
                && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) {
            return error("修改用户'" + user.getUserName() + "'失败，邮箱账号已存在");
        }
        user.setUpdateBy(getUserId());
        return toAjax(userService.updateUsers(user));
    }

    /**
     * 修改用户-web修改个人信息
     */
//    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "/updateUser")
    public AjaxResult updateUser(@RequestBody SysUserUpdate user) {
        if (!StringUtils.isEmpty(user) && !StringUtils.isEmpty(user.getPassword())) {
            boolean matches = user.getPassword().matches(PW_PATTERN);
            if (!matches) {
                return error("您的密码太简单!需要包含大小英文、数字、特殊字符、并且长度8-20");
            }
        }
//        userService.checkUserAllowedUpdate(user);
//        userService.checkUserDataScope(user.getId());
        if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUniqueUpdate(user))) {
            return error("修改用户'" + user.getUserName() + "'失败，登录账号已存在");
        } else if (StringUtils.isNotEmpty(user.getPhoneNum())
                && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUniqueUpdate(user))) {
            return error("修改用户'" + user.getUserName() + "'失败，手机号码已存在");
        } else if (StringUtils.isNotEmpty(user.getEmail())
                && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUniqueUpdate(user))) {
            return error("修改用户'" + user.getUserName() + "'失败，邮箱账号已存在");
        }
        user.setUpdateBy(getUsername());
        user.setUpdateTime(new Date());
        if (!StringUtils.isEmpty(user.getPassword())) {
            user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        }
        int i = userService.updateUsersUpdate(user);
        if (i != 0) {
            // redisCache.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + tokenId);
            // 删除用户缓存记录
            LoginUser loginUser = getLoginUser();
            tokenService.delLoginUser(loginUser.getToken());
        }
        return toAjax(i);
    }

    /**
     * 删除用户
     */
    @PreAuthorize("@ss.hasPermi('system:user:remove')")
    @Log(title = "用户管理", businessType = BusinessType.DELETE)
    @RequestMapping("/remove/{Ids}")
    public AjaxResult remove(@PathVariable Long[] Ids) {
        if (ArrayUtils.contains(Ids, getId())) {
            return error("当前用户不能删除");
        }
        for (Long id : Ids) {
//            BaseUser baseUser = baseUserService.getUserById(id);
//            if (baseUser.getUserName().equals("admin")){
//                return success("admin账号不能修改");
//            }
        }
        return toAjax(userService.deleteUserByIds(Ids));
    }
    ///**
    // * 删除用户
    // */
    //@PreAuthorize("@ss.hasPermi('system:user:remove')")
    //@Log(title = "用户管理", businessType = BusinessType.DELETE)
    //@PostMapping("/del")
    //public AjaxResult remove(@RequestBody List<SysUser> users) {
    //    Long[] userIds = new Long[users.size()];
    //    for (int i = 0; i < users.size(); i++) {
    //        userIds[i] = users.get(i).getUserId();
    //    }
    //    if (ArrayUtils.contains(userIds, getUserId())) {
    //        return error("当前用户不能删除");
    //    }
    //    return toAjax(userService.deleteUserByIds(userIds));
    //}

    /**
     * 重置密码
     */
    @PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @GetMapping("/resetPwd/{id}")
    public AjaxResult resetPwd(@PathVariable(value = "id") Long id) {
        SysUser user = new SysUser();
        user.setId(id);
        user.setPassword(SecurityUtils.encryptPassword(defaultPassword));
        user.setUpdateBy(getUsername());
        return toAjax(userService.resetPwd(user));
    }


    /**
     * 修改密码
     */
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @RequestMapping("/updatePassWord")
    public AjaxResult updatePassWord(@RequestBody SysUser user) {
        LoginUser loginUser = getLoginUser();
        if (!SecurityUtils.matchesPassword(user.getPassword(), loginUser.getPassword())) {
            return error("修改密码失败，旧密码错误");
        }
        boolean matches = user.getNewPassword().matches(PW_PATTERN);
        if (!matches) {
            return error("您的密码太简单!需要包含大小英文、数字、特殊字符、并且长度8-20");
        }
        if (SecurityUtils.matchesPassword(user.getNewPassword(), loginUser.getPassword())) {
            return error("新密码不能与旧密码相同");
        }
        user.setPassword(SecurityUtils.encryptPassword(user.getNewPassword()));
        user.setUpdateBy(getUsername());
        if (userService.resetPwd(user) > 0) {
            // 更新缓存用户密码
            loginUser.getUser().setPassword(SecurityUtils.encryptPassword(user.getNewPassword()));
            tokenService.setLoginUser(loginUser);
            return success();
        }
        return error("修改密码异常，请联系管理员");
    }

    /**
     * 状态修改
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @RequestMapping("/changeStatus")
    public AjaxResult changeStatus(@RequestBody SysUser user) {
//        userService.checkUserAllowed(user);
//        userService.checkUserDataScope(user.getId());
        user.setUpdateBy(getUsername());
        return toAjax(userService.updateUserStatus(user));
    }

    /**
     * 根据用户编号获取授权角色
     */
    @PreAuthorize("@ss.hasPermi('system:user:query')")
    @GetMapping("/authRole/{userId}")
    @Log(title = "用户管理", businessType = BusinessType.MESSAGE)
    public AjaxResult authRole(@PathVariable("userId") Long id) {
        AjaxResult ajax = AjaxResult.success();
        SysUser user = userService.selectUserById(id);
        List<SysRole> roles = roleService.selectRolesByUserId(id);
        ajax.put("user", user);
        ajax.put("roles", SysUser.isAdmin(id) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
        return ajax;
    }

    /**
     * 用户授权角色
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.GRANT)
    @RequestMapping("/authRole")
    public AjaxResult insertAuthRole(Long userId, Long[] roleIds) {
//        userService.checkUserDataScope(userId);
        userService.insertUserAuth(userId, roleIds);
        return success();
    }

    /**
     * 获取部门树列表
     */
    @PreAuthorize("@ss.hasPermi('system:user:list')")
    @GetMapping("/deptTree")
    @Log(title = "用户管理", businessType = BusinessType.OTHER)
    public AjaxResult deptTree(SysDeptVo dept) {
        return success(deptService.selectDeptTreeList(dept));
    }

    /**
     * 数据权限分配
     */
    @GetMapping("/dataPermission/{id}/{dataPermission}")
    @Log(title = "用户管理", businessType = BusinessType.GRANT)
    public AjaxResult dataPermission(@PathVariable("id") Long id, @PathVariable("dataPermission") Integer dataPermission) {
        BaseUser baseUser = baseUserService.getUserById(id);
        if (baseUser.getUserName().equals("admin")) {
            return success("admin账号不能修改");
        }
        if (userService.dataPermission(id, dataPermission)) {
            return success();
        } else {
            return error();
        }
    }
}
