package com.iqser.red.service.persistence.v1.internal.api.controller.internal;

import java.util.stream.Collectors;

import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.iqser.red.service.persistence.management.v1.processor.service.DossierService;
import com.iqser.red.service.persistence.management.v1.processor.service.FileManagementStorageService;
import com.iqser.red.service.persistence.management.v1.processor.service.FileStatusService;
import com.iqser.red.service.persistence.management.v1.processor.settings.FileManagementServiceSettings;
import com.iqser.red.service.persistence.service.v1.api.internal.resources.InternalApi;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileType;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.WorkflowStatus;

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

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping(InternalApi.BASE_PATH+"/admin")
public class AdminInterfaceController {

    private final FileManagementStorageService fileManagementStorageService;
    private final FileStatusService fileStatusService;
    private final FileManagementServiceSettings fileManagementServiceSettings;
    private final DossierService dossierService;
    private final AmqpAdmin amqpAdmin;


    @PostMapping("/reset-file")
    public void resetFile(@RequestParam("dossierId") String dossierId, @RequestParam("fileId") String fileId) {

        fileManagementStorageService.deleteObject(dossierId, fileId, FileType.SECTION_GRID);
        fileManagementStorageService.deleteObject(dossierId, fileId, FileType.REDACTION_LOG);
        fileManagementStorageService.deleteObject(dossierId, fileId, FileType.DOCUMENT_PAGES);
        fileManagementStorageService.deleteObject(dossierId, fileId, FileType.DOCUMENT_TEXT);
        fileManagementStorageService.deleteObject(dossierId, fileId, FileType.DOCUMENT_POSITION);
        fileManagementStorageService.deleteObject(dossierId, fileId, FileType.DOCUMENT_STRUCTURE);
        fileManagementStorageService.deleteObject(dossierId, fileId, FileType.NER_ENTITIES);
        fileManagementStorageService.deleteObject(dossierId, fileId, FileType.FIGURE);
        fileManagementStorageService.deleteObject(dossierId, fileId, FileType.TABLES);

        fileStatusService.setStatusFullReprocess(dossierId, fileId, true, true);

    }


    @PostMapping("/reset-image-info")
    public void resetImageInfo(@RequestParam("dossierId") String dossierId, @RequestParam("fileId") String fileId) {

        if (fileManagementServiceSettings.isImageServiceEnabled()) {
            fileManagementStorageService.deleteObject(dossierId, fileId, FileType.IMAGE_INFO);
            fileStatusService.addToImageQueue(dossierId, fileId);
        }
    }


    @PostMapping("/ocr")
    public void forceOCR(@RequestParam("dossierId") String dossierId, @RequestParam("fileId") String fileId) {

        fileStatusService.setStatusOcrQueued(dossierId, fileId);

    }


    @PostMapping("/ocr-all-files-that-have-already-been-ocrd")
    public void forceOCR(@RequestParam(value = "dryRun", defaultValue = "true") boolean dryRun) {

        if (dryRun) {
            log.info("Dry run!");
        }

        var dossiers = dossierService.getAllDossiers();
        for (var dossier : dossiers) {
            if (!dossier.isDeleted()) {
                var files = fileStatusService.getActiveFiles(dossier.getId());
                var filesThatRequireOCR = files.stream()
                        .filter(f -> !f.isExcluded())
                        .filter(f -> !f.isExcludedFromAutomaticAnalysis())
                        .filter(f -> !f.isSoftOrHardDeleted())
                        .filter(f -> f.getOcrStartTime() != null)
                        .filter(f -> f.getWorkflowStatus() != WorkflowStatus.APPROVED)
                        .collect(Collectors.toList());

                for (var file : filesThatRequireOCR) {
                    log.info("Will OCR file: {} from dossier {} with status {} and processing status {} with last OCR time {}",
                            file.getId(),
                            file.getDossierId(),
                            file.getWorkflowStatus(),
                            file.getProcessingStatus(),
                            file.getOcrStartTime());

                    if (!dryRun) {
                        fileStatusService.setStatusOcrQueued(file.getDossierId(), file.getId());
                    }

                }

            }
        }
    }


    @PostMapping("/reset-text-for-all-files")
    public void resetText(@RequestParam(value = "dryRun", defaultValue = "true") boolean dryRun) {

        if (dryRun) {
            log.info("Dry run!");
        }

        var dossiers = dossierService.getAllDossiers();
        for (var dossier : dossiers) {
            if (!dossier.isDeleted()) {
                var files = fileStatusService.getActiveFiles(dossier.getId());
                var filesThatRequireTextReset = files.stream()
                        .filter(f -> !f.isExcluded())
                        .filter(f -> !f.isExcludedFromAutomaticAnalysis())
                        .filter(f -> !f.isSoftOrHardDeleted())
                        .filter(f -> f.getWorkflowStatus() != WorkflowStatus.APPROVED)
                        .collect(Collectors.toList());

                for (var file : filesThatRequireTextReset) {
                    log.info("Will OCR file: {} from dossier {} with status {} and processing status {} with last OCR time {}",
                            file.getId(),
                            file.getDossierId(),
                            file.getWorkflowStatus(),
                            file.getProcessingStatus(),
                            file.getOcrStartTime());

                    if (!dryRun) {

                        var dossierId = file.getDossierId();
                        var fileId = file.getId();

                        fileManagementStorageService.deleteObject(dossierId, fileId, FileType.SECTION_GRID);
                        fileManagementStorageService.deleteObject(dossierId, fileId, FileType.REDACTION_LOG);
                        fileManagementStorageService.deleteObject(dossierId, fileId, FileType.DOCUMENT_STRUCTURE);
                        fileManagementStorageService.deleteObject(dossierId, fileId, FileType.DOCUMENT_TEXT);
                        fileManagementStorageService.deleteObject(dossierId, fileId, FileType.DOCUMENT_PAGES);
                        fileManagementStorageService.deleteObject(dossierId, fileId, FileType.DOCUMENT_POSITION);
                        fileManagementStorageService.deleteObject(dossierId, fileId, FileType.NER_ENTITIES);

                        fileStatusService.setStatusFullReprocess(dossierId, fileId, true, true);
                    }

                }

            }
        }
    }


    @PostMapping("/flush-queue")
    public void resetText(@RequestParam() String queueName) {

        amqpAdmin.purgeQueue(queueName);
    }

}
