package com.caliverse.admin.history.service;

import com.caliverse.admin.domain.entity.EInitDataType;
import com.caliverse.admin.domain.request.LogGenericRequest;
import com.caliverse.admin.dynamodb.domain.doc.DynamoDBDocBase;
import com.caliverse.admin.global.common.constants.AdminConstants;
import com.caliverse.admin.history.domain.DynamodbDataInitializeHistory;
import com.caliverse.admin.history.domain.MysqlDataInitializeHistory;
import com.caliverse.admin.history.repository.DynamodbDataInitializeHistoryRepository;
import com.caliverse.admin.history.repository.MysqlDataInitializeHistoryRepository;
import com.fasterxml.jackson.databind.ObjectMapper;
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.beans.factory.annotation.Value;
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.List;

@Service
@RequiredArgsConstructor
@Slf4j
public class DataInitializeHistoryService {

    private final MysqlDataInitializeHistoryRepository mysqlDataInitializeHistoryRepository;
    private final DynamodbDataInitializeHistoryRepository dynamodbDataInitializeHistoryRepository;
    private final ObjectMapper objectMapper;

    @Autowired
    @Qualifier("mongoAdminTemplate")
    private MongoTemplate mongoTemplate;

    @Value("${amazon.dynamodb.metaTable}")
    private String dynamodbTableName;

    public <T> List<T> loadHistoryData(LogGenericRequest logGenericRequest, Class<T> class1) {
        String startTime = logGenericRequest.getStartDt().toString().substring(0, 10);
        String endTime = logGenericRequest.getEndDt().toString().substring(0, 10);
        String tranId = logGenericRequest.getTranId();

        Criteria criteria = makeCriteria(startTime, endTime);
        List<AggregationOperation> operations = new ArrayList<>();

        operations.add(Aggregation.match(criteria));

        if(tranId != null && !tranId.isEmpty()) {
            operations.add(context ->
                    new Document("$match",
                            new Document(AdminConstants.MONGO_DB_KEY_TRAN_ID, tranId)
                    )
            );
        }

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

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

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

    protected Criteria makeCriteria(String startTime, String endTime) {
        return new Criteria()
                .andOperator(
                        Criteria.where(AdminConstants.MONGO_DB_KEY_TIMESTAMP).gte(startTime).lt(endTime)
                        ,Criteria.where(AdminConstants.MONGO_DB_KEY_DB_TYPE).is("DYNAMODB")
                );
    }

    public <T> void mysqlDataInitHistory(EInitDataType dataType,
                                    String tableName,
                                    String tranId,
                                    boolean isSuccess,
                                    String message,
                                    T data
    ){

        try {
            MysqlDataInitializeHistory history = new MysqlDataInitializeHistory(
                    dataType,
                    tableName,
                    tranId,
                    isSuccess,
                    message,
                    data
            );

            mysqlDataInitializeHistoryRepository.save(history);

        }catch(Exception e){
            log.error("dataInit history Save Error", e);
        }
    }

    public <T> void dynamodbDataInitHistory(EInitDataType dataType,
                                            String tranId,
                                            boolean isSuccess,
                                            String message,
                                            DynamoDBDocBase data,
                                            Object key
    ){

        try {
            DynamodbDataInitializeHistory history = new DynamodbDataInitializeHistory(
                    dataType,
                    dynamodbTableName,
                    tranId,
                    isSuccess,
                    message,
                    data,
                    objectMapper.writeValueAsString(key)
            );

            dynamodbDataInitializeHistoryRepository.save(history);

        }catch(Exception e){
            log.error("dataInit history Save Error", e);
        }
    }

}
