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

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

import java.util.Base64;

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

import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.DigitalSignatureEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.DigitalSignatureKmsEntity;
import com.iqser.red.service.persistence.management.v1.processor.service.DigitalSignatureKmsService;
import com.iqser.red.service.persistence.management.v1.processor.service.DigitalSignatureService;
import com.iqser.red.service.persistence.management.v1.processor.service.DigitalSignatureTypeService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.AuditPersistenceService;
import com.iqser.red.service.persistence.service.v1.api.external.resource.DigitalSignatureResource;
import com.iqser.red.service.persistence.service.v1.api.shared.model.AuditCategory;
import com.iqser.red.service.persistence.service.v1.api.shared.model.DigitalSignatureKms;
import com.iqser.red.service.persistence.service.v1.api.shared.model.DigitalSignatureKmsViewModel;
import com.iqser.red.service.persistence.service.v1.api.shared.model.DigitalSignatureViewModel;
import com.iqser.red.service.persistence.service.v1.api.shared.model.audit.AuditRequest;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.configuration.DigitalSignature;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.configuration.DigitalSignatureType;
import com.knecon.fforesight.keycloakcommons.security.KeycloakSecurity;

import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
public class DigitalSignatureController implements DigitalSignatureResource {

    private static final String DIGITAL_SIGNATURE_AUDIT_ID = "DigitalSignature";
    private final DigitalSignatureTypeService digitalSignatureTypeService;
    private final DigitalSignatureService digitalSignatureService;
    private final DigitalSignatureKmsService digitalSignatureKmsService;
    private final AuditPersistenceService auditPersistenceService;


    @Override
    @PreAuthorize("hasAuthority('" + READ_DIGITAL_SIGNATURE + "')")
    public DigitalSignatureType getActiveDigitalSignatureType() {

        return digitalSignatureTypeService.getActiveDigitalSignatureType();
    }


    @Override
    @PreAuthorize("hasAuthority('" + WRITE_DIGITAL_SIGNATURE + "')")
    public void setActiveDigitalSignatureType(DigitalSignatureType digitalSignatureType) {

        digitalSignatureTypeService.setActiveDigitalSignatureType(digitalSignatureType);
        auditPersistenceService.insertRecord(AuditRequest.builder()
                .userId(KeycloakSecurity.getUserId())
                .objectId(DIGITAL_SIGNATURE_AUDIT_ID)
                .category(AuditCategory.SETTINGS.name())
                .message("Digital signature type has been updated.")
                .build());
    }


    @Override
    @PreAuthorize("hasAuthority('" + WRITE_DIGITAL_SIGNATURE + "')")
    public DigitalSignatureViewModel saveDigitalSignature(@RequestBody DigitalSignature digitalSignatureModel) {

        DigitalSignatureViewModel digitalSignatureViewModel = convertToView(digitalSignatureService.saveDigitalSignature(convert(digitalSignatureModel)));
        auditPersistenceService.insertRecord(AuditRequest.builder()
                .userId(KeycloakSecurity.getUserId())
                .objectId(DIGITAL_SIGNATURE_AUDIT_ID)
                .category(AuditCategory.SETTINGS.name())
                .message("Digital signature has been saved.")
                .build());
        return digitalSignatureViewModel;

    }


    @Override
    @PreAuthorize("hasAuthority('" + WRITE_DIGITAL_SIGNATURE + "')")
    public void updateDigitalSignature(@RequestBody DigitalSignatureViewModel digitalSignatureModel) {

        digitalSignatureService.updateDigitalSignature(convert(digitalSignatureModel));
        auditPersistenceService.insertRecord(AuditRequest.builder()
                .userId(KeycloakSecurity.getUserId())
                .objectId(DIGITAL_SIGNATURE_AUDIT_ID)
                .category(AuditCategory.SETTINGS.name())
                .message("Digital signature has been updated.")
                .build());
    }


    @Override
    @PreAuthorize("hasAuthority('" + READ_DIGITAL_SIGNATURE + "')")
    public DigitalSignatureViewModel getDigitalSignature() {

        return convertToView(digitalSignatureService.getDigitalSignature());
    }


    @Override
    @PreAuthorize("hasAuthority('" + WRITE_DIGITAL_SIGNATURE + "')")
    public void deleteDigitalSignature() {

        digitalSignatureService.deleteDigitalSignature();
        auditPersistenceService.insertRecord(AuditRequest.builder()
                .userId(KeycloakSecurity.getUserId())
                .objectId(DIGITAL_SIGNATURE_AUDIT_ID)
                .category(AuditCategory.SETTINGS.name())
                .message("Digital signature has been deleted.")
                .build());
    }


    @Override
    @PreAuthorize("hasAuthority('" + WRITE_DIGITAL_SIGNATURE + "')")
    public DigitalSignatureKmsViewModel saveDigitalSignatureKms(@RequestBody DigitalSignatureKms digitalSignature) {

        DigitalSignatureKmsViewModel result = convert(digitalSignatureKmsService.saveDigitalSignature(digitalSignature));
        auditPersistenceService.insertRecord(AuditRequest.builder()
                .userId(KeycloakSecurity.getUserId())
                .objectId(DIGITAL_SIGNATURE_AUDIT_ID)
                .category(AuditCategory.SETTINGS.name())
                .message("Digital KMS signature has been saved.")
                .build());
        return result;
    }


    @Override
    @PreAuthorize("hasAuthority('" + READ_DIGITAL_SIGNATURE + "')")
    public DigitalSignatureKmsViewModel getDigitalSignatureKms() {

        return convert(digitalSignatureKmsService.getDigitalSignature());
    }


    @Override
    @PreAuthorize("hasAuthority('" + WRITE_DIGITAL_SIGNATURE + "')")
    public void deleteDigitalSignatureKms() {

        digitalSignatureKmsService.deleteDigitalSignature();
        auditPersistenceService.insertRecord(AuditRequest.builder()
                .userId(KeycloakSecurity.getUserId())
                .objectId(DIGITAL_SIGNATURE_AUDIT_ID)
                .category(AuditCategory.SETTINGS.name())
                .message("Digital KMS signature has been deleted.")
                .build());
    }


    private DigitalSignatureKmsViewModel convert(DigitalSignatureKmsEntity digitalSignature) {

        return DigitalSignatureKmsViewModel.builder()
                .kmsAccessKey(digitalSignature.getKmsAccessKey())
                .kmsKeyId(digitalSignature.getKmsKeyId())
                .kmsRegion(digitalSignature.getKmsRegion())
                .kmsServiceEndpoint(digitalSignature.getKmsServiceEndpoint())
                .certificateName(digitalSignature.getCertificateName())
                .build();
    }


    private DigitalSignatureEntity convert(DigitalSignatureViewModel digitalSignature) {

        return DigitalSignatureEntity.builder()
                .certificateName(digitalSignature.getCertificateName())
                .contactInfo(digitalSignature.getContactInfo())
                .location(digitalSignature.getLocation())
                .reason(digitalSignature.getReason())
                .build();
    }


    public DigitalSignatureViewModel convertToView(DigitalSignatureEntity model) {

        return DigitalSignatureViewModel.builder()
                .certificateName(model.getCertificateName())
                .contactInfo(model.getContactInfo())
                .location(model.getLocation())
                .reason(model.getReason())
                .build();
    }


    public DigitalSignatureEntity convert(DigitalSignature digitalSignature) {

        return DigitalSignatureEntity.builder()
                .certificateName(digitalSignature.getCertificateName())
                .contactInfo(digitalSignature.getContactInfo())
                .location(digitalSignature.getLocation())
                .password(digitalSignature.getPassword())
                .reason(digitalSignature.getReason())
                .privateKey(Base64.getDecoder().decode(digitalSignature.getBase64EncodedPrivateKey()))
                .build();
    }

}
