package eu.dnetlib.uoaadmintoolslibrary.controllers;

import com.mongodb.DuplicateKeyException;
import eu.dnetlib.uoaadmintoolslibrary.entities.Page;
import eu.dnetlib.uoaadmintoolslibrary.entities.fullEntities.PortalPage;
import eu.dnetlib.uoaadmintoolslibrary.handlers.ForbiddenException;
import eu.dnetlib.uoaadmintoolslibrary.handlers.MismatchingContentException;
import eu.dnetlib.uoaadmintoolslibrary.handlers.utils.RolesUtils;
import eu.dnetlib.uoaadmintoolslibrary.services.PageService;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.security.access.prepost.PreAuthorize;

import javax.validation.constraints.Null;
import java.util.*;

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

    @Autowired
    private PageService pageService;

    @Autowired
    private RolesUtils rolesUtils;

    // used by portals WITHOUT ANY PARAMS
    @RequestMapping(value = "/page/full", method = RequestMethod.GET)
    public List<PortalPage> getPagesFull(@RequestParam(value="pid", required=false) String pid,
                                         @RequestParam(value="page_route", required=false) String page_route) {
        // isEnabled is not filled!!! Do not use this method to get pages for specific pid - use getPagesForPortalByType instead.
        return pageService.getPagesFull(pid, page_route);
    }

    // used by portals WITHOUT ANY PARAMS
    @RequestMapping(value = "/page", method = RequestMethod.GET)
    public List<Page> getAllPages(@RequestParam(value="pid", required=false) String pid,
                                  @RequestParam(value="page_route", required=false) String page_route,
                                  @RequestParam(value="with_positions", required=false) String with_positions) {
        return pageService.getAllPages(pid, page_route, with_positions);
    }

//    // not used by portals
//    @RequestMapping(value = "/page", method = RequestMethod.DELETE)
//    public void deleteAllPages() {
//        pageService.deleteAllPages();
//    }

    // used
//    @PreAuthorize("hasAnyAuthority(@AuthorizationService.PORTAL_ADMIN)")
    @RequestMapping(value = "/page/update", method = RequestMethod.POST)
    public PortalPage updatePage(@RequestBody PortalPage portalPage) {
        List<String> roles = rolesUtils.getRoles();
        if(portalPage == null) {
            throw new NullPointerException("Update page: portalPage is null");
        }
        if(portalPage.getId() == null) {
            // EXCEPTION - MismatchingContent
            throw new MismatchingContentException("Update page: Page has no id.");
        }
        if(!rolesUtils.isPortalAdmin(roles) || (
                portalPage.getPortalPid() != null && !rolesUtils.hasUpdateAuthority(roles, portalPage.getPortalType(), portalPage.getPortalPid()))) {
            // EXCEPTION - Access denied
            throw new ForbiddenException("Update page: You are not authorized to update  a page for "+portalPage.getPortalType()+
                    (portalPage.getPortalPid()!=null ? " : "+portalPage.getPortalPid() : ""));
        }

        Page existingPage = pageService.getPageByPortalTypeAndRoute(portalPage.getPortalType(), portalPage.getRoute(), portalPage.getPortalPid());
        if(existingPage != null && !existingPage.getId().equals(portalPage.getId())) {
            throw new MismatchingContentException("Update page: There is already a page ("+existingPage.getId()+") with route: "+portalPage.getRoute() + " in "+
                    portalPage.getPortalType() + (portalPage.getPortalPid() != null ? " : "+portalPage.getPortalPid() : ""));
        }
        return pageService.updatePage(portalPage);
    }

    // used
//    @PreAuthorize("hasAnyAuthority(@AuthorizationService.PORTAL_ADMIN)")
    @RequestMapping(value = "/page/save", method = RequestMethod.POST)
    public PortalPage insertPage(@RequestBody PortalPage portalPage) {
        List<String> roles = rolesUtils.getRoles();
        if(portalPage == null) {
            throw new NullPointerException("Save page: portalPage is null");
        }
        if(portalPage.getId() != null) {
            // EXCEPTION - MismatchingContent
            throw new MismatchingContentException("Save page: Page has already an id: "+portalPage.getId());
        }
        if(!rolesUtils.isPortalAdmin(roles) || (
                portalPage.getPortalPid() != null && !rolesUtils.hasUpdateAuthority(roles, portalPage.getPortalType(), portalPage.getPortalPid()))) {
            // EXCEPTION - Access denied
            throw new ForbiddenException("Save page: You are not authorized to create a page for "+portalPage.getPortalType()+
                    (portalPage.getPortalPid()!=null ? " : "+portalPage.getPortalPid() : ""));
        }

        Page existingPage = pageService.getPageByPortalTypeAndRoute(portalPage.getPortalType(), portalPage.getRoute(), portalPage.getPortalPid());
        if(existingPage != null) {
            throw new MismatchingContentException("Save page: There is already a page ("+existingPage.getId()+") with route: "+portalPage.getRoute() + " in "+
                    portalPage.getPortalType() + (portalPage.getPortalPid() != null ? " : "+portalPage.getPortalPid() : ""));
        }

        return pageService.insertPage(portalPage);
    }

    // used
//    @PreAuthorize("hasAnyAuthority(@AuthorizationService.PORTAL_ADMIN)")
    @RequestMapping(value = "/page/delete", method = RequestMethod.POST)
    public Boolean deletePages(@RequestBody List<String> pages) throws Exception {
        return pageService.deletePages(pages);
    }

//    // not used by portals
//    @RequestMapping(value = "/page/{id}", method = RequestMethod.GET)
//    public Page getPage(@PathVariable(value = "id") String id) {
//        return pageService.getPage(id);
//    }
//
//    // not used by portals
//    @RequestMapping(value = "/page/{id}", method = RequestMethod.DELETE)
//    public void deletePage(@PathVariable(value = "id") String id) {
//        pageService.deletePage(id);
//    }
//
//    // not used by portals
//    @RequestMapping(value = "/page/{id}/entity", method = RequestMethod.GET)
//    public List<String> getPageEntities(@PathVariable(value = "id") String id) {
//        return pageService.getPageEntities(id);
//    }
//
//    // not used by portals
//    @RequestMapping(value = "page/{id}/entity/toggle", method = RequestMethod.POST)
//    public Page togglePageEntity(@PathVariable(value = "id") String id, @RequestParam String entityId, @RequestParam String status) throws Exception {
//        return pageService.togglePageEntity(id, entityId, status);
//    }
}