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

import java.util.concurrent.CompletableFuture;

import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
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.DownloadResponse;
import com.iqser.red.service.persistence.service.v1.api.shared.model.DownloadStatusResponse;
import com.iqser.red.service.persistence.service.v1.api.shared.model.PrepareDownloadRequest;
import com.iqser.red.service.persistence.service.v1.api.shared.model.PrepareDownloadWithOptionRequest;
import com.iqser.red.service.persistence.service.v1.api.shared.model.RemoveDownloadRequest;
import com.iqser.red.service.persistence.service.v1.api.shared.model.common.JSONPrimitive;

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

@ResponseStatus(HttpStatus.OK)
public interface DownloadResource {

    String REST_PATH = ExternalApi.BASE_PATH + "/async/download";
    String FALSE = "false";

    String STORAGE_ID = "storageId";

    String OTT = "oneTimeToken";
    String OTT_PATH_VARIABLE = "/{" + OTT + "}";
    String GENERATE_OTT_PATH = "/generate-ott";
    String OTT_PATH = "/with-ott";


    @Operation(summary = "Prepares a download for given fileIds and types", description = "None")
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Success."), @ApiResponse(responseCode = "400", description = "Request contains error."), @ApiResponse(responseCode = "404", description = "Dossier or file not found.")})
    @PostMapping(value = REST_PATH + "/prepare", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    DownloadResponse prepareDownload(@RequestBody PrepareDownloadRequest request);


    @Operation(summary = "Prepares a download for given fileIds and types and reports", description = "None")
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Success."), @ApiResponse(responseCode = "400", description = "Request contains error."), @ApiResponse(responseCode = "404", description = "Dossier or file not found.")})
    @PostMapping(value = REST_PATH + "/prepare-option", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    DownloadResponse prepareDownload(@RequestBody PrepareDownloadWithOptionRequest request);


    @Operation(summary = "Removes a previously created download status", description = "None")
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Success."), @ApiResponse(responseCode = "404", description = "StorageId does not exist.")})
    @PostMapping(value = REST_PATH + "/delete", consumes = MediaType.APPLICATION_JSON_VALUE)
    void deleteDownloadStatus(@RequestBody RemoveDownloadRequest removeDownloadRequest);


    @Operation(summary = "Gets to download status for the current user", description = "None")
    @ApiResponses(value = {@ApiResponse(responseCode = "204", description = "Success."), @ApiResponse(responseCode = "400", description = "Request contains error."), @ApiResponse(responseCode = "404", description = "Dossier or file not found.")})
    @GetMapping(value = REST_PATH + "/status", produces = MediaType.APPLICATION_JSON_VALUE)
    DownloadStatusResponse getDownloadStatus();


    @ResponseBody
    @ResponseStatus(value = HttpStatus.OK)
    @Operation(summary = "Returns a downloadable byte stream of the requested file")
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Download with this Id is no longer available")})
    @GetMapping(value = REST_PATH)
    void downloadFile(@RequestParam(STORAGE_ID) String storageId);



    @ResponseBody
    @ResponseStatus(value = HttpStatus.OK)
    @Operation(summary = "Returns a oneTimeToken for a requested download", description = "Use the optional \"inline\" request parameter " + "to select, if this report will be opened in the browser.")
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
    @PostMapping(value = REST_PATH + GENERATE_OTT_PATH)
    JSONPrimitive<String> generateOneTimeToken(@RequestBody JSONPrimitive<String> storageIdWrapper);


    @ResponseBody
    @ResponseStatus(value = HttpStatus.OK)
    @Operation(summary = "Returns a downloadable byte stream of the requested file using a valid oneTimeToken")
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Download with this Id is no longer available"), @ApiResponse(responseCode = "400", description = "OTT is not valid")})
    @GetMapping(value = REST_PATH + OTT_PATH + OTT_PATH_VARIABLE)
    void downloadFileUsingOTT(@PathVariable(OTT) String oneTimeToken, @RequestParam(value = "tenantId") String tenantId);

}
