package com.caliverse.admin.mongodb.service;

import com.caliverse.admin.domain.entity.HISTORYTYPEDETAIL;
import com.caliverse.admin.domain.entity.log.LogAction;
import com.caliverse.admin.domain.entity.log.LogCategory;
import com.caliverse.admin.domain.request.HistoryRequest;
import com.caliverse.admin.global.common.constants.AdminConstants;
import com.caliverse.admin.mongodb.entity.DBType;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@RequiredArgsConstructor
@Service
@Slf4j
public class HistoryLogService {
    @Autowired
    @Qualifier("mongoIndicatorTemplate")
    private MongoTemplate mongoTemplate;

    public <T> List<T> loadHistoryData(HistoryRequest historyRequest, Class<T> class1) {
        String startTime = historyRequest.getStartDt() != null ? historyRequest.getStartDt().toString() : "";
        String endTime = historyRequest.getEndDt() != null ? historyRequest.getEndDt().toString() : "";
        LogCategory category = historyRequest.getCategory() != null ? historyRequest.getCategory() : null;
        LogAction action = historyRequest.getAction() != null ? historyRequest.getAction() : null;
        String user = historyRequest.getUserMail() != null ? historyRequest.getUserMail() : "";
        String status = historyRequest.getStatus() != null ? historyRequest.getStatus() : "";

        List<AggregationOperation> operations = new ArrayList<>();
        Criteria criteria = null;

        operations.add(context ->
                new Document("$addFields",
                        new Document("logTimeString",
                                new Document("$dateToString",
                                    new Document("format", "%Y-%m-%d")
                                            .append("date", "$logTime")
                            )
                        )
                )
        );

        if(!startTime.isEmpty() && !endTime.isEmpty()) {
            criteria = makeCriteria(startTime, endTime);
            operations.add(Aggregation.match(criteria));
        }

        if(action != null) {
            operations.add(context ->
                    new Document("$match",
                            new Document(AdminConstants.MONGO_DB_KEY_CATEGORY, category)
                    )
            );
        }

        if(action != null) {
            operations.add(context ->
                    new Document("$match",
                            new Document(AdminConstants.MONGO_DB_KEY_ACTION, action)
                    )
            );
        }

        if(!user.isEmpty()) {
            operations.add(context ->
                    new Document("$match",
                            new Document(AdminConstants.MONGO_DB_KEY_WORKER, user)
                    )
            );
        }

        if(!user.isEmpty()) {
            operations.add(context ->
                    new Document("$match",
                            new Document(AdminConstants.MONGO_DB_KEY_STATUS, status)
                    )
            );
        }

        if(historyRequest.getTableName() != null && !historyRequest.getTableName().isEmpty()){
            operations.add(context ->
                    new Document("$match",
                            new Document()
                                    .append("category", LogCategory.MARIADB)
                                    .append("domain.tableName", historyRequest.getTableName())
                                    .append("domain.data._id", historyRequest.getSqlId())
                    )
            );
        }

        // 최종 출력 형식
        operations.add(context ->
                new Document("$sort",
                        new Document(AdminConstants.MONGO_DB_KEY_LOGTIME, -1)
                )
        );

        Aggregation aggregation = Aggregation.newAggregation(operations);
        log.info("loadHistoryData Query: {}", aggregation);

        AggregationResults<T> results = mongoTemplate.aggregate(aggregation, AdminConstants.MONGO_DB_COLLECTION_BUSINESS_LOG, class1);
        return results.getMappedResults();
    }

    protected Criteria makeCriteria(String startTime, String endTime) {
        return new Criteria()
                .andOperator(
                        Criteria.where("logTimeString").gte(startTime).lte(endTime)
                );
    }
}
