package com.seezoon.admin.modules.sys.controller;

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

import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.CaseUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

import com.seezoon.admin.modules.sys.dto.UserAo;
import com.seezoon.admin.modules.sys.dto.UserInfo;
import com.seezoon.admin.modules.sys.dto.UserResourcesVo;
import com.seezoon.admin.modules.sys.dto.vue.RouteMeta;
import com.seezoon.admin.modules.sys.dto.vue.VueRouteMenu;
import com.seezoon.admin.modules.sys.security.SecurityUtils;
import com.seezoon.admin.modules.sys.security.UserService;
import com.seezoon.dao.modules.sys.entity.SysMenu;
import com.seezoon.framework.api.Result;
import com.seezoon.framework.utils.TreeHelper;
import com.seezoon.framework.web.BaseController;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;

@Api(tags = "个人用户信息")
@RestController
@RequestMapping("/sys/user")
@RequiredArgsConstructor
public class UserController extends BaseController {

    private final UserService userService;

    @ApiOperation(value = "获取用户信息")
    @GetMapping("/info")
    public Result<UserInfo> getUserInfo() {
        UserInfo user = userService.userInfo(SecurityUtils.getUserId());
        return Result.ok(user);
    }

    @ApiOperation(value = "获取用户信息")
    @PostMapping("/save_user_info")
    public Result saveUserInfo(@Valid @RequestBody UserAo userAo) {
        userService.saveUserInfo(SecurityUtils.getUserId(), userAo);
        return Result.SUCCESS;
    }

    @ApiOperation(value = "更新密码")
    @PostMapping("/update_password")
    public Result updatePassword(@RequestParam @NotEmpty @Size(min = 6, max = 50) String oldPassword,
        @RequestParam @NotEmpty @Size(min = 6, max = 50) String newPassword) {
        boolean result = userService.updatePassword(SecurityUtils.getUserId(), oldPassword, newPassword);
        if (!result) {
            return Result.error("原密码错误");
        }
        return Result.SUCCESS;
    }

    @ApiOperation(value = "获取资源")
    @GetMapping("/get_resources")
    public Result<UserResourcesVo> getResources() {
        UserInfo user = SecurityUtils.getUser();
        // 角色
        Set<String> roles =
            userService.findRolesByUserId(user.getUserId()).stream().map(v -> v.getCode()).collect(Collectors.toSet());

        List<SysMenu> menus = userService.findMenusByUserId(user.getUserId());
        // 权限
        Set<String> permissions = menus.stream().filter(v -> StringUtils.isNotBlank(v.getPermission()))
            .map(v -> StringUtils.trim(v.getPermission())).collect(Collectors.toSet());

        UserResourcesVo userResourcesVo = new UserResourcesVo(roles, permissions, this.getRoutes(menus));

        return Result.ok(userResourcesVo);
    }

    private List<VueRouteMenu> getRoutes(List<SysMenu> menus) {
        Map<Integer, List<SysMenu>> parentIdGroup = menus.stream().filter(v -> SysMenu.MENU_TYPE_BUTTON != v.getType())
            .collect(Collectors.groupingBy(sysMenu -> sysMenu.getParentId()));
        // 先找到根节点
        List<SysMenu> sysMenus = parentIdGroup.get(TreeHelper.DEFAULT_PARENT_ID);
        if (null == sysMenus || sysMenus.isEmpty()) {
            return Collections.emptyList();
        }
        return this.genRoutes(sysMenus, parentIdGroup);
    }

    private List<VueRouteMenu> genRoutes(List<SysMenu> sysMenus, Map<Integer, List<SysMenu>> parentIdGroup) {
        List<VueRouteMenu> vueRouteMenus = new ArrayList<>();
        sysMenus.forEach(menu -> {
            String uriPath = menu.getUrl();
            // 标准化下后面使用，menu.getUrl() 可能会携带参数
            if (StringUtils.isNotEmpty(uriPath)) {
                UriComponents uriComponents = UriComponentsBuilder.fromUriString(menu.getUrl()).build();
                uriPath = uriComponents.getPath();
            }

            VueRouteMenu route = new VueRouteMenu();
            route.setMeta(new RouteMeta(menu.getName(), menu.getIcon()));
            if (menu.getType() == SysMenu.MENU_TYPE_DIRECTORY) {
                // 如果不设置点击时候目录path相同的会一起展开,child 使用的绝对路径不受影响
                route.setPath("/" + menu.getName());
                route.setComponent(VueRouteMenu.COMPONENT_LAYOUT);
            } else if (menu.getType() == SysMenu.MENU_TYPE_MENU) {
                if (null != menu.getUrl() && !menu.getUrl().startsWith("https://")
                    && !menu.getUrl().startsWith("http://")) {
                    route.setComponent(uriPath + "/index");
                    route.setPath(menu.getUrl());
                } else { // 外部链接
                    route.setComponent(VueRouteMenu.COMPONENT_IFRAME);
                    if (SysMenu.TARGET_MAIN.equals(menu.getTarget())) {// 内部特殊结构,外部前端自动处理
                        route.setPath(StringUtils.isNotEmpty(uriPath) ? uriPath : "/" + menu.getId());
                        route.getMeta().setFrameSrc(menu.getUrl());
                    } else {
                        route.setPath(menu.getUrl());
                    }
                }
            }
            // 名字和组件名字对应才可以keepAlive
            if (StringUtils.isNotEmpty(menu.getUrl())) {
                String[] menuSplit = StringUtils.split(uriPath, "/");
                if (menuSplit.length > 0) {
                    String name = "";
                    for (String s : menuSplit) {
                        name += CaseUtils.toCamelCase(s, true, '_', '-');
                    }
                    route.setName(name);
                }
            }
            // 处理子路由
            List<SysMenu> children = parentIdGroup.get(menu.getId());
            if (null != children && !children.isEmpty()) {
                route.setChildren(this.genRoutes(children, parentIdGroup));
            }
            vueRouteMenus.add(route);
        });
        return vueRouteMenus;
    }
}
