package com.iqser.red.persistence.service.v1.external.api.impl.controller;

import static com.iqser.red.service.persistence.management.v1.processor.roles.ActionRoles.GET_RSS;

import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.knecon.fforesight.keycloakcommons.security.KeycloakSecurity;
import com.iqser.red.service.persistence.management.v1.processor.client.redactionreportservice.RssReportClient;
import com.iqser.red.service.persistence.management.v1.processor.service.ComponentOverrideService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.AuditPersistenceService;
import com.iqser.red.service.persistence.service.v1.api.external.resource.RSSResource;
import com.iqser.red.service.persistence.service.v1.api.shared.model.AuditCategory;
import com.iqser.red.service.persistence.service.v1.api.shared.model.audit.AuditRequest;
import com.iqser.red.service.persistence.service.v1.api.shared.model.component.ComponentsOverrides;
import com.iqser.red.service.persistence.service.v1.api.shared.model.component.RevertOverrideRequest;
import com.iqser.red.service.persistence.service.v1.api.shared.model.rss.RSSFileResponse;
import com.iqser.red.service.persistence.service.v1.api.shared.model.rss.RSSResponse;
import com.iqser.red.service.redaction.report.v1.api.model.rss.DetailedRSSResponse;

import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
public class RSSController implements RSSResource {

    private final RssReportClient rssReportClient;
    private final ComponentOverrideService componentOverrideService;
    private final AuditPersistenceService auditPersistenceService;


    @PreAuthorize("hasAuthority('" + GET_RSS + "')")
    public RSSResponse getRSS(@PathVariable(DOSSIER_ID) String dossierId, @RequestParam(value = "fileId", required = false) String fileId) {

        return convert(rssReportClient.getRSS(dossierId, fileId));

    }


    @PreAuthorize("hasAuthority('" + GET_RSS + "')")
    private RSSResponse convert(com.iqser.red.service.redaction.report.v1.api.model.rss.RSSResponse rssResponse) {

        return new RSSResponse(rssResponse.getFiles().stream().map(this::convert).collect(Collectors.toList()));
    }


    @PreAuthorize("hasAuthority('" + GET_RSS + "')")
    private RSSFileResponse convert(com.iqser.red.service.redaction.report.v1.api.model.rss.RSSFileResponse rssFileResponse) {

        return new RSSFileResponse(rssFileResponse.getFilename(), rssFileResponse.getResult());

    }


    @PreAuthorize("hasAuthority('" + GET_RSS + "')")
    public DetailedRSSResponse getDetailedRSS(@PathVariable(DOSSIER_ID) String dossierId, @RequestParam(value = "fileId", required = false) String fileId) {

        return rssReportClient.getDetailedRSS(dossierId, fileId);
    }


    @PreAuthorize("hasAuthority('" + GET_RSS + "')")
    public void addOverrides(@PathVariable(DOSSIER_ID) String dossierId, @PathVariable(FILE_ID) String fileId, @RequestBody ComponentsOverrides componentsOverrides) {

        var rssReport = rssReportClient.getDetailedRSS(dossierId, fileId);
        var components = rssReport.getFiles().get(0).getResult();

        componentOverrideService.addOverrides(dossierId, fileId, componentsOverrides);

        componentsOverrides.getComponentOverrides()
                .forEach((key, value) -> auditPersistenceService.audit(AuditRequest.builder()
                        .userId(KeycloakSecurity.getUserId())
                        .objectId(fileId)
                        .category(AuditCategory.DOCUMENT.name())
                        .message("The component is overwritten with value")
                        .details(Map.of(DOSSIER_ID,
                                dossierId,
                                FILE_ID,
                                fileId,
                                "ComponentName",
                                key,
                                "Action",
                                "MODIFY",
                                "OriginalValue",
                                components.get(key).getOriginalValue(),
                                "OldValue",
                                components.get(key).getValue() != null ? components.get(key).getValue() : components.get(key).getOriginalValue(),
                                "NewValue",
                                value))
                        .build()));
    }


    @PreAuthorize("hasAuthority('" + GET_RSS + "')")
    public ComponentsOverrides getOverrides(@PathVariable(DOSSIER_ID) String dossierId, @PathVariable(FILE_ID) String fileId) {

        return componentOverrideService.getOverrides(dossierId, fileId);
    }


    @PreAuthorize("hasAuthority('" + GET_RSS + "')")
    public void revertOverrides(@PathVariable(DOSSIER_ID) String dossierId, @PathVariable(FILE_ID) String fileId, @RequestBody RevertOverrideRequest revertOverrideRequest) {

        var rssReport = rssReportClient.getDetailedRSS(dossierId, fileId);
        var components = rssReport.getFiles().get(0).getResult();

        componentOverrideService.revertOverrides(dossierId, fileId, revertOverrideRequest);

        revertOverrideRequest.getComponents()
                .forEach(component -> auditPersistenceService.audit(AuditRequest.builder()
                        .userId(KeycloakSecurity.getUserId())
                        .objectId(fileId)
                        .category(AuditCategory.DOCUMENT.name())
                        .message("The component override for was reverted")
                        .details(Map.of(DOSSIER_ID,
                                dossierId,
                                FILE_ID,
                                fileId,
                                "ComponentName",
                                component,
                                "Action",
                                "REVERT",
                                "OriginalValue",
                                components.get(component).getOriginalValue(),
                                "OldValue",
                                components.get(component).getValue() != null ? components.get(component).getValue() : components.get(component).getOriginalValue(),
                                "NewValue",
                                components.get(component).getOriginalValue()))
                        .build()));
    }

}
