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

import com.iqser.red.persistence.service.v1.external.api.impl.controller.*;
import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException;
import com.iqser.red.service.persistence.service.v1.api.shared.model.FileAttributes;
import com.iqser.red.service.persistence.service.v1.api.shared.model.FileStatus;
import com.iqser.red.service.persistence.service.v1.api.shared.model.FileUploadResult;
import com.iqser.red.service.persistence.service.v2.api.external.model.FileDeleteRequest;
import com.iqser.red.service.persistence.service.v2.api.external.model.FileStatusList;
import com.iqser.red.service.persistence.service.v2.api.external.resource.FileResource;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static com.iqser.red.service.persistence.service.v2.api.external.resource.DossierResource.*;
import static com.iqser.red.service.persistence.service.v2.api.external.resource.DossierTemplateResource.DOSSIER_TEMPLATE_ID_PARAM;

@RestController
@RequiredArgsConstructor
@Tag(name = "3. File endpoints", description = "Provides operations related to files")
public class FileControllerV2 implements FileResource {

    private final UploadController uploadController;
    private final StatusController statusController;
    private final DossierController dossierController;
    private final FileManagementController fileManagementController;
    private final FileAttributesController fileAttributesController;
    private final DossierTemplateController dossierTemplateController;

    public FileUploadResult upload(@PathVariable(DOSSIER_TEMPLATE_ID_PARAM) String dossierTemplateId,
                                   @PathVariable(DOSSIER_ID_PARAM) String dossierId,
                                   @RequestPart(name = FILE_PARAM) MultipartFile file,
                                   @RequestParam(value = KEEP_MANUAL_CHANGES_PARAM, required = false, defaultValue = "false") boolean keepManualChanges) {

        dossierTemplateController.getDossierTemplate(dossierTemplateId);

        return uploadController.upload(file, dossierId, keepManualChanges);
    }

    public FileStatusList getDossierStatus(@PathVariable(DOSSIER_TEMPLATE_ID_PARAM) String dossierTemplateId,
                                           @PathVariable(DOSSIER_ID_PARAM) String dossierId,
                                           @RequestParam(name = INCLUDE_ACTIVE_PARAM, defaultValue = "true", required = false) boolean includeActive,
                                           @RequestParam(name = INCLUDE_ARCHIVED_PARAM, defaultValue = "false", required = false) boolean includeArchived,
                                           @RequestParam(name = INCLUDE_SOFT_DELETED_PARAM, defaultValue = "false", required = false) boolean includeSoftDeleted) {

        dossierTemplateController.getDossierTemplate(dossierTemplateId);

        List<FileStatus> fileStatusList = new ArrayList<>();

        if (!includeArchived && dossierController.getDossier(dossierId, includeArchived, includeSoftDeleted).getArchivedTime() != null) {
            return new FileStatusList(fileStatusList);
        }

        if (includeActive) {
            fileStatusList.addAll(statusController.getDossierStatus(dossierId));
        }

        if (includeSoftDeleted) {
            fileStatusList.addAll(statusController.getSoftDeletedDossierStatus(dossierId));
        }

        return new FileStatusList(fileStatusList);
    }


    public FileStatus getFileStatus(@PathVariable(DOSSIER_TEMPLATE_ID_PARAM) String dossierTemplateId,
                                    @PathVariable(DOSSIER_ID_PARAM) String dossierId,
                                    @PathVariable(FILE_ID_PARAM) String fileId,
                                    @RequestParam(name = INCLUDE_ACTIVE_PARAM, defaultValue = "true", required = false) boolean includeActive,
                                    @RequestParam(name = INCLUDE_ARCHIVED_PARAM, defaultValue = "false", required = false) boolean includeArchived,
                                    @RequestParam(name = INCLUDE_SOFT_DELETED_PARAM, defaultValue = "false", required = false) boolean includeSoftDeleted) {

        dossierTemplateController.getDossierTemplate(dossierTemplateId);

        boolean dossierIsArchived = dossierController.getDossier(dossierId, includeArchived, includeSoftDeleted).getArchivedTime() != null;
        if (!includeArchived && dossierIsArchived) {
            throw new NotFoundException("The requested file does not exist.");
        }

        var status = statusController.getFileStatus(dossierId, fileId);

        if (!includeActive && !dossierIsArchived && status.getSoftDeletedTime() == null) {
            throw new NotFoundException("The requested file does not exist.");
        }

        if (!includeSoftDeleted && status.getSoftDeletedTime() != null) {
            throw new NotFoundException("The requested file does not exist.");
        }

        return status;
    }


    public void deleteFile(@PathVariable(DOSSIER_TEMPLATE_ID_PARAM) String dossierTemplateId,
                           @PathVariable(DOSSIER_ID_PARAM) String dossierId,
                           @PathVariable(FILE_ID_PARAM) String fileId,
                           @RequestParam(name = DELETE_PERMANENTLY_PARAM, defaultValue = "false", required = false) boolean deletePermanently) {

        dossierTemplateController.getDossierTemplate(dossierTemplateId);

        if (deletePermanently) {
            fileManagementController.hardDeleteFiles(dossierId, Set.of(fileId));
        } else {
            fileManagementController.deleteFile(dossierId, fileId);
        }

    }


    public void deleteFiles(@PathVariable(DOSSIER_TEMPLATE_ID_PARAM) String dossierTemplateId,
                            @PathVariable(DOSSIER_ID_PARAM) String dossierId,
                            @RequestBody FileDeleteRequest fileDeleteRequest,
                            @RequestParam(name = DELETE_PERMANENTLY_PARAM, defaultValue = "false", required = false) boolean deletePermanently) {

        dossierTemplateController.getDossierTemplate(dossierTemplateId);

        if (deletePermanently) {
            fileManagementController.hardDeleteFiles(dossierId, new HashSet<>(fileDeleteRequest.getFileIds()));
        } else {
            fileManagementController.deleteFiles(dossierId, fileDeleteRequest.getFileIds());
        }
    }


    public void setFileAttributes(@PathVariable(DOSSIER_TEMPLATE_ID_PARAM) String dossierTemplateId,
                                  @PathVariable(DOSSIER_ID_PARAM) String dossierId,
                                  @PathVariable(FILE_ID_PARAM) String fileId,
                                  @RequestBody FileAttributes fileAttributes) {

        dossierTemplateController.getDossierTemplate(dossierTemplateId);

        fileAttributesController.setFileAttributes(dossierId, fileId, fileAttributes);
    }


}
