/*
 * Copyright (c) 2023 codvision.com All Rights Reserved.
 */

package com.codvision.auth.controller.manager;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.codvision.auth.entity.SysUser;
import com.codvision.auth.entity.dto.SysUserDTO;
import com.codvision.auth.entity.dto.SysUserQueryDTO;
import com.codvision.auth.entity.excel.SysUserExcel;
import com.codvision.auth.entity.vo.SysUserVO;
import com.codvision.auth.service.IDingUserService;
import com.codvision.auth.service.ISysUserService;
import com.codvision.auth.support.AuthConst;
import com.codvision.auth.support.CacheContants;
import com.codvision.auth.support.UserContext;
import com.codvision.authcore.annotation.RequiresPermissions;
import com.codvision.base.support.EasyExcelUtil;
import com.codvision.commoncore.common.ResponseEntity;
import com.codvision.commoncore.exception.BusinessException;
import com.codvision.webcore.annotation.ApiSecret;
import com.codvision.webcore.bean.QueryPage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 系统用户 管理模块
 *
 * @author lingee
 * @date 2023-11-09
 */
@Slf4j
@RestController
@RequestMapping("/v1/manager/sysUser")
@Api(tags = "平台管理端-系统用户管理模块")
public class ManagerSysUserController {

    @Resource
    private ISysUserService sysUserService;

    @Resource
    private IDingUserService dingUserService;

    @Lazy
    @Resource
    private RedissonClient redissonClient;

    @ApiOperation(value = "获取系统用户详情", notes = "获取系统用户详情接口")
    @PostMapping("/detail")
    @RequiresPermissions("sys_user_detail")
    public ResponseEntity<SysUserVO> getByUid(@ApiParam(value = "系统用户ID", required = true) @RequestParam(value = "uid") Integer uid) {
        SysUserVO vo = sysUserService.getDetailByUid(uid);
        return new ResponseEntity<SysUserVO>().ok().data(vo);
    }

    @PostMapping("/detailByName")
    @ApiOperation(value = "根据用户名获取用户详情", notes = "根据用户名获取用户详情接口")
    @RequiresPermissions("sys_user_detail_name")
    public ResponseEntity<SysUserVO> getDetailByUid(@ApiParam(value = "用户名", required = true) @RequestParam(value = "loginName") String loginName) {
        ResponseEntity<SysUserVO> responseEntity = new ResponseEntity<>();

        return responseEntity.data(sysUserService.getDetailByLoginName(loginName));
    }

    @ApiOperation(value = "获取系统用户分页列表", notes = "获取系统用户分页列表接口")
    @PostMapping("/findAll")
    @RequiresPermissions("sys_user_list")
    public ResponseEntity<IPage<SysUserVO>> findAll(@ApiParam(value = "关键字") @RequestParam(required = false) String keyword,
                                                    @ApiParam(value = "组织id") @RequestParam(required = false) Integer oid,
                                                    @ApiParam(value = "角色id") @RequestParam(required = false) Integer roleId,
                                                    @RequestParam(value = "page", required = false, defaultValue = "1") int page,
                                                    @RequestParam(value = "size", required = false, defaultValue = "10") int size,
                                                    @ApiParam(value = "是否绑定zzdId：0否，1是") @RequestParam(value = "flagBindZzd", required = false) Integer flagBindZzd,
                                                    @ApiParam(value = "应用code") @RequestParam(value = "appCode", required = false) String appCode,
                                                    @ApiParam(value = "是否禁用flagForbidden：0否，1是") @RequestParam(value = "flagForbidden", required = false, defaultValue = "-1") Integer flagForbidden) {
        QueryPage<SysUser> queryPage = new QueryPage<>(page, size);

        SysUserQueryDTO queryDTO = new SysUserQueryDTO(keyword, oid, roleId, flagBindZzd, appCode, flagForbidden);

        IPage<SysUserVO> pageResult = sysUserService.findAll(queryPage, queryDTO);
        return new ResponseEntity<IPage<SysUserVO>>().ok().data(pageResult);
    }

    @ApiOperation(value = "新增系统用户", notes = "新增系统用户接口")
    @PostMapping("/add")
    @RequiresPermissions("sys_user_add")
    public ResponseEntity<String> addSysUser(@Valid @RequestBody SysUserDTO sysUserDTO) {
        Integer userId = sysUserService.addSysUser(sysUserDTO);
        return new ResponseEntity<String>().ok().data(String.valueOf(userId)).message("添加成功");
    }

    @ApiOperation(value = "删除系统用户", notes = "删除系统用户接口")
    @PostMapping("/del")
    @RequiresPermissions("sys_user_del")
    public ResponseEntity<String> del(@ApiParam(value = "系统用户ID", required = true) @RequestBody List<Integer> userIds) {
        if (CollectionUtils.isEmpty(userIds)) {
            throw new BusinessException(30002);
        }
        SysUser updateBean = new SysUser();
        updateBean.setDelFlag(AuthConst.DEFAULT_ROLE_FLAG);
        sysUserService.update(Wrappers.<SysUser>lambdaUpdate().setSql("del_flag = 1, del_key = id").in(SysUser::getId, userIds));
        return new ResponseEntity<String>().ok().message("删除成功");
    }

    @ApiOperation(value = "更新系统用户", notes = "更新系统用户接口")
    @PostMapping("/update")
    @RequiresPermissions("sys_user_edit")
    public ResponseEntity<String> update(@RequestBody SysUserDTO sysUserDTO) {
        sysUserService.updateUser(sysUserDTO);
        return new ResponseEntity<String>().ok().message("更新成功");
    }

    @ApiOperation(value = "根据用户id列表获取用户列表", notes = "根据用户id列表获取用户列表接口")
    @PostMapping("/getByUidList")
    public ResponseEntity<List<SysUserVO>> getByUidList(@RequestBody List<Integer> uidList) {
        return new ResponseEntity<List<SysUserVO>>().ok().data(sysUserService.getListByIds(uidList));
    }

    @ApiSecret(ignore = true)
    @ApiOperation(value = "下载用户导入模板", notes = "下载用户导入模板接口")
    @GetMapping("/downloadTemplate")
    public void downloadTemplate(HttpServletResponse response) {
        EasyExcelUtil.downloadTemplate("用户模板表", "用户", SysUserExcel.class, response);
    }

    @ApiSecret(ignore = true)
    @ApiOperation(value = "用户导入", notes = "用户导入接口")
    @PostMapping("/import")
    public ResponseEntity<String> excelImport(@RequestPart("file") MultipartFile file) {
        return new ResponseEntity<String>().ok().data(sysUserService.excelImport(file));
    }

    @ApiSecret(ignore = true)
    @ApiOperation(value = "用户导出", notes = "用户导出接口")
    @GetMapping("/export")
    public ResponseEntity<String> excelExport(@RequestParam(required = false) String keyword,
                                              @RequestParam(required = false) Integer oid,
                                              @RequestParam(required = false) Integer roleId) {
        SysUserQueryDTO queryDTO = new SysUserQueryDTO();
        queryDTO.setKeyword(keyword);

        if (ObjectUtil.isNotEmpty(oid)) {
            queryDTO.setOid(oid);
        } else {
            SysUserVO user = UserContext.get();
            queryDTO.setOid(user.getActiveOid());
        }
        queryDTO.setRoleId(roleId);

        sysUserService.excelExport(queryDTO);
        return new ResponseEntity<String>().ok();
    }

    @ApiSecret(ignore = true)
    @ApiOperation(value = "同步钉钉组织用户", notes = "同步钉钉组织用户接口")
    @PostMapping("/syncDing")
    public ResponseEntity<String> syncDing(@ApiParam(value = "用户绑定默认角色编码", required = true) @RequestParam String roleCode) {
        RLock lock = redissonClient.getLock(CacheContants.SYNC_DING_LOCK);
        if (lock.isLocked()) {
            throw new BusinessException("同步中，请稍后重试");
        }
        try {
            // 等待10秒获取锁，持有锁30秒
            if (lock.tryLock(10, 30, TimeUnit.SECONDS)) {
                dingUserService.syncDepartment();
                dingUserService.syncUser(roleCode);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new BusinessException(e.getMessage());
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
        return new ResponseEntity<String>().ok().message("同步成功");
    }
}
