package eu.dnetlib.uoaadmintools.controllers;

import eu.dnetlib.uoaadmintools.entities.menu.Menu;
import eu.dnetlib.uoaadmintools.entities.menu.MenuFull;
import eu.dnetlib.uoaadmintools.entities.menu.MenuItem;
import eu.dnetlib.uoaadmintools.entities.menu.MenuItemFull;
import eu.dnetlib.uoaadmintools.services.MenuService;
import eu.dnetlib.uoaadmintoolslibrary.dao.PortalDAO;
import eu.dnetlib.uoaadmintoolslibrary.entities.Portal;
import eu.dnetlib.uoaadmintoolslibrary.handlers.ContentNotFoundException;
import eu.dnetlib.uoaadmintoolslibrary.handlers.MismatchingContentException;
import eu.dnetlib.uoaadmintoolslibrary.handlers.utils.RolesUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@CrossOrigin(origins = "*")
public class MenuController {
    private final Logger log = Logger.getLogger(this.getClass());

    @Autowired
    private MenuService menuService;
    @Autowired
    private PortalDAO portalDAO;
    @Autowired
    private RolesUtils rolesUtils;

    // NOT USED - maybe leave it
////    @PreAuthorize("hasAnyAuthority(" +
////            "@AuthorizationService.PORTAL_ADMIN, " +
////            "@AuthorizationService.curator('community'), @AuthorizationService.manager('community', #pid))")
//    @RequestMapping(value = "/community/{pid}/menu", method = RequestMethod.GET)
//    public List<MenuItem> getMenuItems(@PathVariable(value = "pid") String pid ) throws ContentNotFoundException {
//        //        @RequestParam(value="featured", required=false) String isFeatured
//        Portal portal = portalDAO.findByPid(pid);
//        if(portal == null){
//            throw new ContentNotFoundException("Portal with pid: "+pid+" not found");
//        }
//        if(!portal.getType().equals("community")) {
//            // EXCEPTION - MismatchingContent
//            throw new MismatchingContentException("Get Notifications: Portal with id: "+portal.getId()+" has type: "+portal.getType()+" instead of community");
//        }
//
//        List<MenuItem> menuItems = menuService.getMenuItems(pid);
//        if(menuItems == null || menuItems.size() == 0){
//            throw new ContentNotFoundException("Menu for community with pid: "+pid+" not found");
//        }
//        return menuItems;
//    }

    // OLD endpoint
    @RequestMapping(value = "/community/{pid}/menu/root/full", method = RequestMethod.GET)
    public List<MenuItemFull> getRootMenuItemsFull(@PathVariable(value = "pid") String pid ) throws ContentNotFoundException {
        Portal portal = portalDAO.findByPid(pid);
        if(portal == null){
            throw new ContentNotFoundException("Portal with pid: "+pid+" not found");
        }
        if(!portal.getType().equals("community")) {
            // EXCEPTION - MismatchingContent
            throw new MismatchingContentException("getMenuItemsFull: Portal with id: "+portal.getId()+" has type: "+portal.getType()+" instead of community");
        }

        List<MenuItemFull> menuItems = menuService.getRootMenuItemsFull(pid);
//        if(menuItems == null || menuItems.size() == 0){
//            throw new ContentNotFoundException("Root menu for community with pid: "+pid+" not found");
//        }
        return menuItems;
    }

    @RequestMapping(value = "/community/{pid}/menu/full", method = RequestMethod.GET)
    public MenuFull getMenuFull(@PathVariable(value = "pid") String pid ) throws ContentNotFoundException {
        Portal portal = portalDAO.findByPid(pid);
        if(portal == null){
            throw new ContentNotFoundException("Portal with pid: "+pid+" not found");
        }
        if(!portal.getType().equals("community")) {
            // EXCEPTION - MismatchingContent
            throw new MismatchingContentException("getMenuItemsFull: Portal with id: "+portal.getId()+" has type: "+portal.getType()+" instead of community");
        }

        MenuFull menu = menuService.getMenuFull(pid);
        return menu;
    }

    @PreAuthorize("hasAnyAuthority(" +
            "@AuthorizationService.PORTAL_ADMIN, " +
            "@AuthorizationService.curator('community')," +
            "@AuthorizationService.manager('community', #pid))")
    @RequestMapping(value = "/community/{pid}/menu/update", method = RequestMethod.POST)
    public MenuItemFull updateMenuItem(@PathVariable String pid, @RequestBody MenuItemFull menuItemFull) {
        Portal portal = portalDAO.findByPid(pid);
        if(portal == null){
            throw new ContentNotFoundException("Portal with pid: "+pid+" not found");
        }
        if(!portal.getType().equals("community")) {
            // EXCEPTION - MismatchingContent
            throw new MismatchingContentException("updateMenuItem: Portal with id: "+portal.getId()+" has type: "+portal.getType()+" instead of community");
        }
        if(menuItemFull.getIsFeatured() && menuItemFull.getItems() != null && menuItemFull.getItems().size() > 0) {
            // EXCEPTION - MismatchingContent
            throw new MismatchingContentException("updateMenuItem: MenuItem "+menuItemFull.getId()+" cannot be featured because it has "+menuItemFull.getItems().size() + " sub menu items");
        }
        if(menuItemFull.getType() == null ||
                (menuItemFull.getType().equals("internal") && menuItemFull.getRoute() == null) ||
                (menuItemFull.getType().equals("external") && menuItemFull.getUrl() == null)) {
            // EXCEPTION - MismatchingContent
            throw new MismatchingContentException("insertMenuItem: A required field is missing in menu item: type="+menuItemFull.getType()
                    + " - url="+menuItemFull.getUrl() + " - route="+menuItemFull.getRoute());
        }
        if(menuItemFull.getPortalPid() == null) {
            menuItemFull.setPortalPid(pid);
        } else if(!menuItemFull.getPortalPid().equals(pid)) {
            // EXCEPTION - MismatchingContent
            throw new MismatchingContentException("updateMenuItem: MenuItem has portalPid: "+menuItemFull.getPortalPid()+" instead of "+pid);
        }
        if(menuItemFull.getId() == null) {
            // EXCEPTION - MismatchingContent
            throw new MismatchingContentException("updateMenuItem: This MenuItem has no id.");
        }

        return menuService.updateMenu(menuItemFull, pid);
    }

    @PreAuthorize("hasAnyAuthority(" +
            "@AuthorizationService.PORTAL_ADMIN, " +
            "@AuthorizationService.curator('community')," +
            "@AuthorizationService.manager('community', #pid))")
    @RequestMapping(value = "/community/{pid}/menu/save", method = RequestMethod.POST)
    public MenuItemFull insertMenuItem(@PathVariable String pid, @RequestBody MenuItem menuItem) {
        Portal portal = portalDAO.findByPid(pid);
        if(portal == null){
            throw new ContentNotFoundException("Portal with pid: "+pid+" not found");
        }
        if(portal.getType() == null || !portal.getType().equals("community")) {
            // EXCEPTION - MismatchingContent
            throw new MismatchingContentException("insertMenuItem: Portal with id: "+portal.getId()+" has type: "+portal.getType()+" instead of community");
        }
        if(menuItem.getIsFeatured() && menuItem.getItems() != null && menuItem.getItems().size() > 0) {
            // EXCEPTION - MismatchingContent
            throw new MismatchingContentException("updateMenuItem: MenuItem "+menuItem.getId()+" cannot be featured because it has "+menuItem.getItems().size() + " sub menu items");
        }
        if(menuItem.getType() == null ||
                (menuItem.getType().equals("internal") && menuItem.getRoute() == null) ||
                (menuItem.getType().equals("external") && menuItem.getUrl() == null)) {
            // EXCEPTION - MismatchingContent
            throw new MismatchingContentException("insertMenuItem: A required field is missing in menu item: type="+menuItem.getType()
                    + " - url="+menuItem.getUrl() + " - route="+menuItem.getRoute());
        }
        if(menuItem.getPortalPid() == null) {
            menuItem.setPortalPid(pid);
        } else if(!menuItem.getPortalPid().equals(pid)) {
            // EXCEPTION - MismatchingContent
            throw new MismatchingContentException("insertMenuItem: MenuItem has portalPid: "+menuItem.getPortalPid()+" instead of "+pid);
        }
        if(menuItem.getId() != null) {
            // EXCEPTION - MismatchingContent
            throw new MismatchingContentException("insertMenuItem: MenuItem has already an id: "+menuItem.getId());
        }

        return menuService.insertMenuItemInMenu(menuItem, pid);
    }

    @PreAuthorize("hasAnyAuthority(" +
            "@AuthorizationService.PORTAL_ADMIN, " +
            "@AuthorizationService.curator('community')," +
            "@AuthorizationService.manager('community', #pid))")
    @RequestMapping(value = "/community/{pid}/menu/delete", method = RequestMethod.POST)
    public Boolean deleteMenuItem(@PathVariable String pid, @RequestBody String menuItemId) throws Exception {
        Portal portal = portalDAO.findByPid(pid);
        if(portal == null){
            throw new ContentNotFoundException("Portal with pid: "+pid+" not found");
        }
        if(!portal.getType().equals("community")) {
            // EXCEPTION - MismatchingContent
            throw new MismatchingContentException("deleteMenuItem: Portal with id: "+portal.getId()+" has type: "+portal.getType()+" instead of community");
        }

        return menuService.deleteMenuItem(menuItemId, pid);
    }

    @PreAuthorize("hasAnyAuthority(" +
            "@AuthorizationService.PORTAL_ADMIN, " +
            "@AuthorizationService.curator('community')," +
            "@AuthorizationService.manager('community', #pid))")
    @RequestMapping(value = "/community/{pid}/menu/reorder", method = RequestMethod.POST)
    public Boolean reorderMenuItems(@PathVariable String pid, @RequestBody List<MenuItemFull> menuItems) throws Exception {
        Portal portal = portalDAO.findByPid(pid);
        if(portal == null){
            throw new ContentNotFoundException("Portal with pid: "+pid+" not found");
        }
        if(!portal.getType().equals("community")) {
            // EXCEPTION - MismatchingContent
            throw new MismatchingContentException("reorderMenuItems: Portal with id: "+portal.getId()+" has type: "+portal.getType()+" instead of community");
        }

        return menuService.reorderMenuItems(menuItems, pid);
    }

    @PreAuthorize("hasAnyAuthority(" +
            "@AuthorizationService.PORTAL_ADMIN, " +
            "@AuthorizationService.curator('community')," +
            "@AuthorizationService.manager('community', #pid))")
    @RequestMapping(value = {"/community/{pid}/menu/toggle"}, method = RequestMethod.POST)
    public Menu toggleMenu(@PathVariable(value = "pid") String pid, @RequestParam String status, @RequestParam(value="featured", required=false) String isFeatured) throws Exception {
        return menuService.toggleMenu(pid, status, isFeatured);
    }
}
