package com.iqser.red.service.persistence.management.v1.processor.service;

import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.stereotype.Service;

import com.iqser.red.service.persistence.management.v1.processor.acl.custom.dossier.DossierACLService;
import com.iqser.red.service.persistence.management.v1.processor.exception.BadRequestException;
import com.iqser.red.service.persistence.management.v1.processor.exception.NotAllowedException;
import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.WorkflowStatus;
import com.knecon.fforesight.keycloakcommons.security.KeycloakSecurity;

import feign.FeignException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Service
@RequiredArgsConstructor
@Slf4j
public class AccessControlService {

    private final FileStatusManagementService fileStatusManagementService;
    private final DossierManagementService dossierManagementService;
    private final DossierACLService dossierACLService;


    public void verifyUserIsReviewer(String dossierId, String fileId) {

        String fileReviewer = getAssignee(dossierId, fileId);

        var isReviewer = KeycloakSecurity.getUserId().equals(fileReviewer);
        if (!isReviewer) {
            throw new NotAllowedException("User must be reviewer of the file.");
        }
    }


    private String getAssignee(String dossierId, String fileId) {

        try {
            return fileStatusManagementService.getFileStatus(fileId).getAssignee();
        } catch (FeignException e) {
            if (e.status() == HttpStatus.NOT_FOUND.value()) {
                throw new NotFoundException("File " + fileId + " dossier " + dossierId + " not found.");
            }
            throw e;
        }
    }


    public void verifyUserIsReviewerOrApprover(String dossierId, String fileId) {

        var dossier = dossierACLService.enhanceDossierWithACLData(dossierManagementService.getDossierById(dossierId, false, false));

        String fileReviewer = getAssignee(dossierId, fileId);

        var isReviewer = KeycloakSecurity.getUserId().equals(fileReviewer);
        var isApprover = dossier.getApproverIds().contains(KeycloakSecurity.getUserId());
        if (!isReviewer && !isApprover) {
            throw new NotAllowedException("User must be reviewer or approver.");
        }
    }


    public void verifyUserIsMemberOrApprover(String dossierId, String userId) {

        var dossier = dossierACLService.enhanceDossierWithACLData(dossierManagementService.getDossierById(dossierId, false, false));

        var isMember = dossier.getMemberIds().contains(userId);
        var isApprover = dossier.getApproverIds().contains(userId);
        if (!isMember && !isApprover) {
            throw new BadRequestException("User must be dossier member or approver.");
        }
    }


    @PostAuthorize("hasPermission(#dossierId, 'Dossier', 'VIEW_OBJECT')")
    public void verifyUserHasViewPermissions(String dossierId) {

    }


    @PostAuthorize("hasPermission(#dossierId, 'Dossier', 'ACCESS_OBJECT')")
    public void verifyUserHasAccessPermissions(String dossierId) {

    }


    @PostAuthorize("hasPermission(#dossierId, 'Dossier', 'APPROVE') || hasPermission(#dossierId, 'Dossier', 'REVIEW')")
    public void verifyUserIsMemberOrApprover(String dossierId) {

    }


    @PostAuthorize("hasPermission(#dossierId, 'Dossier', 'APPROVE')")
    public void verifyUserIsApprover(String dossierId) {

    }


    @PostAuthorize("hasPermission(#dossierId, 'Dossier', 'OWNER')")
    public void verifyUserIsDossierOwner(String dossierId) {

    }


    @PostAuthorize("hasPermission(#dossierId, 'Dossier', 'WRITE')")
    public void verifyWriter(String dossierId) {

    }


    @PostAuthorize("hasPermission(#dossierId, 'Dossier', 'APPROVE') || hasPermission(#dossierId, 'Dossier', 'OWNER')")
    public void verifyUserIsDossierOwnerOrApprover(String dossierId) {

    }


    @PostAuthorize("hasAuthority('RED_MANAGER') || hasPermission(#dossierId, 'Dossier', 'APPROVE') || hasPermission(#dossierId, 'Dossier', 'OWNER')")
    public void verifyUserIsDossierOwnerOrApproverOrManager(String dossierId) {

    }


    public void verifyFileIsNotApproved(String dossierId, String fileId) {

        try {
            var status = fileStatusManagementService.getFileStatus(fileId).getWorkflowStatus();

            if (WorkflowStatus.APPROVED.equals(status)) {
                throw new NotAllowedException("File is already in status APPROVED.");
            }
        } catch (FeignException e) {
            if (e.status() == HttpStatus.NOT_FOUND.value()) {
                throw new NotFoundException("File " + fileId + " dossier " + dossierId + " not found.");
            }
            throw e;
        }
    }

}
