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

import static com.iqser.red.service.persistence.service.v2.api.external.resource.DossierResource.DOSSIER_ID_PARAM;
import static com.iqser.red.service.persistence.service.v2.api.external.resource.DossierResource.DOSSIER_ID_PATH_PARAM;
import static com.iqser.red.service.persistence.service.v2.api.external.resource.DossierResource.DOSSIER_PATH;
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 static com.iqser.red.service.persistence.service.v2.api.external.resource.FileResource.FILE_ID_PARAM;
import static com.iqser.red.service.persistence.service.v2.api.external.resource.FileResource.FILE_ID_PATH_VARIABLE;

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
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.component.RevertOverrideRequest;
import com.iqser.red.service.persistence.service.v2.api.external.model.BulkComponentsRequest;
import com.iqser.red.service.persistence.service.v2.api.external.model.Component;
import com.iqser.red.service.persistence.service.v2.api.external.model.ComponentOverrideList;
import com.iqser.red.service.persistence.service.v2.api.external.model.FileComponents;
import com.iqser.red.service.persistence.service.v2.api.external.model.FileComponentsList;

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.")})
@ResponseStatus(value = HttpStatus.OK)
public interface ComponentResource {

    String PATH = ExternalApiConstants.BASE_PATH + DOSSIER_TEMPLATE_PATH + DOSSIER_TEMPLATE_ID_PATH_VARIABLE;
    String FILE_PATH = PATH + DOSSIER_PATH + DOSSIER_ID_PATH_PARAM + FileResource.FILE_PATH;

    String COMPONENTS_PATH = "/components";

    String BULK_COMPONENTS_PATH = "/bulk/get-components";

    String INCLUDE_DETAILS_PARAM = "includeDetails";

    String INCLUDE_DETAILS_DESCRIPTION = """
            A toggle to decide whether to include detailed component information in the response:
                        
            - true: The component object's field componentDetails stores detailed information about the source of its respective value(s).
            - false (default): The component object does not contain a field componentDetails.
            """;

    String OVERRIDES_PATH = "/overrides";
    String REVERT_PATH = "/revert";

    String COMPONENT_OVERRIDE_PARAM = "componentOverride";
    String REVERT_OVERRIDE_PARAM = "revertOverride";


    @GetMapping(value = FILE_PATH + FILE_ID_PATH_VARIABLE + COMPONENTS_PATH, produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
    @Operation(summary = "Returns the components for a file", description = "None")
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
    FileComponents getComponents(@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 that contains the file.", required = true) @PathVariable(DOSSIER_ID_PARAM) String dossierId,
                                 @Parameter(name = FILE_ID_PARAM, description = "The identifier of the file that the components are requested for.", required = true) @PathVariable(FILE_ID_PARAM) String fileId,
                                 @Parameter(name = INCLUDE_DETAILS_PARAM, description = INCLUDE_DETAILS_DESCRIPTION) @RequestParam(name = INCLUDE_DETAILS_PARAM, defaultValue = "false", required = false) boolean includeDetails);


    @GetMapping(value = FILE_PATH + BULK_COMPONENTS_PATH, produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
    @Operation(summary = "Returns the components for all files of a dossier", description = "None")
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
    FileComponentsList getComponentsOfDossier(@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 that contains the file.", required = true) @PathVariable(DOSSIER_ID_PARAM) String dossierId,
                                              @Parameter(name = INCLUDE_DETAILS_PARAM, description = INCLUDE_DETAILS_DESCRIPTION) @RequestParam(name = INCLUDE_DETAILS_PARAM, defaultValue = "false", required = false) boolean includeDetails);


    @PostMapping(value = FILE_PATH
                         + BULK_COMPONENTS_PATH, produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}, consumes = MediaType.APPLICATION_JSON_VALUE)
    @Operation(summary = "Returns the components for all files of a dossier", description = "None")
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
    FileComponentsList getComponentsForFiles(@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 that contains the file.", required = true) @PathVariable(DOSSIER_ID_PARAM) String dossierId,
                                             @Parameter(name = INCLUDE_DETAILS_PARAM, description = INCLUDE_DETAILS_DESCRIPTION) @RequestParam(name = INCLUDE_DETAILS_PARAM, defaultValue = "false", required = false) boolean includeDetails,
                                             @RequestBody BulkComponentsRequest bulkComponentsRequest);


    @ResponseBody
    @ResponseStatus(value = HttpStatus.NO_CONTENT)
    @PostMapping(value = FILE_PATH + FILE_ID_PATH_VARIABLE + OVERRIDES_PATH, consumes = MediaType.APPLICATION_JSON_VALUE)
    @Operation(summary = "Adds overrides for components", description = "None")
    @ApiResponses(value = {@ApiResponse(responseCode = "204", description = "OK"), @ApiResponse(responseCode = "404", description = "Not found"), @ApiResponse(responseCode = "403", description = "Forbidden")})
    void addOverride(@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 that contains the file.", required = true) @PathVariable(DOSSIER_ID_PARAM) String dossierId,
                     @Parameter(name = FILE_ID_PARAM, description = "The identifier of the file that the components are requested for.", required = true) @PathVariable(FILE_ID_PARAM) String fileId,
                     @Parameter(name = COMPONENT_OVERRIDE_PARAM, description = "The object to override the component.", required = true) @RequestBody Component componentOverrideModel);


    @ResponseBody
    @ResponseStatus(value = HttpStatus.OK)
    @GetMapping(value = FILE_PATH + FILE_ID_PATH_VARIABLE + OVERRIDES_PATH, produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
    @Operation(summary = "Gets overrides for components", description = "None")
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Not found")})
    ComponentOverrideList getOverrides(@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 that contains the file.", required = true) @PathVariable(DOSSIER_ID_PARAM) String dossierId,
                                       @Parameter(name = FILE_ID_PARAM, description = "The identifier of the file that the components are requested for.", required = true) @PathVariable(FILE_ID_PARAM) String fileId);


    @ResponseBody
    @ResponseStatus(value = HttpStatus.NO_CONTENT)
    @PostMapping(value = FILE_PATH + FILE_ID_PATH_VARIABLE + OVERRIDES_PATH + REVERT_PATH, consumes = MediaType.APPLICATION_JSON_VALUE)
    @Operation(summary = "Reverts overrides for components", description = "None")
    @ApiResponses(value = {@ApiResponse(responseCode = "204", description = "OK"), @ApiResponse(responseCode = "404", description = "Not found"), @ApiResponse(responseCode = "403", description = "Forbidden")})
    void revertOverrides(@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 that contains the file.", required = true) @PathVariable(DOSSIER_ID_PARAM) String dossierId,
                         @Parameter(name = FILE_ID_PARAM, description = "The identifier of the file that the components are requested for.", required = true) @PathVariable(FILE_ID_PARAM) String fileId,
                         @Parameter(name = REVERT_OVERRIDE_PARAM) @RequestBody RevertOverrideRequest revertOverrideRequest);

}
