package com.izouma.jmrh.web;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.izouma.jmrh.domain.AuthorityMenu;
import com.izouma.jmrh.domain.Menu;
import com.izouma.jmrh.repo.AuthorityMenuRepo;
import com.izouma.jmrh.repo.MenuRepo;
import com.izouma.jmrh.security.Authority;
import com.izouma.jmrh.utils.SecurityUtils;
import lombok.AllArgsConstructor;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/menu")
public class MenuController extends BaseController {
    @Autowired
    private MenuRepo menuRepo;
    @Autowired
    private AuthorityMenuRepo authorityMenuRepo;
    @Value("classpath:/static/backlog.json")
    private Resource resource;

    /*
    * 登录角色权限菜单
    * */
    @GetMapping("/userMenu")
    public List<Menu> userMenu() {
        Set<Authority> authorities = SecurityUtils.getAuthenticatedUser().getAuthorities();
        String menuIds = "";
        for (Authority item : authorities) {
            AuthorityMenu byAuthorityName = authorityMenuRepo.findByAuthorityName(item.getName());
            if (byAuthorityName != null) {
                if (byAuthorityName.getMenuId() != null && byAuthorityName.getMenuId() != "") {
                    menuIds += "," + byAuthorityName.getMenuId();
                }
            }
        }
        String substring = menuIds.substring(1);
        List<Menu> menuList = menuRepo.findByInId(substring);
        //List<Menu> menuList = menuRepo.findByNameAndRootTrue(name);
      /*  for (Menu menu : menuList) {
            sortMenu(menu);
        }*/
        List<Menu> child = getChild(2L, menuList);
        Collections.sort(child);
        return child;
    }

    /*
     * 待办列表菜单
     * */
    @GetMapping("/userMenuList")
    public List<Map<String, String>> userMenuList() {
        Set<Authority> authorities = SecurityUtils.getAuthenticatedUser().getAuthorities();
        String menuIds = "";
        for (Authority item : authorities) {
            AuthorityMenu byAuthorityName = authorityMenuRepo.findByAuthorityName(item.getName());
            if (byAuthorityName != null) {
                if (byAuthorityName.getMenuId() != null && byAuthorityName.getMenuId() != "") {
                    menuIds += "," + byAuthorityName.getMenuId();
                }
            }
        }
        String substring = menuIds.substring(1);
        List<Menu> menuList = menuRepo.findByInId(substring);
        List<Map<String, String>> hashMaps = new ArrayList<>();
        try {
            String areaData = IOUtils.toString(resource.getInputStream(), Charset.forName("UTF-8"));
            List<Map<String, String>> list = JSONArray.parseObject(areaData, List.class);
            for (Menu menu : menuList) {
                for (Map<String, String> map : list) {
                    if (menu.getPath().equals(map.get("url"))) {
                        String url = menu.getPath().substring(0, menu.getPath().indexOf("List"));
                        map.put("listAll", url + "/all");
                        map.put("countUrl", url + "/count");
                        hashMaps.add(map);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return hashMaps;
    }

    @PreAuthorize("hasRole('ADMIN')")
    @GetMapping("/all")
    public List<Menu> all() {
        List<Menu> menuList = menuRepo.findByEnabledTrue();
        //menuList.forEach(this::sortMenu);
        return getChild(0L, menuList);
    }

    @PreAuthorize("hasRole('ADMIN')")
    @GetMapping("/allUserMenu")
    public Map allUserMenu(String authorityName) {
        List<Menu> menuList = menuRepo.findByEnabledTrue();
        AuthorityMenu byAuthorityName = authorityMenuRepo.findByAuthorityName(authorityName);
        HashMap mode = new HashMap<String, Objects>();
        mode.put("menuList", getChild(0L, menuList));
        if (byAuthorityName != null) {
            String menuId = byAuthorityName.getMenuId();
            String[] split = menuId.split(",");
            mode.put("menuId", split);
        }
        return mode;
    }

    @PreAuthorize("hasRole('ADMIN')")
    @PostMapping("/save")
    public Menu save(Menu menu) {
        if (menu.getEnabled() == null) {
            menu.setEnabled(true);
        }
        if (menu.getSort() == null) {
            menu.setSort(menuRepo.nextSort());
        }
        menuRepo.save(menu);
        return menu;
    }

    @PreAuthorize("hasRole('ADMIN')")
    @GetMapping("/groupByCategory")
    public Map<String, List<Menu>> groupByCategory() {
        return menuRepo.findAll().stream()
                .filter(menu -> menu.getCategory() != null)
                .collect(Collectors.groupingBy(Menu::getCategory));
    }

    private void sortMenu(Menu menu) {
        if (menu.getChildren() != null) {
            menu.getChildren().sort(Comparator.comparingInt(Menu::getSort));
        }
        menu.getChildren().forEach(this::sortMenu);
    }

    private static List<Menu> getChild(Long pid, List<Menu> allList) {
        ArrayList<Menu> child = new ArrayList<>();
        for (Menu menu : allList) {
            if (pid.longValue() == menu.getParent().longValue()) {
                menu.setChildren(getChild(menu.getId(), allList));
                if (menu.getChildren().size() > 0) {
                    Collections.sort(menu.getChildren());
                    /*menu.getChildren().sort(Comparator.comparingInt(Menu::getSort));*/
                }
                child.add(menu);
            }
        }
        return child;
    }
}
