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

import java.util.List;

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
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.RequestPart;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.multipart.MultipartFile;

import com.iqser.red.service.persistence.service.v1.api.shared.model.DownloadResponse;
import com.iqser.red.service.persistence.service.v1.api.shared.model.FileExchangeExportRequest;
import com.iqser.red.service.persistence.service.v1.api.shared.model.FileStatus;
import com.iqser.red.service.persistence.service.v1.api.shared.model.FileStatusFilter;
import com.iqser.red.service.persistence.service.v1.api.shared.model.ImportResponse;
import com.iqser.red.service.persistence.service.v1.api.shared.model.ReanalysisSettings;
import com.iqser.red.service.persistence.service.v1.api.shared.model.ReanalyzeFilesResponse;

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

@ResponseStatus(value = HttpStatus.NO_CONTENT)
public interface SupportResource {

    String REANALYSIS_REST_PATH = ExternalApi.BASE_PATH + "/reanalyze";
    String ERROR_REANALYSIS_REST_PATH = REANALYSIS_REST_PATH + "/error";

    String STATUS_REST_PATH = ExternalApi.BASE_PATH + "/status/filter";
    String FILE_EXCHANGE_REST_PATH = ExternalApi.BASE_PATH + "/file-exchange";
    String DATASET_EXCHANGE = ExternalApi.BASE_PATH + "/dataset-exchange";

    String BULK_REST_PATH = "/bulk";

    String DOSSIER_TEMPLATE_ID = "dossierTemplateId";
    String DOSSIER_ID = "dossierId";
    String FILE_ID = "fileId";

    String DOSSIER_ID_PATH_VARIABLE = "/{" + DOSSIER_ID + "}";
    String FILE_ID_PATH_VARIABLE = "/{" + FILE_ID + "}";
    String DOSSIER_TEMPLATE_DOSSIER_TEMPLATE_ID_PATH_VARIABLE = "/dossierTemplateId/{" + DOSSIER_TEMPLATE_ID + "}";
    String DOSSIER_TEMPLATE_ID_PATH_VARIABLE = "/{" + DOSSIER_TEMPLATE_ID + "}";
    String DOSSIER_DOSSIER_ID_PATH_VARIABLE = "/dossierId/{" + DOSSIER_ID + "}";

    String FALSE = "false";

    String FULL_REANALYSIS_PARAM = "fullReanalysis";
    String RUN_OCR_PARAM = "runOcr";
    String EXPORT = "/export";
    String IMPORT = "/import";


    @ResponseStatus(value = HttpStatus.OK)
    @PostMapping(value = REANALYSIS_REST_PATH + DOSSIER_TEMPLATE_DOSSIER_TEMPLATE_ID_PATH_VARIABLE)
    @Operation(summary = "Reanalyze all files in dossier template", description = """
            ## Reanalyze Files Endpoint
            
            Use this endpoint to reanalyze all files in a specified Dossier Template. The reanalysis process can be tailored using various filtering options provided in the request body.
            
            ### Parameters
            
            - **DossierTemplateId**: Specifies the Dossier Template whose files need to be reanalyzed.
            
            ### Request Body Configuration Options
            
            - **dossierIds**: List of dossier IDs to filter. If empty, all dossiers are selected for reanalysis.
            - **fileIds**: List of file IDs to filter. If empty, all files are selected for reanalysis.
            - **repeatStructureAnalysis**: Boolean. If true, layout parsing and named entity recognition will be repeated.
            - **fileStatusFilter**: Use this to create a filter for files to reanalyze. Matches any file if set to null.
            """)
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "403", description = "Forbidden")})
    ReanalyzeFilesResponse reanalyzeFiles(@PathVariable(DOSSIER_TEMPLATE_ID) String dossierTemplateId, @RequestBody ReanalysisSettings reanalysisSettings);


    @PostMapping(value = ERROR_REANALYSIS_REST_PATH)
    @Operation(summary = "Reanalyze all files in error state.", description = "None")
    @ApiResponses(value = {@ApiResponse(responseCode = "204", description = "OK"), @ApiResponse(responseCode = "403", description = "Forbidden")})
    void reanalyzeAllRelevantErrorFiles(@RequestParam(value = FULL_REANALYSIS_PARAM, required = false, defaultValue = FALSE) boolean repeatStructureAnalysis,
                                        @RequestParam(value = RUN_OCR_PARAM, required = false, defaultValue = FALSE) boolean runOcr);


    @PostMapping(value = ERROR_REANALYSIS_REST_PATH + DOSSIER_ID_PATH_VARIABLE + BULK_REST_PATH)
    @Operation(summary = "Reanalyze multiple files in error state for a dossier.", description = "None")
    @ApiResponses(value = {@ApiResponse(responseCode = "204", description = "OK"), @ApiResponse(responseCode = "404", description = "Not found"), @ApiResponse(responseCode = "403", description = "Forbidden")})
    void reanalyzeErrorFilesBulkForDossier(@PathVariable(DOSSIER_ID) String dossierId,
                                           @RequestBody List<String> fileIds,
                                           @RequestParam(value = FULL_REANALYSIS_PARAM, required = false, defaultValue = FALSE) boolean repeatStructureAnalysis,
                                           @RequestParam(value = RUN_OCR_PARAM, required = false, defaultValue = FALSE) boolean runOcr);


    @ResponseStatus(value = HttpStatus.OK)
    @ResponseBody
    @PostMapping(value = STATUS_REST_PATH, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
    @Operation(summary = "Get the filtered status for all files in the workspace.", description = "None")
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
    List<FileStatus> getFileStatus(@RequestBody FileStatusFilter fileStatusFilter);


    @ResponseStatus(value = HttpStatus.OK)
    @ResponseBody
    @PostMapping(value = STATUS_REST_PATH
                         + DOSSIER_TEMPLATE_DOSSIER_TEMPLATE_ID_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
    @Operation(summary = "Get the filtered status for all files in a dossier template.", description = "None")
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
    List<FileStatus> getFileStatusForDossierTemplate(@PathVariable(DOSSIER_TEMPLATE_ID) String dossierTemplateId, @RequestBody FileStatusFilter fileStatusFilter);


    @ResponseStatus(value = HttpStatus.OK)
    @ResponseBody
    @PostMapping(value = STATUS_REST_PATH + DOSSIER_DOSSIER_ID_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
    @Operation(summary = "Get the filtered status for all files in a dossier.", description = "None")
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
    List<FileStatus> exportFiles(@PathVariable(DOSSIER_ID) String dossierId, @RequestBody FileStatusFilter fileStatusFilter);


    @ResponseStatus(value = HttpStatus.OK)
    @ResponseBody
    @PostMapping(value = FILE_EXCHANGE_REST_PATH
                         + EXPORT
                         + DOSSIER_TEMPLATE_ID_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
    @Operation(summary = "Exports all dossiers and files from a given Dossier Template.", description = """
            ## Export Files Endpoint
            
            Use this endpoint to export a full Dossier Template, including all configurations, dossiers, and files.
            The endpoint returns a String storageId, which is used to query the DownloadController for the export zip archive's status and to download the archive.
            
            ### Parameters
            
            - **DossierTemplateId**: Specifies the Dossier Template to be exported.
            
            ### Request Body Configuration Options
            
            - **dossierIds**: List of dossier IDs to filter. If empty, all dossiers are selected.
            - **fileIds**: List of file IDs to filter. If empty, all files are selected.
            - **excludeLayoutFiles**: Boolean. If true, excludes DOCUMENT_STRUCTURE/_PAGES/_TEXT/_POSITIONS, SIMPLIFIED_TEXT, and NER_ENTITIES files.
            - **excludeManualRedactions**: Boolean. If true, excludes MANUAL_REDACTIONS files.
            - **excludeAnalysisLogs**: Boolean. If true, excludes ENTITY_LOG and COMPONENT_LOG (with overrides) files.
            - **excludeFileAttributes**: Boolean. If true, excludes file attributes.
            - **originFileOnly**: Boolean. If true, exports only the origin file, ignoring untouched and viewer documents.""")
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
    DownloadResponse exportFiles(@PathVariable(DOSSIER_TEMPLATE_ID) String dossierTemplateId, @RequestBody FileExchangeExportRequest exportRequest);


    @ResponseStatus(value = HttpStatus.OK)
    @ResponseBody
    @PostMapping(value = DATASET_EXCHANGE + EXPORT + DOSSIER_TEMPLATE_ID_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE)
    @Operation(summary = "Exports all dossiers and files from a given Dossier Template.", description = """
            ## Export Preview Files Endpoint
            
            Use this endpoint to export all files of a DossierTemplate as a Preview file containing all applied annotations as redaction annotations with additional data
            The endpoint returns a String storageId, which is used to query the DownloadController for the export zip archive's status and to download the archive.
            """)
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
    DownloadResponse exportDataset(@PathVariable(DOSSIER_TEMPLATE_ID) String dossierTemplateId);


    @ResponseBody
    @ResponseStatus(value = HttpStatus.OK)
    @PostMapping(value = FILE_EXCHANGE_REST_PATH + IMPORT, consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    @Operation(summary = "Imports a file exchange export zip.", description = "Use this endpoint to import a full export of a given Dossier Template including all its configurations, dossiers, and files. Returns the resulting dossierTemplateId.")
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
    ImportResponse importFiles(@Schema(type = "string", format = "binary", name = "file") @RequestPart(name = "file") MultipartFile file);


    @ResponseBody
    @ResponseStatus(value = HttpStatus.OK)
    @PostMapping(value = DATASET_EXCHANGE + IMPORT, consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    @Operation(summary = "Imports a file exchange export zip.", description = "Use this endpoint to import a full export of a given Dossier Template including all its configurations, dossiers, and files. Returns the resulting dossierTemplateId.")
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
    ImportResponse importDataset(@Schema(type = "string", format = "binary", name = "file") @RequestPart(name = "file") MultipartFile file);

}
