package com.caliverse.admin.mongodb.service;

import com.caliverse.admin.domain.entity.FieldChange;
import com.caliverse.admin.domain.entity.HISTORYTYPEDETAIL;
import com.caliverse.admin.domain.entity.log.LogStatus;
import com.caliverse.admin.dynamodb.domain.doc.DynamoDBDocBase;
import com.caliverse.admin.global.common.constants.CommonConstants;
import com.caliverse.admin.global.common.utils.CommonUtils;
import com.caliverse.admin.global.component.manager.TransactionIdManager;
import com.caliverse.admin.mongodb.ChangeDetector;
import com.caliverse.admin.mongodb.entity.EDBOperationType;
import com.caliverse.admin.mongodb.repository.DynamodbHistoryLogRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;

@Service
@RequiredArgsConstructor
@Slf4j
public class DynamodbHistoryLogService {
    @Value("${amazon.dynamodb.metaTable}")
    private String tableName;

    private final TransactionIdManager transactionIdManager;
    private final BusinessLogService businessLogService;

    public void insertHistoryLog(LogStatus logStatus,
                                 String message,
                                 DynamoDBDocBase metadata
    ){

        List<FieldChange> changes = ChangeDetector.detectInsertChanges(metadata);

        if(!changes.isEmpty()) {
            CompletableFuture<String> logFuture = businessLogService.logDynamodb(
                    tableName,
                    EDBOperationType.INSERT,
                    CommonUtils.getAdmin() == null ? CommonConstants.SYSTEM : CommonUtils.getAdmin().getEmail(),
                    CommonUtils.getClientIp() == null ? CommonConstants.SYSTEM : CommonUtils.getClientIp(),
                    metadata,
                    logStatus,
                    changes,
                    message,
                    transactionIdManager.getCurrentTransactionId()
            );

            logFuture.whenComplete((result, throwable) -> {
               if (throwable != null) {
                   log.warn("Business log failed for info: {}, error: {}", CommonUtils.objectByString(metadata), throwable.getMessage());
               }
            });
        }
    }

    public void updateHistoryLog(LogStatus logStatus,
                                 String message,
                                 DynamoDBDocBase beforeMetadata,
                                 DynamoDBDocBase afterMetadata
    ){
        List<FieldChange> changes = ChangeDetector.detectChanges(
                beforeMetadata,
                afterMetadata
        );

        if(!changes.isEmpty()) {
            CompletableFuture<String> logFuture = businessLogService.logDynamodb(
                    tableName,
                    EDBOperationType.UPDATE,
                    CommonUtils.getAdmin() == null ? CommonConstants.SYSTEM : CommonUtils.getAdmin().getEmail(),
                    CommonUtils.getClientIp() == null ? CommonConstants.SYSTEM : CommonUtils.getClientIp(),
                    afterMetadata,
                    logStatus,
                    changes,
                    message,
                    transactionIdManager.getCurrentTransactionId()
            );

            logFuture.whenComplete((result, throwable) -> {
                if (throwable != null) {
                    log.warn("Business log failed for info: {}, error: {}", CommonUtils.objectByString(afterMetadata), throwable.getMessage());
                }
            });
        }
    }

    public void deleteHistoryLog(LogStatus logStatus,
                                 String message,
                                 DynamoDBDocBase metadata
    ){

        List<FieldChange> changes = ChangeDetector.detectDeleteChanges(metadata);

        if(!changes.isEmpty()) {
            CompletableFuture<String> logFuture = businessLogService.logDynamodb(
                    tableName,
                    EDBOperationType.DELETE,
                    CommonUtils.getAdmin() == null ? CommonConstants.SYSTEM : CommonUtils.getAdmin().getEmail(),
                    CommonUtils.getClientIp() == null ? CommonConstants.SYSTEM : CommonUtils.getClientIp(),
                    metadata,
                    logStatus,
                    changes,
                    message,
                    transactionIdManager.getCurrentTransactionId()
            );

            logFuture.whenComplete((result, throwable) -> {
                if (throwable != null) {
                    log.warn("Business log failed for info: {}, error: {}", CommonUtils.objectByString(metadata), throwable.getMessage());
                }
            });
        }
    }
}
