package com.stdproject.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stdproject.common.OperationLog;
import com.stdproject.common.PageRequest;
import com.stdproject.common.Result;
import com.stdproject.entity.AppRole;
import com.stdproject.entity.AppRoleMenu;
import com.stdproject.entity.AppRoleUser;
import com.stdproject.service.IAppRoleMenuService;
import com.stdproject.service.IAppRoleService;
import com.stdproject.service.IAppRoleUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 应用-角色表 前端控制器
 * </p>
 *
 * @author StdProject
 * @since 2023-12-07
 */
@Tag(name = "角色管理", description = "角色添加、角色修改、角色删除、角色查询，角色权限分配等功能")
@RestController
@RequestMapping("/api/role")
public class AppRoleController {

    @Autowired
    private IAppRoleService appRoleService;
    
    @Autowired
    private IAppRoleMenuService appRoleMenuService;
    
    @Autowired
    private IAppRoleUserService appRoleUserService;

    @Operation(summary = "分页查询角色列表")
    @PostMapping("/page")
    @OperationLog(type = "06", module = "角色管理", description = "分页查询角色列表")
    public Result<IPage<AppRole>> page(@RequestBody @Valid PageRequest pageRequest) {
        Page<AppRole> page = new Page<>(pageRequest.getCurrent(), pageRequest.getSize());
        QueryWrapper<AppRole> queryWrapper = new QueryWrapper<>();
        
        // 关键字搜索
        if (StringUtils.hasText(pageRequest.getKeyword())) {
            queryWrapper.and(wrapper -> wrapper
                .like("rolename", pageRequest.getKeyword())
                .or().like("rolecode", pageRequest.getKeyword())
                .or().like("description", pageRequest.getKeyword())
            );
        }
        
        // 只查询有效的角色
        queryWrapper.eq("isvaild", "1");
        
        // 排序
        if (StringUtils.hasText(pageRequest.getOrderBy())) {
            if ("asc".equalsIgnoreCase(pageRequest.getOrderDirection())) {
                queryWrapper.orderByAsc(pageRequest.getOrderBy());
            } else {
                queryWrapper.orderByDesc(pageRequest.getOrderBy());
            }
        } else {
            queryWrapper.orderByAsc("rolecode");
        }
        
        IPage<AppRole> result = appRoleService.page(page, queryWrapper);
        return Result.success(result);
    }

    @Operation(summary = "查询所有有效角色列表")
    @GetMapping("/list")
    @OperationLog(type = "06", module = "角色管理", description = "查询所有有效角色列表")
    public Result<List<AppRole>> list() {
        QueryWrapper<AppRole> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("isvaild", "1");
        queryWrapper.orderByAsc("rolecode");
        
        List<AppRole> roles = appRoleService.list(queryWrapper);
        return Result.success(roles);
    }

    @Operation(summary = "根据ID查询角色详情")
    @GetMapping("/{id}")
    @OperationLog(type = "06", module = "角色管理", description = "查询角色详情")
    public Result<AppRole> getById(@Parameter(description = "角色ID") @PathVariable String id) {
        AppRole role = appRoleService.getById(id);
        return Result.success(role);
    }
    @Operation(summary = "新增角色")
    @PostMapping
    @OperationLog(type = "01", module = "角色管理", description = "新增角色")
    public Result<String> save(@RequestBody @Valid AppRole appRole) {
        // 检查角色名称是否已存在
        QueryWrapper<AppRole> nameQuery = new QueryWrapper<>();
        nameQuery.eq("rolename", appRole.getRolename());
        nameQuery.eq("isvaild", "1");
        AppRole existRoleName = appRoleService.getOne(nameQuery);
        if (ObjectUtils.isNotEmpty(existRoleName)) {
            return Result.error("角色名称已存在");
        }
        // 自动生成角色编号
        String maxRoleCode = getMaxRoleCode();
        String newRoleCode;
        if (maxRoleCode == null) {
            newRoleCode = "001";
        } else {
            int nextCode = Integer.parseInt(maxRoleCode) + 1;
            newRoleCode = String.format("%03d", nextCode);
        }
        appRole.setRolecode(newRoleCode);
        // 设置默认值
        appRole.setIsvaild("1");
        appRole.setLastmodifier("admin");
        appRole.setLastmodifydate(LocalDateTime.now());
        boolean success = appRoleService.save(appRole);
        return success ? Result.success("新增成功") : Result.error("新增失败");
    }

    /**
     * 获取最大的角色编号
     * @return 最大角色编号
     */
    private String getMaxRoleCode() {
        LambdaQueryWrapper<AppRole> queryWrapper = new LambdaQueryWrapper<AppRole>()
                .eq(AppRole::getIsvaild, "1")
                .orderByDesc(AppRole::getRolecode)
                .select(AppRole::getRolecode)
                .last("LIMIT 1");
        List<AppRole> list = appRoleService.list(queryWrapper);
        return list.isEmpty() ? null : list.get(0).getRolecode();
    }

    @Operation(summary = "修改角色")
    @PutMapping
    @OperationLog(type = "02", module = "角色管理", description = "修改角色")
    public Result<String> update(@RequestBody @Valid AppRole appRole) {
        // 检查角色是否存在
        AppRole existRole = appRoleService.getById(appRole.getId());
        if (existRole == null) {
            return Result.error("角色不存在");
        }
                
        // 如果修改了角色名称，检查新名称是否已被其他角色使用
        if (!existRole.getRolename().equals(appRole.getRolename())) {
            QueryWrapper<AppRole> nameQuery = new QueryWrapper<>();
            nameQuery.eq("rolename", appRole.getRolename());
            nameQuery.eq("isvaild", "1");
            nameQuery.ne("id", appRole.getId());
            AppRole roleWithSameName = appRoleService.getOne(nameQuery);
            if (roleWithSameName != null) {
                return Result.error("角色名称已被其他角色使用");
            }
        }
        appRole.setLastmodifier("admin");
        appRole.setLastmodifydate(LocalDateTime.now());
        boolean success = appRoleService.updateById(appRole);
        return success ? Result.success("修改成功") : Result.error("修改失败");
    }

    @Operation(summary = "删除角色")
    @DeleteMapping("/{id}")
    @OperationLog(type = "03", module = "角色管理", description = "删除角色")
    public Result<String> delete(@Parameter(description = "角色ID") @PathVariable String id) {
        // 检查是否有用户关联此角色
        QueryWrapper<AppRoleUser> userQuery = new QueryWrapper<>();
        userQuery.eq("roleid", id);
        long userCount = appRoleUserService.count(userQuery);
        if (userCount > 0) {
            return Result.error("存在用户关联此角色，无法删除");
        }
        
        // 软删除：设置为无效
        AppRole role = appRoleService.getById(id);
        if (role != null) {
            role.setIsvaild("0");
            role.setLastmodifydate(LocalDateTime.now());
            boolean success = appRoleService.updateById(role);
            
            if (success) {
                // 同时删除角色菜单关联
                QueryWrapper<AppRoleMenu> menuQuery = new QueryWrapper<>();
                menuQuery.eq("roleid", id);
                appRoleMenuService.remove(menuQuery);
            }
            
            return success ? Result.success("删除成功") : Result.error("删除失败");
        }
        
        return Result.error("角色不存在");
    }

    

    @Operation(summary = "根据角色类型查询角色列表")
    @GetMapping("/type/{type}")
    @OperationLog(type = "06", module = "角色管理", description = "根据角色类型查询角色列表")
    public Result<List<AppRole>> getByType(@Parameter(description = "角色类型：1-应用管理员，2-应用普通用户") @PathVariable String type) {
        QueryWrapper<AppRole> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("type", type);
        queryWrapper.eq("isvaild", "1");
        queryWrapper.orderByAsc("rolecode");        
        List<AppRole> roles = appRoleService.list(queryWrapper);
        return Result.success(roles);
    }

    @Operation(summary = "分配角色菜单权限")
    @PostMapping("/assign-menus/{roleId}")
    @OperationLog(type = "02", module = "角色管理", description = "分配角色菜单权限")
    public Result<String> assignMenus(
            @Parameter(description = "角色ID") @PathVariable String roleId,
            @RequestBody List<String> menuIds) {
        
        // 检查角色是否存在
        AppRole role = appRoleService.getById(roleId);
        if (role == null || !"1".equals(role.getIsvaild())) {
            return Result.error("角色不存在或已禁用");
        }
        
        // 先删除原有的菜单权限
        QueryWrapper<AppRoleMenu> deleteQuery = new QueryWrapper<>();
        deleteQuery.eq("roleid", roleId);
        appRoleMenuService.remove(deleteQuery);
        
        // 添加新的菜单权限
        if (menuIds != null && !menuIds.isEmpty()) {
            List<AppRoleMenu> roleMenus = menuIds.stream().map(menuId -> {
                AppRoleMenu roleMenu = new AppRoleMenu();
                roleMenu.setRoleid(roleId);
                roleMenu.setMenuid(menuId);
                roleMenu.setAppId(role.getAppId());
                return roleMenu;
            }).collect(Collectors.toList());
            
            boolean success = appRoleMenuService.saveBatch(roleMenus);
            return success ? Result.success("权限分配成功") : Result.error("权限分配失败");
        }
        
        return Result.success("权限分配成功");
    }

    @Operation(summary = "获取角色的菜单权限")
    @GetMapping("/menus/{roleId}")
    @OperationLog(type = "06", module = "角色管理", description = "获取角色的菜单权限")
    public Result<List<String>> getRoleMenus(@Parameter(description = "角色ID") @PathVariable String roleId) {
        QueryWrapper<AppRoleMenu> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("roleid", roleId);
        
        List<AppRoleMenu> roleMenus = appRoleMenuService.list(queryWrapper);
        List<String> menuIds = roleMenus.stream()
            .map(AppRoleMenu::getMenuid)
            .collect(Collectors.toList());
        
        return Result.success(menuIds);
    }

    @Operation(summary = "分配用户角色")
    @PostMapping("/assign-users/{roleId}")
    @OperationLog(type = "02", module = "角色管理", description = "分配用户角色")
    public Result<String> assignUsers(
            @Parameter(description = "角色ID") @PathVariable String roleId,
            @RequestBody List<String> userIds) {
        
        // 检查角色是否存在
        AppRole role = appRoleService.getById(roleId);
        if (role == null || !"1".equals(role.getIsvaild())) {
            return Result.error("角色不存在或已禁用");
        }
        
        // 先删除原有的用户角色关联
        QueryWrapper<AppRoleUser> deleteQuery = new QueryWrapper<>();
        deleteQuery.eq("roleid", roleId);
        appRoleUserService.remove(deleteQuery);
        
        // 添加新的用户角色关联
        if (userIds != null && !userIds.isEmpty()) {
            List<AppRoleUser> roleUsers = userIds.stream().map(userId -> {
                AppRoleUser roleUser = new AppRoleUser();
                roleUser.setRoleid(roleId);
                roleUser.setUserid(userId);
                roleUser.setAppId(role.getAppId());
                return roleUser;
            }).collect(Collectors.toList());
            
            boolean success = appRoleUserService.saveBatch(roleUsers);
            return success ? Result.success("用户分配成功") : Result.error("用户分配失败");
        }
        
        return Result.success("用户分配成功");
    }

    @Operation(summary = "获取角色的用户列表")
    @GetMapping("/users/{roleId}")
    @OperationLog(type = "06", module = "角色管理", description = "获取角色的用户列表")
    public Result<List<String>> getRoleUsers(@Parameter(description = "角色ID") @PathVariable String roleId) {
        QueryWrapper<AppRoleUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("roleid", roleId);
        
        List<AppRoleUser> roleUsers = appRoleUserService.list(queryWrapper);
        List<String> userIds = roleUsers.stream()
            .map(AppRoleUser::getUserid)
            .collect(Collectors.toList());
        
        return Result.success(userIds);
    }
}