package com.zd.system.controller;

import com.zd.common.core.constant.Constants;
import com.zd.common.core.constant.UserConstants;
import com.zd.common.core.domain.R;
import com.zd.common.core.domain.per.PerFun;
import com.zd.common.core.domain.per.PerPrefix;
import com.zd.common.core.utils.SecurityUtils;
import com.zd.common.core.utils.StringUtils;
import com.zd.common.core.utils.poi.ExcelUtil;
import com.zd.common.core.web.controller.BaseController;
import com.zd.common.core.web.domain.AjaxResult;
import com.zd.common.core.web.page.TableDataInfo;
import com.zd.common.log.annotation.Log;
import com.zd.common.log.enums.BusinessType;
import com.zd.common.redis.service.RedisService;
import com.zd.common.security.annotation.InnerAuth;
import com.zd.common.security.annotation.PreAuthorize;
import com.zd.system.api.domain.*;
import com.zd.system.api.model.LoginUser;
import com.zd.system.domain.SysPost;
import com.zd.system.service.*;
import io.swagger.annotations.Api;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 用户学生信息
 *
 * @author zd
 */
@RestController
@RequestMapping("/user/student")
@Api(tags = {"学生管理"})
public class SysStudentController extends BaseController {
    @Autowired
    private ISysStudentService sysStudentService;

    @Autowired
    private ISysRoleService roleService;

    @Autowired
    private ISysPostService postService;

    @Autowired
    private ISysPermissionService permissionService;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    RedisService redisService;
    @Autowired
    private ISysUserService userService;

    private static String USER_TYPE = UserConstants.USER_TYPE_STUDENT;

    /**
     * 获取用户列表 "system:user_student:list"
     */
    @PreAuthorize(hasPermi = PerPrefix.SYSTEM_USER_STUDENT+ PerFun.LIST)
    @GetMapping("/list")
    public TableDataInfo list(SysUser user) {
        user.setUserType(USER_TYPE);
        startPage();
        List<SysUser> list = sysStudentService.selectUserList(user);
        return getDataTable(list);
    }

    //"system:user_student:export"
    @Log(title = "用户管理", businessType = BusinessType.EXPORT)
    @PreAuthorize(hasPermi = PerPrefix.SYSTEM_USER_STUDENT+ PerFun.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysUser user) throws IOException {
        user.setUserType(USER_TYPE);
        List<SysUser> list = sysStudentService.selectUserList(user);

        List<SysUserStudentByExport> studentList = new ArrayList<>();
        for (SysUser sysUser : list) {
            studentList.add(new SysUserStudentByExport(sysUser));
        }
        ExcelUtil<SysUserStudentByExport> util = new ExcelUtil<>(SysUserStudentByExport.class);
        //本地日期,不包括时分秒
        LocalDate nowDate = LocalDate.now();
        util.exportExcel(response, studentList, "学生信息导出数据表",null,"学生信息导出数据表"+nowDate);
    }

    //"system:user_student:import"
    @Log(title = "学生管理", businessType = BusinessType.IMPORT)
    @PreAuthorize(hasPermi = PerPrefix.SYSTEM_USER_STUDENT+ PerFun.IMPORT)
    @PostMapping("/importData")
    public AjaxResult importData(MultipartFile file, boolean updateSupport,SysUserStudentByExcel sysUserStudentByExcel) throws Exception {
        ExcelUtil<SysUserStudentByExcel> util = new ExcelUtil<SysUserStudentByExcel>(SysUserStudentByExcel.class);
        List<SysUserStudentByExcel> userList = util.importExcel(file.getInputStream(),true);
        String operName = SecurityUtils.getUsername();
        List<SysUserStudentByExcel> sysUserStudentByExcels = sysStudentService.importUserByStudent(userList, updateSupport, operName,sysUserStudentByExcel);
        Map <String,Object> resultMap = new HashMap <>();
        resultMap.put("totalNum",userList.size());
        resultMap.put("successNum",userList.size()- sysUserStudentByExcels.size());
        resultMap.put("failureNum", sysUserStudentByExcels.size());
        resultMap.put("downFile", sysUserStudentByExcels.size()>0?true:false);
        if(sysUserStudentByExcels.size()>0){
            redisService.setCacheObject("exportByStudent"+SecurityUtils.getUserId(), sysUserStudentByExcels, 1L, TimeUnit.HOURS);
        }
        return AjaxResult.success(resultMap);
    }

    @Log(title = "学员导出错误数据", businessType = BusinessType.IMPORT)
    @PreAuthorize(hasPermi = PerPrefix.SYSTEM_USER_STUDENT+ PerFun.IMPORT)
    @PostMapping("/importErrorData")
    public void importErrorData(HttpServletResponse response) throws Exception {
        String tips = "导入注意事项：（未按如下要求填写，会导致数据不能正常导入）\n" +
                "1、请不要修改此表格的格式，包括插入删除行和列、合并拆分单元格等。请在表格里面逐行录入数据。一次最多导入5000条数据信息。\n" +
                "2、需要填写的单元格字段规则校验，请按照提示输入。\n" +
                "3、请不要随意复制单元格，这样会破坏字段规则校验。\n" +
                "4、带有星号（*）的红色字段为必填项。\n" +
                "5、请注意：工号、联系电话是唯一的，不能重复，不可多条；工号限制最大7个字符，联系电话限制最大13个字符。\n" +
                "6、请注意：出生日期填写为：YYYY-MM-DD。\n" +
                "7、所在部门需填写系统中已录入的部门名称，否则无法正常导入。";
        ExcelUtil<SysUserStudentByExcel> util = new ExcelUtil<SysUserStudentByExcel>(SysUserStudentByExcel.class);
        List<SysUserStudentByExcel> sysUserStudentByExcels = redisService.getCacheObject("exportByStudent"+SecurityUtils.getUserId());
        if(sysUserStudentByExcels.size()>0){
            util.exportExcel(response, sysUserStudentByExcels, "未导入的用户数据", tips, "学生信息批量导入模板");
        }
    }

    @PostMapping("/importTemplate")
    @PreAuthorize(hasPermi = PerPrefix.SYSTEM_USER_STUDENT+ PerFun.EXCELTEMPLATE)
    public void importTemplate(HttpServletResponse response) throws IOException {
        String tips = "导入注意事项：（未按如下要求填写，会导致数据不能正常导入）\n" +
                "1、请不要修改此表格的格式，包括插入删除行和列、合并拆分单元格等。请在表格里面逐行录入数据。一次最多导入5000条数据信息。\n" +
                "2、需要填写的单元格字段规则校验，请按照提示输入。\n" +
                "3、请不要随意复制单元格，这样会破坏字段规则校验。\n" +
                "4、带有星号（*）的红色字段为必填项。\n" +
                "5、请注意：工号、联系电话是唯一的，不能重复，不可多条；工号限制最大7个字符，联系电话限制最大13个字符。\n" +
                "6、请注意：出生日期填写为：YYYY-MM-DD。\n" +
                "7、所在部门需填写系统中已录入的部门名称，否则无法正常导入。";
        ExcelUtil<SysUserStudentByExcel> util = new ExcelUtil<SysUserStudentByExcel>(SysUserStudentByExcel.class);
//        util.importTemplateExcel(response, "用户数据");
        util.exportExcel(response, null, "学生信息批量导入模板", tips, "学生信息批量导入模板");
    }

    /**
     * 注册用户信息
     */
    @InnerAuth
    @PostMapping("/register")
    public R<Boolean> register(@RequestBody SysUser sysUser) {
        String username = sysUser.getUserName();
        if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser")))) {
            return R.fail("当前系统没有开启注册功能！");
        }
        if (UserConstants.NOT_UNIQUE.equals(sysStudentService.checkUserNameUnique(username))) {
            return R.fail("保存用户'" + username + "'失败，注册账号已存在");
        }
        return R.ok(sysStudentService.registerUser(sysUser));
    }

    /**
     * 根据用户编号获取详细信息 "system:user_student:query"
     */
    @PreAuthorize(hasPermi = PerPrefix.SYSTEM_USER_STUDENT+ PerFun.QUERY)
    @GetMapping(value = {"/", "/{userId}"})
    public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) {
        AjaxResult ajax = AjaxResult.success();
        List<SysRole> roles = roleService.selectRoleAll();
        ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
        ajax.put("posts", postService.selectPostAll(new SysPost()));
        if (StringUtils.isNotNull(userId)) {
            SysUser sysUser = sysStudentService.selectUserById(userId);
            if(StringUtils.isNotNull(sysUser.getCardNum())){
                try{
                    long num = Long.parseLong(sysUser.getCardNum(),16);
                    sysUser.setCardNum(num+"");
                }catch (Exception e){
                    logger.info("卡号解密失败===="+sysUser.getCardNum());
                }
            }
            ajax.put(AjaxResult.DATA_TAG, sysUser);
            ajax.put("postIds", postService.selectPostListByUserId(userId));
            ajax.put("roleIds", roleService.selectRoleListByUserId(userId));
        }
        return ajax;
    }

    /**
     * 新增用户 "system:user_student:add"
     */
    @PreAuthorize(hasPermi = PerPrefix.SYSTEM_USER_STUDENT+ PerFun.ADD)
    @Log(title = "用户管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysUser user) {
        user.setUserType(USER_TYPE);
        if (UserConstants.NOT_UNIQUE.equals(sysStudentService.checkUserNameUnique(user.getUserName()))) {
            return AjaxResult.error("新增用户'" + user.getUserName() + "'失败，登录账号已存在");
        } else if (StringUtils.isNotEmpty(user.getPhonenumber())
                && UserConstants.NOT_UNIQUE.equals(sysStudentService.checkPhoneUnique(user))) {
            return AjaxResult.error("新增用户'" + user.getUserName() + "'失败，手机号码已存在");
        } else if (StringUtils.isNotEmpty(user.getEmail())
                && UserConstants.NOT_UNIQUE.equals(sysStudentService.checkEmailUnique(user))) {
            return AjaxResult.error("新增用户'" + user.getUserName() + "'失败，邮箱账号已存在");
        }
        user.setCreateBy(SecurityUtils.getUsername());
        String password = configService.selectConfigByKey("sys.user.initPassword");
        user.setPassword(SecurityUtils.encryptPassword(password));
        user.setPosition("4");
        return toAjax(sysStudentService.insertUser(user));
    }

    /**
     * 修改用户 "system:user_student:edit"
     */
    @PreAuthorize(hasPermi = PerPrefix.SYSTEM_USER_STUDENT+ PerFun.EDIT)
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysUser user) {
        user.setUserType(USER_TYPE);
        sysStudentService.checkUserAllowed(user);
        if (StringUtils.isNotEmpty(user.getPhonenumber())
                && UserConstants.NOT_UNIQUE.equals(sysStudentService.checkPhoneUnique(user))) {
            return AjaxResult.error("修改用户'" + user.getUserName() + "'失败，手机号码已存在");
        } else if (StringUtils.isNotEmpty(user.getEmail())
                && UserConstants.NOT_UNIQUE.equals(sysStudentService.checkEmailUnique(user))) {
            return AjaxResult.error("修改用户'" + user.getUserName() + "'失败，邮箱账号已存在");
        }
        if(StringUtils.isNotEmpty(user.getCardNum())){
            Long carNum10 = Long.parseLong(user.getCardNum());
            String carNum16 = carNum10.toHexString(carNum10).toUpperCase();
            SysUser sysUser= userService.selectUserInfoByCardNum(carNum16);
            if(null!=sysUser && user.getUserId().intValue()!=sysUser.getUserId().intValue()){
                return AjaxResult.error(user.getCardNum()+"已与"+sysUser.getNickName()+"绑定,无法提交");
            }
        }
        user.setUpdateBy(SecurityUtils.getUsername());
        return toAjax(sysStudentService.update(user));
    }

    @PutMapping("/editStudent")
    public AjaxResult editStudent(@Validated @RequestBody SysUser user) {
        user.setUserType(USER_TYPE);
        sysStudentService.checkUserAllowed(user);
        if (StringUtils.isNotEmpty(user.getPhonenumber())
                && UserConstants.NOT_UNIQUE.equals(sysStudentService.checkPhoneUnique(user))) {
            return AjaxResult.error("修改用户'" + user.getUserName() + "'失败，手机号码已存在");
        } else if (StringUtils.isNotEmpty(user.getEmail())
                && UserConstants.NOT_UNIQUE.equals(sysStudentService.checkEmailUnique(user))) {
            return AjaxResult.error("修改用户'" + user.getUserName() + "'失败，邮箱账号已存在");
        }
        user.setUpdateBy(SecurityUtils.getUsername());
        return toAjax(sysStudentService.updateUserStatus(user));
    }

    /**
     * 删除用户 "system:user_student:remove"
     */
    @PreAuthorize(hasPermi = PerPrefix.SYSTEM_USER_STUDENT+ PerFun.REMOVE)
    @Log(title = "用户管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{userIds}")
    public AjaxResult remove(@PathVariable Long[] userIds) {
        if (ArrayUtils.contains(userIds, SecurityUtils.getUserId())) {
            return AjaxResult.error("当前用户不能删除");
        }
        return toAjax(sysStudentService.deleteUserByIds(userIds));
    }

    /**
     * 重置密码 "system:user_student:edit"
     */
    @PreAuthorize(hasPermi = PerPrefix.SYSTEM_USER_STUDENT+ PerFun.RESETPWD)
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping("/resetPwd")
    public AjaxResult resetPwd(@RequestBody SysUser user) {
        user.setUserType(USER_TYPE);
        sysStudentService.checkUserAllowed(user);
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        user.setUpdateBy(SecurityUtils.getUsername());
        return toAjax(sysStudentService.resetPwd(user));
    }

    /**
     * 状态修改 "system:user_student:edit"
     */
    @PreAuthorize(hasPermi = PerPrefix.SYSTEM_USER_STUDENT+ PerFun.EDIT)
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping("/changeStatus")
    public AjaxResult changeStatus(@RequestBody SysUser user) {
        sysStudentService.checkUserAllowed(user);
        user.setUpdateBy(SecurityUtils.getUsername());
        return toAjax(sysStudentService.updateUserStatus(user));
    }

    /**
     * 根据用户编号获取授权角色 "system:user_student:query"
     */
    @PreAuthorize(hasPermi = PerPrefix.SYSTEM_USER_STUDENT+ PerFun.QUERY)
    @GetMapping("/authRole/{userId}")
    public AjaxResult authRole(@PathVariable("userId") Long userId) {
        AjaxResult ajax = AjaxResult.success();
        SysUser user = sysStudentService.selectUserById(userId);
        List<SysRole> roles = roleService.selectRolesByUserId(userId);
        ajax.put("user", user);
        ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
        return ajax;
    }

    /**
     * 用户授权角色 "system:user_student:edit"
     */
    @PreAuthorize(hasPermi = PerPrefix.SYSTEM_USER_STUDENT+ PerFun.EDIT)
    @Log(title = "用户管理", businessType = BusinessType.GRANT)
    @PutMapping("/authRole")
    public AjaxResult insertAuthRole(Long userId, Long[] roleIds) {
        sysStudentService.insertUserAuth(userId, roleIds);
        return success();
    }

    /**
     * 获取所有可用户IDS
     *
     * @return 结果
     */
    @InnerAuth
    @GetMapping("/all")
    public AjaxResult userALLIDS() {
        Long userId = SecurityUtils.getUserId();
        SysUser user = new SysUser();
        user.setDelFlag(Constants.NORMAL);
        user.setStatus(Constants.NORMAL);
        List<SysUser> sysUsers = sysStudentService.selectUserList(user);
        List<Long> collect = sysUsers.stream().map(a -> a.getUserId()).collect(Collectors.toList());
        return AjaxResult.success(collect);

    }

    /**
     * 获取指定院系用户IDS
     *
     * @param deptId
     * @return 结果
     */
    @InnerAuth
    @GetMapping("/dept/{deptId}")
    public AjaxResult userDeptIDS(@PathVariable("deptId") Long deptId) {
        SysUser user = new SysUser();
        user.setDelFlag(Constants.NORMAL);
        user.setStatus(Constants.NORMAL);
        user.setDeptId(deptId);
        List<SysUser> sysUsers = sysStudentService.selectUserList(user);
        List<Long> collect = sysUsers.stream().map(a -> a.getUserId()).collect(Collectors.toList());
        return AjaxResult.success(collect);

    }
}
