package org.brapi.test.BrAPITestServer.controller.geno;

import java.util.List;

import org.brapi.test.BrAPITestServer.controller.core.BrAPIController;
import org.brapi.test.BrAPITestServer.exceptions.BrAPIServerException;
import org.brapi.test.BrAPITestServer.model.dto.geno.GenomeMapWriteRequest;
import org.brapi.test.BrAPITestServer.model.dto.geno.LinkageGroupWriteRequest;
import org.brapi.test.BrAPITestServer.model.dto.geno.MarkerPositionWriteRequest;
import org.brapi.test.BrAPITestServer.service.geno.GenomeMapService;
import org.brapi.test.BrAPITestServer.service.geno.MarkerPositionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import io.swagger.model.geno.GenomeMap;
import io.swagger.model.geno.GenomeMapListResponse;
import io.swagger.model.geno.GenomeMapListResponseResult;
import io.swagger.model.geno.GenomeMapSingleResponse;
import io.swagger.model.geno.LinkageGroup;
import io.swagger.model.geno.LinkageGroupListResponse;
import io.swagger.model.geno.LinkageGroupListResponseResult;
import io.swagger.model.geno.MarkerPosition;
import io.swagger.model.geno.MarkerPositionsListResponse;
import io.swagger.model.geno.MarkerPositionsListResponseResult;
import jakarta.servlet.http.HttpServletRequest;

@RestController
public class GenotypingGenomeMapWriteController extends BrAPIController {

	private static final Logger log = LoggerFactory.getLogger(GenotypingGenomeMapWriteController.class);

	private final GenomeMapService genomeMapService;
	private final MarkerPositionService markerPositionService;
	private final HttpServletRequest request;

	@Autowired
	public GenotypingGenomeMapWriteController(GenomeMapService genomeMapService,
			MarkerPositionService markerPositionService, HttpServletRequest request) {
		this.genomeMapService = genomeMapService;
		this.markerPositionService = markerPositionService;
		this.request = request;
	}

	@CrossOrigin
	@RequestMapping(value = "/maps", produces = { "application/json" }, consumes = {
			"application/json" }, method = RequestMethod.POST)
	public ResponseEntity<GenomeMapListResponse> mapsPost(@RequestBody GenomeMapWriteRequest body,
			@RequestHeader(value = "Authorization", required = false) String authorization)
			throws BrAPIServerException {
		log.debug("Request: " + request.getRequestURI());
		validateSecurityContext(request, "ROLE_USER");
		validateAcceptHeader(request);
		GenomeMap data = genomeMapService.saveMap(body);
		return responseOK(new GenomeMapListResponse(), new GenomeMapListResponseResult(), List.of(data));
	}

	@CrossOrigin
	@RequestMapping(value = "/maps/{mapDbId}", produces = { "application/json" }, consumes = {
			"application/json" }, method = RequestMethod.PUT)
	public ResponseEntity<GenomeMapSingleResponse> mapsMapDbIdPut(@PathVariable("mapDbId") String mapDbId,
			@RequestBody GenomeMapWriteRequest body,
			@RequestHeader(value = "Authorization", required = false) String authorization)
			throws BrAPIServerException {
		log.debug("Request: " + request.getRequestURI());
		validateSecurityContext(request, "ROLE_USER");
		validateAcceptHeader(request);
		GenomeMap data = genomeMapService.updateMap(mapDbId, body);
		return responseOK(new GenomeMapSingleResponse(), data);
	}

	@CrossOrigin
	@RequestMapping(value = "/maps/{mapDbId}", produces = { "application/json" }, method = RequestMethod.DELETE)
	public ResponseEntity<GenomeMapSingleResponse> mapsMapDbIdDelete(@PathVariable("mapDbId") String mapDbId,
			@RequestHeader(value = "Authorization", required = false) String authorization)
			throws BrAPIServerException {
		log.debug("Request: " + request.getRequestURI());
		validateSecurityContext(request, "ROLE_USER");
		validateAcceptHeader(request);
		GenomeMap data = genomeMapService.deleteMap(mapDbId);
		return responseOK(new GenomeMapSingleResponse(), data);
	}

	@CrossOrigin
	@RequestMapping(value = "/maps/{mapDbId}/linkagegroups", produces = { "application/json" }, consumes = {
			"application/json" }, method = RequestMethod.POST)
	public ResponseEntity<LinkageGroupListResponse> mapsMapDbIdLinkagegroupsPost(
			@PathVariable("mapDbId") String mapDbId, @RequestBody LinkageGroupWriteRequest body,
			@RequestHeader(value = "Authorization", required = false) String authorization)
			throws BrAPIServerException {
		log.debug("Request: " + request.getRequestURI());
		validateSecurityContext(request, "ROLE_USER");
		validateAcceptHeader(request);
		LinkageGroup data = genomeMapService.saveLinkageGroup(mapDbId, body);
		return responseOK(new LinkageGroupListResponse(), new LinkageGroupListResponseResult(), List.of(data));
	}

	@CrossOrigin
	@RequestMapping(value = "/maps/{mapDbId}/linkagegroups/{linkageGroupDbId}", produces = {
			"application/json" }, consumes = { "application/json" }, method = RequestMethod.PUT)
	public ResponseEntity<LinkageGroupListResponse> mapsMapDbIdLinkagegroupsLinkageGroupDbIdPut(
			@PathVariable("mapDbId") String mapDbId, @PathVariable("linkageGroupDbId") String linkageGroupDbId,
			@RequestBody LinkageGroupWriteRequest body,
			@RequestHeader(value = "Authorization", required = false) String authorization)
			throws BrAPIServerException {
		log.debug("Request: " + request.getRequestURI());
		validateSecurityContext(request, "ROLE_USER");
		validateAcceptHeader(request);
		LinkageGroup data = genomeMapService.updateLinkageGroup(mapDbId, linkageGroupDbId, body);
		return responseOK(new LinkageGroupListResponse(), new LinkageGroupListResponseResult(), List.of(data));
	}

	@CrossOrigin
	@RequestMapping(value = "/maps/{mapDbId}/linkagegroups/{linkageGroupDbId}", produces = {
			"application/json" }, method = RequestMethod.DELETE)
	public ResponseEntity<LinkageGroupListResponse> mapsMapDbIdLinkagegroupsLinkageGroupDbIdDelete(
			@PathVariable("mapDbId") String mapDbId, @PathVariable("linkageGroupDbId") String linkageGroupDbId,
			@RequestHeader(value = "Authorization", required = false) String authorization)
			throws BrAPIServerException {
		log.debug("Request: " + request.getRequestURI());
		validateSecurityContext(request, "ROLE_USER");
		validateAcceptHeader(request);
		LinkageGroup data = genomeMapService.deleteLinkageGroup(mapDbId, linkageGroupDbId);
		return responseOK(new LinkageGroupListResponse(), new LinkageGroupListResponseResult(), List.of(data));
	}

	@CrossOrigin
	@RequestMapping(value = "/markerpositions", produces = { "application/json" }, consumes = {
			"application/json" }, method = RequestMethod.POST)
	public ResponseEntity<MarkerPositionsListResponse> markerpositionsPost(@RequestBody MarkerPositionWriteRequest body,
			@RequestHeader(value = "Authorization", required = false) String authorization)
			throws BrAPIServerException {
		log.debug("Request: " + request.getRequestURI());
		validateSecurityContext(request, "ROLE_USER");
		validateAcceptHeader(request);
		MarkerPosition data = markerPositionService.saveMarkerPosition(body);
		return responseOK(new MarkerPositionsListResponse(), new MarkerPositionsListResponseResult(), List.of(data));
	}

	@CrossOrigin
	@RequestMapping(value = "/markerpositions/{markerPositionDbId}", produces = { "application/json" }, consumes = {
			"application/json" }, method = RequestMethod.PUT)
	public ResponseEntity<MarkerPositionsListResponse> markerpositionsMarkerPositionDbIdPut(
			@PathVariable("markerPositionDbId") String markerPositionDbId,
			@RequestBody MarkerPositionWriteRequest body,
			@RequestHeader(value = "Authorization", required = false) String authorization)
			throws BrAPIServerException {
		log.debug("Request: " + request.getRequestURI());
		validateSecurityContext(request, "ROLE_USER");
		validateAcceptHeader(request);
		MarkerPosition data = markerPositionService.updateMarkerPosition(markerPositionDbId, body);
		return responseOK(new MarkerPositionsListResponse(), new MarkerPositionsListResponseResult(), List.of(data));
	}

	@CrossOrigin
	@RequestMapping(value = "/markerpositions/{markerPositionDbId}", produces = {
			"application/json" }, method = RequestMethod.DELETE)
	public ResponseEntity<MarkerPositionsListResponse> markerpositionsMarkerPositionDbIdDelete(
			@PathVariable("markerPositionDbId") String markerPositionDbId,
			@RequestHeader(value = "Authorization", required = false) String authorization)
			throws BrAPIServerException {
		log.debug("Request: " + request.getRequestURI());
		validateSecurityContext(request, "ROLE_USER");
		validateAcceptHeader(request);
		MarkerPosition data = markerPositionService.deleteMarkerPosition(markerPositionDbId);
		return responseOK(new MarkerPositionsListResponse(), new MarkerPositionsListResponseResult(), List.of(data));
	}
}
