package com.zsc.edu.gateway.modules.system.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sun.source.tree.Tree;
import com.zsc.edu.gateway.framework.mybatisplus.DataPermission;
import com.zsc.edu.gateway.framework.security.UserDetailsImpl;
import com.zsc.edu.gateway.modules.operationLog.entity.OperationLogAnnotation;
import com.zsc.edu.gateway.modules.system.dto.UserCreateDto;
import com.zsc.edu.gateway.modules.system.dto.UserSelfUpdateDto;
import com.zsc.edu.gateway.modules.system.dto.UserSelfUpdatePasswordDto;
import com.zsc.edu.gateway.modules.system.dto.UserUpdateDto;
import com.zsc.edu.gateway.modules.system.entity.*;
import com.zsc.edu.gateway.modules.system.query.UserQuery;
import com.zsc.edu.gateway.modules.system.service.*;
import com.zsc.edu.gateway.modules.system.utils.TreeUtil;
import com.zsc.edu.gateway.modules.system.vo.MenuVo;
import com.zsc.edu.gateway.modules.system.vo.UserDetail;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户Controller
 *
 * @author harry yao
 */
@AllArgsConstructor
@RestController
@RequestMapping("api/rest/user")
public class UserController {

    private final UserService service;

    private final RoleService roleService;
    private final DeptService deptService;
    private final AuthorityService authorityService;
    private final MenuService menuService;

    /**
     * 登录前，获取csrfToken信息
     * 登录成功后，获取principal和csrfToken信息
     *
     * @param principal 认证主体
     * @param csrfToken csrf令牌
     * @return 包含csrf令牌和登录用户的认证主体信息
     */
    @RequestMapping(value = "me", method = {RequestMethod.POST, RequestMethod.GET})
    public Map<String, Object> me(@AuthenticationPrincipal Object principal, CsrfToken csrfToken) {
        Map<String, Object> map = new LinkedHashMap<>();
        map.put("user", principal);
        map.put("csrf", csrfToken);
        return map;
    }

    /**
     * 切换角色
     */
    @OperationLogAnnotation(operationType = "更新角色")
    @PatchMapping("/switch/{roleId}")
    public UserDetailsImpl switchRole(@PathVariable Long roleId) {
        return service.switchRole(roleId);
    }

    /**
     * 用户获取自己的信息
     *
     * @param userDetails 操作用户
     * @return 用户信息
     */
    @GetMapping("self")
    public UserDetail selfDetail(@AuthenticationPrincipal UserDetailsImpl userDetails) {
        UserDetail userDetail = new UserDetail();
        User user = service.selfDetail(userDetails);
        user.dept = deptService.getById(user.deptId);
        Role role= roleService.getOne(new QueryWrapper<Role>().eq("id",user.roleId));
        userDetail.setPermissions(role.getName());
        Set<Authority> authorities = authorityService.selectAuthoritiesByRoleId(role.getId());
        userDetail.setAuthorities(authorities.stream().toList());
        userDetail.setUser(user);
        return userDetail;
    }

    /**
     * 用户更新自己的信息
     *
     * @param userDetails 操作用户
     * @param dto         表单数据
     * @return 更新后的用户信息
     */
    @OperationLogAnnotation(content = "信息", operationType = "更新")
    @PatchMapping("self")
    public Boolean selfUpdate(
            @AuthenticationPrincipal UserDetailsImpl userDetails,
            @RequestBody UserSelfUpdateDto dto
    ) {
        return service.selfUpdate(userDetails, dto);
    }

    /**
     * 用户更新自己的密码
     *
     * @param userDetails 操作用户
     * @param dto         表单数据
     */

    @OperationLogAnnotation(content = "'密码'", operationType = "更新")
    @PatchMapping("self/update-password")
    public Boolean selfUpdatePassword(
            @AuthenticationPrincipal UserDetailsImpl userDetails,
            @RequestBody UserSelfUpdatePasswordDto dto
    ) {
        return service.selfUpdatePassword(userDetails, dto);
    }

    /**
     * 分页查询用户信息 hasAuthority('SYSTEM:USER:QUERY')
     *
     * @param query    查询表单
     * @param page 分页
     * @return 分页用户信息
     */
    @GetMapping()
    @PreAuthorize("hasAuthority('system:user:query')")
    public Page<User> query(Long deptId, UserQuery query, Page<User> page) {
        if (deptId != null) {
            List<Dept> deptList = TreeUtil.flat(deptService.listTree(deptId), Dept::getChildren, d -> d.setChildren(null));
            List<Long> deptIds = deptList.stream().map(Dept::getId).collect(Collectors.toList());
            query.setDeptIds(deptIds);
        }
        return service.page(page, query.wrapper());
    }



    /**
     * 新建用户 hasAuthority('SYSTEM:USER:CREATE')
     *
     * @param dto 表单数据
     * @return 新建的用户信息
     */

    @OperationLogAnnotation(operationType = "新建")
    @PostMapping
    @PreAuthorize("hasAuthority('system:user:create')")
    public Boolean create(@RequestBody UserCreateDto dto) {
        return service.create(dto);
    }

    /**
     * 更新用户 hasAuthority('SYSTEM:USER:UPDATE')
     *
     * @param dto 表单数据
     * @param id  ID
     * @return 更新后的用户
     */
    @OperationLogAnnotation(operationType = "更新")
    @PatchMapping("{id}")
    @PreAuthorize("hasAuthority('system:user:update')")
    public Boolean update(@RequestBody UserUpdateDto dto, @PathVariable("id") Long id) {
        return service.update(dto, id);
    }

    /**
     * 更新用户密码 hasAuthority('SYSTEM:USER:UPDATE')
     *
     * @param id       ID
     * @param password 新密码
     */
    @OperationLogAnnotation(content = "'密码'", operationType = "更新")
    @PatchMapping("{id}/update-password")
    @PreAuthorize("hasAuthority('system:user:update')")
    public Boolean updatePassword(@PathVariable("id") Long id, @RequestParam String password) {
        return service.updatePassword(password, id);
    }

    /**
     * 切换用户"启动/禁用"状态 hasAuthority('SYSTEM:USER:DELETE')
     *
     * @param id ID
     * @return Dept 更新后的用户
     */
    @PatchMapping("{id}/toggle")
    @PreAuthorize("hasAuthority('system:user:delete')")
    public Boolean toggle(@PathVariable("id") Long id) {
        return service.toggle(id);
    }
    /**
     * 删除用户 hasAuthority('SYSTEM:USER:DELETE')
     * */
    @OperationLogAnnotation(operationType = "删除")
    @DeleteMapping("{id}")
    @PreAuthorize("hasAuthority('system:user:delete')")
    public Boolean delete(@PathVariable("id") Long id) {
        return service.removeById(id);
    }
    /**
     * 根据部门ID查询用户
     * */
    @GetMapping("dept/{id}")
    public Collection<User> listByDept(@PathVariable("id") Long id) {
        return service.list(new LambdaQueryWrapper<User>().eq(User::getDeptId, id));
    }

    /**
     * 根据ID查询用户
     * */
    @GetMapping("{id}")
    public User detail(@PathVariable("id") Long id) {
        return service.getById(id);
    }

    /**
     * 发送邮件
     * */
    @GetMapping("send-email")
    public String sendEmail(@RequestParam String email) {
        return service.sendEmail(email);
    }

}

