package com.iqser.red.service.persistence.service.v2.api.external.resource;

import static com.iqser.red.service.persistence.service.v2.api.external.resource.DossierTemplateResource.DOSSIER_TEMPLATE_ID_PARAM;
import static com.iqser.red.service.persistence.service.v2.api.external.resource.DossierTemplateResource.DOSSIER_TEMPLATE_ID_PATH_VARIABLE;
import static com.iqser.red.service.persistence.service.v2.api.external.resource.DossierTemplateResource.DOSSIER_TEMPLATE_PATH;

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.Dossier;
import com.iqser.red.service.persistence.service.v2.api.external.model.DocuMineDossierRequest;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.DossierAttributes;
import com.iqser.red.service.persistence.service.v2.api.external.model.DossierList;
import com.iqser.red.service.persistence.service.v2.api.external.model.DownloadRequest;
import com.iqser.red.service.persistence.service.v2.api.external.model.DownloadStatus;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;

@ApiResponses(value = {@ApiResponse(responseCode = "429", description = "Too many requests.")})
public interface DossierResource {

    String DOSSIER_PATH = "/dossiers";
    String PATH = ExternalApiConstants.BASE_PATH + DOSSIER_TEMPLATE_PATH + DOSSIER_TEMPLATE_ID_PATH_VARIABLE + DOSSIER_PATH;
    String DOSSIER_ID_PARAM = "dossierId";
    String DOSSIER_ID_PATH_PARAM = "/{" + DOSSIER_ID_PARAM + "}";
    String ATTRIBUTES_PATH = "/attributes";
    String CREATE_DOWNLOAD_PATH = "/create-download";

    String INCLUDE_ACTIVE_PARAM = "includeActive";
    String INCLUDE_ARCHIVED_PARAM = "includeArchived";
    String INCLUDE_SOFT_DELETED_PARAM = "includeSoftDeleted";

    String DELETE_PERMANENTLY_PARAM = "deletePermanently";


    @ResponseStatus(value = HttpStatus.OK)
    @ResponseBody
    @GetMapping(value = PATH, produces = MediaType.APPLICATION_JSON_VALUE)
    @Operation(summary = "Gets all existing dossiers for a specific dossier template.", description = "None")
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
    DossierList getDossiers(@Parameter(name = DOSSIER_TEMPLATE_ID_PARAM, description = "The identifier of the dossier template that is used for the dossier.", required = true) @PathVariable(DOSSIER_TEMPLATE_ID_PARAM) String dossierTemplateId,
                            @Parameter(name = INCLUDE_ACTIVE_PARAM, description = "A Toggle to include active dossiers: If `true` (default) the response contains dossiers that are active, i.e. the dossier is neither archived nor soft-deleted.") @RequestParam(name = INCLUDE_ACTIVE_PARAM, defaultValue = "true", required = false) boolean includeActive,
                            @Parameter(name = INCLUDE_ARCHIVED_PARAM, description = "A Toggle to include archived dossiers: If `true` the response contains dossiers that have been archived.") @RequestParam(name = INCLUDE_ARCHIVED_PARAM, defaultValue = "false", required = false) boolean includeArchived,
                            @Parameter(name = INCLUDE_SOFT_DELETED_PARAM, description = "A Toggle to include soft-deleted dossiers: If `true` the response contains dossiers that have been soft-deleted, i.e. the dossiers can still be restored.") @RequestParam(name = INCLUDE_SOFT_DELETED_PARAM, defaultValue = "false", required = false) boolean includeSoftDeleted);


    @ResponseStatus(value = HttpStatus.OK)
    @ResponseBody
    @GetMapping(value = PATH + DOSSIER_ID_PATH_PARAM, produces = MediaType.APPLICATION_JSON_VALUE)
    @Operation(summary = "Gets an existing dossier.", description = "By default, the requested dossier will be returned only if it is active. This behavior can be changed by using and combining the respective toggle parameters.")
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Not found")})
    Dossier getDossier(@Parameter(name = DOSSIER_TEMPLATE_ID_PARAM, description = "The identifier of the dossier template that is used for the dossier.", required = true) @PathVariable(DOSSIER_TEMPLATE_ID_PARAM) String dossierTemplateId,
                       @Parameter(name = DOSSIER_ID_PARAM, description = "The identifier of the dossier to retrieve.", required = true) @PathVariable(DOSSIER_ID_PARAM) String dossierId,
                       @Parameter(name = INCLUDE_SOFT_DELETED_PARAM, description = "A Toggle to return a soft-deleted dossier: If `true` the dossier will be returned if it has been soft-deleted, i.e. the dossier can still be restored.") @RequestParam(name = INCLUDE_SOFT_DELETED_PARAM, defaultValue = "false", required = false) boolean includeSoftDeleted);


    @ResponseBody
    @PostMapping(value = PATH, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    @Operation(summary = "Creates or updates a dossier for a specific dossier template.", description = "None")
    @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "Successfully saved the dossier."), @ApiResponse(responseCode = "400", description = "Malformed request parameters or body"), @ApiResponse(responseCode = "409", description = "Duplicate")})
    ResponseEntity<Dossier> createDossierOrUpdateDossier(@Parameter(name = DOSSIER_TEMPLATE_ID_PARAM, description = "The identifier of the dossier template that is used for the dossier.", required = true) @PathVariable(DOSSIER_TEMPLATE_ID_PARAM) String dossierTemplateId,
                                                         @RequestBody DocuMineDossierRequest dossier);


    @ResponseStatus(value = HttpStatus.NO_CONTENT)
    @DeleteMapping(value = PATH + DOSSIER_ID_PATH_PARAM)
    @Operation(summary = "Deletes an existing dossier.", description = "Dossiers get soft-deleted unless specified other. A soft-deleted dossier can be restored during a retention period that is configured in the application settings. The default retention period is 96h.")
    @ApiResponses(value = {@ApiResponse(responseCode = "204", description = "Successfully deleted the dossier."), @ApiResponse(responseCode = "404", description = "Not found")})
    void deleteDossier(@Parameter(name = DOSSIER_TEMPLATE_ID_PARAM, description = "The identifier of the dossier template that is used for the dossier.", required = true) @PathVariable(DOSSIER_TEMPLATE_ID_PARAM) String dossierTemplateId,
                       @Parameter(name = DOSSIER_ID_PARAM, description = "The identifier of the dossier to retrieve.", required = true) @PathVariable(DOSSIER_ID_PARAM) String dossierId,
                       @Parameter(name = DELETE_PERMANENTLY_PARAM, description = "A toggle to determine the deletion mode for a dossier: `true`: The dossier will be permanently deleted and can't be restored. `false` (default): Soft-delete, allowing restoration within the application-configured retention period.") @RequestParam(name = DELETE_PERMANENTLY_PARAM, defaultValue = "false", required = false) boolean deletePermanently);


    @ResponseStatus(value = HttpStatus.NO_CONTENT)
    @ResponseBody
    @PostMapping(value = PATH + DOSSIER_ID_PATH_PARAM + ATTRIBUTES_PATH, consumes = MediaType.APPLICATION_JSON_VALUE)
    @Operation(summary = "Update or set attributes for a specific dossier.", description = "None")
    @ApiResponses(value = {@ApiResponse(responseCode = "204", description = "Dossier attributes successfully updated."), @ApiResponse(responseCode = "404", description = "Not found")})
    void setDossierAttributes(@Parameter(name = DOSSIER_TEMPLATE_ID_PARAM, description = "The identifier of a dossier template", required = true) @PathVariable(DOSSIER_TEMPLATE_ID_PARAM) String dossierTemplateId,
                                                 @Parameter(name = DOSSIER_ID_PARAM, description = "The identifier of a dossier", required = true) @PathVariable(DOSSIER_ID_PARAM) String dossierId,
                                                 @RequestBody DossierAttributes dossierAttributes);


    @ResponseBody
    @ResponseStatus(value = HttpStatus.OK)
    @PostMapping(value = PATH + DOSSIER_ID_PATH_PARAM + CREATE_DOWNLOAD_PATH, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
    @Operation(summary = "Initiate the creation of a download package for all files of a dossier.")
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Successfully started the creation of the download package for all files of the requested dossier."), @ApiResponse(responseCode = "404", description = "Not found")})
    DownloadStatus prepareDossierDownload(@Parameter(name = DOSSIER_TEMPLATE_ID_PARAM, description = "The identifier of a dossier template", required = true) @PathVariable(DOSSIER_TEMPLATE_ID_PARAM) String dossierTemplateId,
                                          @Parameter(name = DOSSIER_ID_PARAM, description = "The identifier of a dossier", required = true) @PathVariable(DOSSIER_ID_PARAM) String dossierId,
                                          @RequestBody DownloadRequest downloadRequest);

}
