package eu.eudat.publicapi.managers;

import eu.eudat.data.entities.DMP;
import eu.eudat.exceptions.security.ForbiddenException;
import eu.eudat.logic.managers.PaginationManager;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.logic.services.operations.DatabaseRepository;
import eu.eudat.models.HintedModelFactory;
import eu.eudat.models.data.helpers.common.DataTableData;
import eu.eudat.publicapi.models.listingmodels.DataManagementPlanPublicListingModel;
import eu.eudat.publicapi.models.overviewmodels.DataManagementPlanPublicModel;
import eu.eudat.publicapi.request.dmp.DataManagmentPlanPublicTableRequest;
import eu.eudat.queryable.QueryableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.UUID;
import java.util.concurrent.CompletableFuture;

@Component
public class DataManagementPlanPublicManager {
    private static final Logger logger = LoggerFactory.getLogger(DataManagementPlanPublicManager.class);

    private DatabaseRepository databaseRepository;

    @Autowired
    public DataManagementPlanPublicManager(ApiContext apiContext) {
        this.databaseRepository = apiContext.getOperationsContext().getDatabaseRepository();
    }

    public DataTableData<DataManagementPlanPublicListingModel> getPublicPaged(DataManagmentPlanPublicTableRequest dmpTableRequest, String fieldsGroup) throws Exception {
        dmpTableRequest.setQuery(databaseRepository.getDmpDao().asQueryable().withHint(HintedModelFactory.getHint(DataManagementPlanPublicListingModel.class)));
        QueryableList<DMP> items = dmpTableRequest.applyCriteria();
        QueryableList<DMP> pagedItems = PaginationManager.applyPaging(items, dmpTableRequest);

        DataTableData<DataManagementPlanPublicListingModel> dataTable = new DataTableData<>();

        CompletableFuture itemsFuture;
        if (fieldsGroup.equals("listing")) {
            itemsFuture = pagedItems.withHint(HintedModelFactory.getHint(DataManagementPlanPublicListingModel.class))
                    .selectAsync(item -> {
//                        item.setDataset(
//                                item.getDataset().stream()
//                                        .filter(dataset -> dataset.getStatus().equals(Dataset.Status.FINALISED.getValue())).collect(Collectors.toSet()));
                        return new DataManagementPlanPublicListingModel().fromDataModelNoDatasets(item);
                    })
                    .whenComplete((resultList, throwable) -> dataTable.setData(resultList));
        } else {
            itemsFuture = pagedItems
                    .selectAsync(item -> new DataManagementPlanPublicListingModel().fromDataModel(item))
                    .whenComplete((resultList, throwable) -> dataTable.setData(resultList));
        }

        CompletableFuture countFuture = pagedItems.countAsync().whenComplete((count, throwable) -> {
            dataTable.setTotalCount(count);
        });
        CompletableFuture.allOf(itemsFuture, countFuture).join();
        if(dataTable.getTotalCount() > dmpTableRequest.getLength())
            dataTable.setTotalCount((long)dmpTableRequest.getLength());

        return dataTable;
    }

    public DataManagementPlanPublicModel getOverviewSinglePublic(String id) throws Exception {
        DMP dataManagementPlanEntity = databaseRepository.getDmpDao().find(UUID.fromString(id));
        if (dataManagementPlanEntity.getStatus() == DMP.DMPStatus.DELETED.getValue()) {
            throw new Exception("DMP is deleted.");
        }
        if (!dataManagementPlanEntity.isPublic()) {
            throw new ForbiddenException("Selected DMP is not public");
        }
        DataManagementPlanPublicModel datamanagementPlan = new DataManagementPlanPublicModel();
        datamanagementPlan.fromDataModelDatasets(dataManagementPlanEntity);
        datamanagementPlan.setDatasets(datamanagementPlan.getDatasets());

        return datamanagementPlan;
    }
}
