package cn.reghao.bnt.web.admin.controller;

import cn.reghao.bnt.web.admin.model.dto.AccountPassword;
import cn.reghao.bnt.web.admin.model.dto.AccountRole;
import cn.reghao.bnt.web.admin.model.dto.CreateAccountDto;
import cn.reghao.bnt.web.admin.model.po.Role;
import cn.reghao.bnt.web.admin.model.vo.RoleVO;
import cn.reghao.bnt.web.admin.model.vo.UserSession;
import cn.reghao.bnt.web.admin.model.vo.UserVO;
import cn.reghao.bnt.web.admin.service.AccountService;
import cn.reghao.bnt.web.admin.service.AccountSessionService;
import cn.reghao.bnt.web.admin.model.po.User;
import cn.reghao.bnt.web.admin.service.RoleService;
import cn.reghao.jutil.jdk.web.db.PageList;
import cn.reghao.jutil.jdk.web.result.Result;
import cn.reghao.jutil.jdk.web.result.ResultStatus;
import cn.reghao.jutil.web.WebResult;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

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

/**
 * @author reghao
 * @date 2021-04-04 21:24:18
 */
@Tag(name = "帐号管理页面")
@RequestMapping("/api/devops/rbac/user")
@RestController
public class UserController {
    private final AccountService accountService;
    private final RoleService roleService;
    private final AccountSessionService accountSessionService;
    private int pageSize = 10;

    public UserController(AccountService accountService, RoleService roleService,
                          AccountSessionService accountSessionService) {
        this.accountService = accountService;
        this.roleService = roleService;
        this.accountSessionService = accountSessionService;
    }

    @Operation(summary = "帐号列表页面", description = "N")
    @GetMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE)
    public String userPage() {
        PageRequest pageRequest = PageRequest.of(0, pageSize);
        Page<UserVO> page = accountService.getUserVOByPage(pageRequest);
        page.getContent().forEach(userVO -> {
            int userId = userVO.getUserId();
            List<UserSession> userSessionList = accountSessionService.getUserSession(userId);
            if (!userSessionList.isEmpty()) {
                UserSession userSession = userSessionList.get(0);
                userVO.setLastAccess(userSession.getLastRequestAt());
                userVO.setSessionCount(userSessionList.size());
            }
        });

        PageList<UserVO> pageList = getPageList(page);
        return WebResult.success(pageList);
    }

    private PageList<UserVO> getPageList(Page<UserVO> page) {
        int pageNumber = page.getNumber() + 1;
        int pageSize = page.getSize();
        long total = page.getTotalElements();
        List<UserVO> list = page.getContent();
        return PageList.pageList(pageNumber, pageSize, (int) total, list);
    }

    @Operation(summary = "用户会话列表页面", description = "N")
    @GetMapping("/session")
    public String userSessionPage(@RequestParam("id") Integer userId) {
        User user = accountService.getById(userId);
        List<UserSession> userSessionList = accountSessionService.getUserSession(userId);
        return WebResult.success(userSessionList);
    }

    @Operation(summary = "帐号角色分配页面", description = "N")
    @GetMapping("/role")
    public String updateRolePage(@RequestParam("userId") Integer userId) {
        List<String> allRoles = roleService.getAllRoles().stream()
                .map(RoleVO::getName)
                .collect(Collectors.toList());
        List<String> userRoles = roleService.getRolesByUser(userId).stream()
                .map(role -> role.getName().replace("ROLE_", "").toLowerCase(Locale.ROOT))
                .collect(Collectors.toList());
        Map<String, Object> map = new HashMap<>();
        map.put("allRoles", allRoles);
        map.put("userRoles", userRoles);
        return WebResult.success(map);
    }

    @Operation(summary = "修改帐号角色", description = "N")
    @PostMapping(value = "/role", produces = MediaType.APPLICATION_JSON_VALUE)
    public String updateRole(@Validated AccountRole accountRole) {
        Result result = accountService.updateAccountRole(accountRole);
        if (result.getCode() == ResultStatus.SUCCESS.getCode()) {
            // 登出当前会话
            accountSessionService.deactivateUserSession(accountRole.getUserId());
        }
        return WebResult.result(result);
    }

    @Operation(summary = "修改帐号密码", description = "N")
    @PostMapping(value = "/passwd", produces = MediaType.APPLICATION_JSON_VALUE)
    public String updatePassword(@Validated AccountPassword accountPassword) {
        int userId = accountPassword.getUserId();
        String password = accountPassword.getPassword();
        accountService.updateAccountPassword(userId, password);
        // 登出当前会话
        accountSessionService.deactivateUserSession(userId);
        return WebResult.success();
    }

    @Operation(summary = "新增帐号页面", description = "N")
    @GetMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE)
    public String addUserPage() {
        List<String> allRoles = roleService.getAllRoles().stream().map(RoleVO::getName).collect(Collectors.toList());
        return WebResult.success(allRoles);
    }

    @Operation(summary = "创建帐号", description = "N")
    @PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE)
    public String createUser(@Validated CreateAccountDto createAccountDto) {
        Result result = accountService.createAccount(createAccountDto);
        return WebResult.result(result);
    }

    @Operation(summary = "删除帐号", description = "N")
    @PostMapping(value = "/delete", produces = MediaType.APPLICATION_JSON_VALUE)
    public String deleteAccount(Integer userId) {
        Result result = accountService.deleteAccount(userId);
        if (result.getCode() == ResultStatus.SUCCESS.getCode()) {
            // 登出当前会话
            accountSessionService.deactivateUserSession(userId);
        }
        return WebResult.result(result);
    }
}
