package eu.eudat.controllers;

import eu.eudat.logic.managers.DepositManager;
import eu.eudat.logic.security.claims.ClaimedAuthorities;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.models.data.doi.DepositCode;
import eu.eudat.models.data.doi.DepositRequest;
import eu.eudat.models.data.doi.Doi;
import eu.eudat.models.data.doi.RepositoryConfig;
import eu.eudat.models.data.helpers.responses.ResponseItem;
import eu.eudat.models.data.security.Principal;
import eu.eudat.types.ApiMessageCode;
import eu.eudat.types.Authorities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@CrossOrigin
@RequestMapping(value = {"/api/deposit/"})
public class DepositController extends BaseController {
    private static final Logger logger = LoggerFactory.getLogger(DepositController.class);

    private DepositManager depositManager;

    @Autowired
    public DepositController(ApiContext apiContext, DepositManager depositManager){
        super(apiContext);
        this.depositManager = depositManager;
    }

    @RequestMapping(method = RequestMethod.GET, value = {"/repos"})
    public @ResponseBody
    ResponseEntity<ResponseItem<List<RepositoryConfig>>> getAvailableRepos(@ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) {
        List<RepositoryConfig> ids = this.depositManager.getAvailableRepos();
        return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<List<RepositoryConfig>>().status(ApiMessageCode.NO_MESSAGE).payload(ids));
    }

    @RequestMapping(method = RequestMethod.POST, value = {"/getAccessToken"})
    public @ResponseBody
    ResponseEntity<ResponseItem<String>> getAccessToken(@RequestBody DepositCode depositCode, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws Exception {
        String accessToken = this.depositManager.authenticate(depositCode.getRepositoryId(), depositCode.getCode());
        return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<String>().status(ApiMessageCode.NO_MESSAGE).payload(accessToken));
    }

    @RequestMapping(method = RequestMethod.POST, value = {"/createDoi"})
    public @ResponseBody
    ResponseEntity<ResponseItem<Doi>> createDoi(@RequestBody DepositRequest depositRequest, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) {
        try {
            Doi doi = this.depositManager.deposit(depositRequest, principal);
            return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<Doi>().status(ApiMessageCode.SUCCESS_MESSAGE).message("Successfully created DOI for Data Datamanagement Plan in question.").payload(doi));
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem<Doi>().status(ApiMessageCode.ERROR_MESSAGE).message("Failed to create DOI for the Data Management Plan: " + e.getMessage()));
        }
    }
}
