package com.caliverse.admin.Indicators.Indicatorsservice.aggregationservice;

import com.caliverse.admin.Indicators.Indicatordomain.IndicatorsLog;
import com.caliverse.admin.Indicators.Indicatorsservice.base.IndicatorsLogLoadServiceBase;
import com.caliverse.admin.global.common.constants.AdminConstants;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class IndicatorsCurrencyLoadService extends IndicatorsLogLoadServiceBase {
    public IndicatorsCurrencyLoadService(
            @Qualifier("mongoIndicatorTemplate") MongoTemplate mongoTemplate
    ) {
        super(mongoTemplate);
    }

    @Override
    public <T extends IndicatorsLog> List<T> getIndicatorsLogData(String startTime, String endTime, Class<T> clazz) {

        return getCurrencyLogData(startTime, endTime, "Acquire", clazz);
    }

    public <T extends IndicatorsLog> List<T> getCurrencyLogData(String startTime, String endTime, String deltaType, Class<T> clazz) {

        Criteria criteria = makeCriteria(startTime, endTime, "logDay");

        UnwindOperation unwindOperation = Aggregation.unwind("currencies");

        MatchOperation matchOp = Aggregation.match(
                Criteria.where("currencies.amountDeltaType").is(deltaType)
        );

        AggregationOperation groupOp = context -> new Document("$group",
                new Document("_id", new Document("logDay", "$logDay")
                        .append("currencyType", "$currencies.currencyType")
                        .append("action", "$currencies.action")
                )
                        .append("actionAmount", new Document("$sum", "$currencies.deltaAmount"))
        );

        AggregationOperation groupOp2 = context -> new Document("$group",
                new Document("_id", new Document("logDay", "$_id.logDay")
                        .append("currencyType", "$_id.currencyType")
                )
                        .append("totalDeltaAmount", new Document("$sum", "$actionAmount"))
                        .append("actions", new Document("$push",
                                new Document("k", "$_id.action").append("v", "$actionAmount")
                        ))
        );

        AddFieldsOperation addFieldsOp = Aggregation.addFields()
                .addField("actionSummary")
                .withValue(ArrayOperators.ArrayToObject.arrayToObject("$actions"))
                .build();

        AggregationOperation projectOp = context -> new Document("$project", new Document()
                .append("_id", 0)
                .append("logDay", "$_id.logDay")
                .append("currencyType", "$_id.currencyType")
                .append("totalDeltaAmount", 1)
                .append("actionSummary", 1)
        );

        List<AggregationOperation> operations = List.of(
                Aggregation.match(criteria),
                unwindOperation,
                matchOp,
                groupOp,
                groupOp2,
                addFieldsOp,
                projectOp,
                Aggregation.sort(Sort.Direction.ASC, AdminConstants.MONGO_DB_KEY_LOGDAY)
        );

        Aggregation aggregation = Aggregation.newAggregation(operations);

        return mongoTemplate.aggregate(
                aggregation.withOptions(AggregationOptions.builder().allowDiskUse(true).build())
                , AdminConstants.MONGO_DB_COLLECTION_CURRENCY
                , clazz
        ).getMappedResults();
    }
}
