package com.backendsys.modules.system.controller;

import cn.hutool.core.util.ObjectUtil;
import com.backendsys.exception.CustException;
import com.backendsys.modules.common.aspect.SysLog;
import com.backendsys.modules.common.config.security.enums.SecurityEnum;
import com.backendsys.modules.common.config.security.utils.SecurityUtil;
import com.backendsys.modules.common.utils.Result;
import com.backendsys.modules.system.entity.SysUserDTO;
import com.backendsys.modules.system.entity.SysUserRoleRelation;
import com.backendsys.modules.system.service.SysUserService;
import com.backendsys.utils.response.PageEntity;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@Validated
@RestController
@Tag(name = "系统用户")
public class SysUserController {

    /**
     * TODO 1.手机号码字段，需要经过验证码校验，不能用 updateUserInfo 改 (待修改)
     * TODO 2.审核用户，需要单独的表做审核记录，不能直接改字段
     */

    @Autowired
    private SecurityUtil securityUtil;

    @Autowired
    private SysUserService sysUserService;

    @Operation(summary = "获取系统用户列表")
    @PreAuthorize("@sr.hasPermission('3.2')")
    @GetMapping("/api/system/user/getUserList")
    public Result getUserList(SysUserDTO sysUserDTO) {
        return Result.success().put("data", sysUserService.selectUserList(sysUserDTO));
    }

    @Operation(summary = "获取系统用户列表 (在线的)")
    @PreAuthorize("@sr.hasPermission('3.1')")
    @GetMapping("/api/system/user/getUserOnlineList")
    public Result getUserOnlineList(SysUserDTO sysUserDTO) {
        return Result.success().put("data", sysUserService.selectUserOnlineList(sysUserDTO));
    }

    /**
     * 权限：
     * - 查询用户信息 (3.2.1)
     * - 查询他人用户信息 (3.2.1.2)
     */
    @Operation(summary = "获取系统用户详情")
    @PreAuthorize("@sr.hasPermission('3.2.1')")
    @GetMapping("/api/system/user/getUserDetail")
    public Result getUserDetail(@Parameter(description = "用户ID") Long user_id) {

        // 查询自身的用户信息 (不传参数)
        user_id = (user_id == null) ? SecurityUtil.getUserId() : user_id;

        // 查询他人的用户信息
        // - 查询自己 (无需权限)
        // - 查询他人 (需要权限或超级管理员)
        if (user_id != SecurityUtil.getUserId() && !securityUtil.hasPermission("3.2.1.2")) {
            throw new CustException(SecurityEnum.NOAUTH);
        }

        return Result.success().put("data", sysUserService.selectUserInfoSimple(user_id));
    }

    @SysLog("创建系统用户")
    @Operation(summary = "创建系统用户")
    @PreAuthorize("@sr.hasPermission('3.2.2')")
    @PostMapping("/api/system/user/createUser")
    public Result createUser(@Validated(SysUserDTO.Create.class) @RequestBody SysUserDTO sysUserDTO) {
        return Result.success().put("data", sysUserService.insertUser(sysUserDTO));
    }

    /**
     * 权限：
     * - 编辑用户信息权限 (3.2.3)
     * - 编辑他人用户信息权限 (3.2.3.2)
     */
    @SysLog("编辑系统用户信息")
    @Operation(summary = "编辑系统用户信息")
    @PreAuthorize("@sr.hasPermission('3.2.3')")
    @PutMapping("/api/system/user/updateUserInfo")
    public Result updateUserInfo(@Validated(SysUserDTO.Update.class) @RequestBody SysUserDTO sysUserDTO) {

        // - 不传 user_id 时，修改目标为 当前用户
        Long user_id = sysUserDTO.getUser_id();
        if (ObjectUtil.isEmpty(user_id)) {
            user_id = SecurityUtil.getUserId();
            sysUserDTO.setUser_id(user_id);
        } else if (SecurityUtil.getUserId() != 1L && user_id == 1L) {
            throw new CustException("不能编辑超管账号");
        }
        // 编辑他人的用户信息
        // - 编辑自己 (无需权限)
        // - 编辑他人 (需要子权限或超级管理员)
        if (user_id != SecurityUtil.getUserId() && !securityUtil.hasPermission("3.2.3.2")) {
            throw new CustException(SecurityEnum.NOAUTH);
        }
        // 防止手动更新字段
        sysUserDTO.setLast_login_time(null);
        sysUserDTO.setLast_login_ip(null);

        return Result.success().put("data", sysUserService.updateUserInfo(sysUserDTO));
    }

    @SysLog("编辑系统用户角色绑定")
    @Operation(summary = "编辑系统用户角色绑定")
    @PreAuthorize("@sr.hasPermission('3.2.3.5')")
    @PutMapping("/api/system/user/updateUserRoleInfo")
    public Result updateUserRoleInfo(@Validated(SysUserRoleRelation.Update.class) @RequestBody SysUserRoleRelation sysUserRoleRelation) {

        // - 不传 user_id 时，修改目标为 当前用户
        Long user_id = sysUserRoleRelation.getUser_id();
        if (ObjectUtil.isEmpty(user_id)) {
            user_id = SecurityUtil.getUserId();
            sysUserRoleRelation.setUser_id(user_id);
        } else if (!SecurityUtil.getUserId().equals(1L) && user_id.equals(1L)) {
            throw new CustException("不能编辑超管账号");
        }

        return Result.success().put("data", sysUserService.updateUserRoleRelation(sysUserRoleRelation));
    }

    @SysLog("编辑系统用户密码")
    @Operation(summary = "编辑系统用户密码")
    @PreAuthorize("@sr.hasPermission('3.2.3.3')")
    @PutMapping("/api/system/user/updateUserPassword")
    public Result updateUserPassword(@Validated(SysUserDTO.UpdatePassword.class) @RequestBody SysUserDTO sysUserDTO) {

        // - 不传 user_id 时，修改目标为 当前用户
        Long user_id = sysUserDTO.getUser_id();
        if (ObjectUtil.isEmpty(user_id)) {
            user_id = SecurityUtil.getUserId();
            sysUserDTO.setUser_id(user_id);
        } else if (!SecurityUtil.getUserId().equals(1L) && user_id.equals(1L)) {
            throw new CustException("不能编辑超管账号");
        }
        // 编辑他人的用户信息
        // - 编辑自己 (无需权限)
        // - 编辑他人 (需要子权限或超级管理员)
        if (user_id != SecurityUtil.getUserId() && !securityUtil.hasPermission("3.2.3.2")) {
            throw new CustException(SecurityEnum.NOAUTH);
        }

        return Result.success().put("data", sysUserService.updateUserPassword(sysUserDTO));
    }

    @SysLog("重置系统用户密码")
    @Operation(summary = "重置系统用户密码")
    @PreAuthorize("@sr.hasPermission('3.2.3.4')")
    @PutMapping("/api/system/user/resetUserPassword")
    public Result resetUserPassword(@Validated(SysUserDTO.ResetPassword.class) @RequestBody SysUserDTO sysUserDTO) {

        // 判断不可为超级管理员(首位)
        Long user_id = sysUserDTO.getUser_id();
        if (user_id != null && user_id == 1L) throw new CustException("不能重置超管账号密码");

        // 判断是否为自身重置，自身密码不能重置，只能修改
        Long self_user_id = SecurityUtil.getUserId();
        Long request_user_id = sysUserDTO.getUser_id();
        if (request_user_id != null && self_user_id == request_user_id) {
            throw new CustException("不能重置自身密码，请自行修改密码");
        }

        return Result.success().put("data", sysUserService.resetUserPassword(sysUserDTO));
    }

    @SysLog("删除系统用户")
    @Operation(summary = "删除系统用户")
    @PreAuthorize("@sr.hasPermission('3.2.4')")
    @DeleteMapping("/api/system/user/deleteUser")
    public Result deleteUser(@Validated(SysUserDTO.Delete.class) @RequestBody SysUserDTO sysUserDTO) {

        Long user_id = sysUserDTO.getUser_id();
        List<Long> user_ids = sysUserDTO.getUser_ids();
        if (user_id == null && (user_ids == null || user_ids.size() == 0)) throw new CustException("user_id 或 user_ids 必填");
        if (user_id != null && user_id == 1L) throw new CustException("不能删除超管账号");
        if (user_ids != null && user_ids.contains(SecurityUtil.getUserId()) && user_id != SecurityUtil.getUserId()) throw new CustException("不能删除自己的账号");
        if (user_ids != null && user_ids.contains(1L) && user_id != 1L) throw new CustException("不能删除超管账号");

        return Result.success().put("data", sysUserService.deleteUser(sysUserDTO));
    }

    @SysLog("审核用户")
    @Operation(summary = "审核用户")
    @PreAuthorize("@sr.hasPermission('3.2.6')")
    @PutMapping("/api/system/user/auditUser")
    public Result auditUser(@Validated(SysUserDTO.Audit.class) @RequestBody SysUserDTO sysUserDTO) {

        Long user_id = sysUserDTO.getUser_id();
        if (user_id != null && user_id == 1L) throw new CustException("不能审核超管账号");
        if (user_id != null && user_id == SecurityUtil.getUserId()) throw new CustException("不能审核自己的账号");

        return Result.success().put("data", sysUserService.auditUser(sysUserDTO));
    }

    @SysLog("踢出系统用户")
    @Operation(summary = "踢出系统用户")
    @PreAuthorize("@sr.hasPermission('3.2.7')")
    @PostMapping("/api/system/user/kickUser")
    public Result kickUser(@Validated(SysUserDTO.Kick.class) @RequestBody SysUserDTO sysUserDTO) {

        Long user_id = sysUserDTO.getUser_id();
        if (user_id != null && user_id == 1L) throw new CustException("不能踢出超管账号");
        if (user_id != null && user_id == SecurityUtil.getUserId()) throw new CustException("不能踢出自己的账号");

        return Result.success().put("data", sysUserService.kickUser(user_id));
    }




    /**
     * 权限：
     * - 查询用户权限 (3.4.1)
     * - 查询他人用户权限 (3.4.1.2)
     */
    @Operation(summary = "获取系统用户权限")
    @PreAuthorize("@sr.hasPermission('3.4.1')")
    @GetMapping("/api/system/user/getUserPermission")
    public Result getUserPermission(@Parameter(description = "用户ID") Long user_id) {

        // 查询自身的用户信息 (不传参数)
        user_id = (user_id == null) ? SecurityUtil.getUserId() : user_id;
        // 查询他人的用户信息
        // - 查询自己 (无需权限)
        // - 查询他人 (需要子权限或超级管理员)
        if (!user_id.equals(SecurityUtil.getUserId()) && !securityUtil.hasPermission("3.4.1.2")) {
            throw new CustException(SecurityEnum.NOAUTH);
        }

        return Result.success().put("data", sysUserService.selectUserPermission(user_id));
    }

    /**
     * 权限：
     * - 查询用户菜单 (3.5.1)
     * - 查询他人用户菜单 (3.5.1.2)
     */
    @Operation(summary = "获取系统用户菜单")
    @PreAuthorize("@sr.hasPermission('3.5.1')")
    @GetMapping("/api/system/user/getUserMenu")
    public Result getUserMenu(@Parameter(description = "用户ID") Long user_id) {

        // 查询自身的用户信息 (不传参数)
        user_id = (user_id == null) ? SecurityUtil.getUserId() : user_id;
        // 查询他人的用户信息
        // - 查询自己 (无需权限)
        // - 查询他人 (需要子权限或超级管理员)
        if (!user_id.equals(SecurityUtil.getUserId()) && !securityUtil.hasPermission("3.4.1.2")) {
            throw new CustException(SecurityEnum.NOAUTH);
        }

        return Result.success().put("data", sysUserService.selectUserMenu(user_id));
    }

}
