package com.caliverse.admin.dynamodb.repository.Impl;

import com.caliverse.admin.domain.entity.HISTORYTYPE;
import com.caliverse.admin.dynamodb.domain.atrrib.CaliumStorageAttrib;
import com.caliverse.admin.dynamodb.domain.doc.CaliumStorageDoc;
import com.caliverse.admin.dynamodb.repository.BaseDynamoDBRepository;
import com.caliverse.admin.dynamodb.repository.CaliumStorageRepository;
import com.caliverse.admin.dynamodb.service.DynamoDBOperations;
import com.caliverse.admin.global.common.code.CommonCode;
import com.caliverse.admin.global.common.code.ErrorCode;
import com.caliverse.admin.global.common.constants.DynamoDBConstants;
import com.caliverse.admin.global.common.exception.RestApiException;
import com.caliverse.admin.global.common.utils.CommonUtils;
import com.caliverse.admin.history.service.DynamodbHistoryLogService;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import software.amazon.awssdk.enhanced.dynamodb.Key;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;

@Component
@Slf4j
public class CaliumStorageRepositoryImpl extends BaseDynamoDBRepository<CaliumStorageDoc> implements CaliumStorageRepository {
    public CaliumStorageRepositoryImpl(DynamoDBOperations operations, DynamodbHistoryLogService dynamodbHistoryLogService, ObjectMapper objectMapper) {
        super(operations, CaliumStorageDoc.class, dynamodbHistoryLogService, objectMapper);
    }

    @Override
    public double getTotal() {
        double total = 0;

        Key key = Key.builder()
                .partitionValue(DynamoDBConstants.PK_KEY_CALIUM)
                .sortValue(DynamoDBConstants.EMPTY)
                .build();

        CaliumStorageDoc caliumStorageDoc = findById(key);

        total = caliumStorageDoc.getAttribValue().getCaliumOperatorStorage().getOperatorTotalCalium();

        log.info("calium total: {}", total);
        return total;
    }

    @Override
    public void updateTotal(double caliumCnt) {
        try{
            Key key = Key.builder()
                    .partitionValue(DynamoDBConstants.PK_KEY_CALIUM)
                    .sortValue(DynamoDBConstants.EMPTY)
                    .build();

            CaliumStorageDoc beforeDoc = findById(key);

            if (beforeDoc != null) {
                CaliumStorageDoc afterDoc = deepCopy(beforeDoc, CaliumStorageDoc.class);

                CaliumStorageAttrib attrib = afterDoc.getAttribValue();

                String now_data = CommonUtils.convertUTCDate(LocalDateTime.now());
                double currentTotal = attrib.getCaliumOperatorStorage().getOperatorTotalCalium();;
                BigDecimal dclCurrentTotal = new BigDecimal(currentTotal);
                BigDecimal dclCaliumCnt = new BigDecimal(caliumCnt);
                BigDecimal result = dclCurrentTotal.add(dclCaliumCnt);
//                double sumTotal = currentTotal + caliumCnt;   // 부동소수점으로 오차가 발생할수 있다(..000000001)
                result = result.setScale(2, RoundingMode.HALF_UP);;
                log.info("updateTotal currentTotal: {}, newCaliumCnt: {}, total: {}", currentTotal, caliumCnt, result);

                CaliumStorageAttrib.CaliumOperatorStorage caliumOperatorStorage = attrib.getCaliumOperatorStorage();
                caliumOperatorStorage.setOperatorTotalCalium(result.doubleValue());
                caliumOperatorStorage.setOperatorCaliumFillUpDate(now_data);

                attrib.setCaliumOperatorStorage(caliumOperatorStorage);

                afterDoc.setAttribValue(attrib);
                afterDoc.setUpdatedDateTime(now_data);

                update(afterDoc);

                log.info("CaliumStorageDoc Calium Total Update Success: {}", objectMapper.writeValueAsString(afterDoc));

                dynamodbHistoryLogService.updateHistoryLog(
                        HISTORYTYPE.CALIUM_TOTAL_UPDATE,
                        HISTORYTYPE.CALIUM_TOTAL_UPDATE.name(),
                        beforeDoc,
                        afterDoc
                );
            }
        }catch (Exception e){
            throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.DYNAMODB_CONNECTION_ERROR.getMessage());
        }
    }

    @Override
    public void stockDeduction(double caliumCnt) {
        try{
            Key key = Key.builder()
                    .partitionValue(DynamoDBConstants.PK_KEY_CALIUM)
                    .sortValue(DynamoDBConstants.EMPTY)
                    .build();

            CaliumStorageDoc beforeDoc = findById(key);

            if (beforeDoc != null) {
                CaliumStorageDoc afterDoc = deepCopy(beforeDoc, CaliumStorageDoc.class);

                CaliumStorageAttrib attrib = afterDoc.getAttribValue();

                String now_data = CommonUtils.convertUTCDate(LocalDateTime.now());
                double currentTotal = attrib.getCaliumOperatorStorage().getOperatorTotalCalium();;
                BigDecimal dclCurrentTotal = new BigDecimal(currentTotal);
                BigDecimal dclCaliumCnt = new BigDecimal(caliumCnt);
                BigDecimal result = dclCurrentTotal.subtract(dclCaliumCnt);
                result = result.setScale(2, RoundingMode.HALF_UP);;
                log.info("stockDeduction currentTotal: {}, newCaliumCnt: {}, total: {}", currentTotal, caliumCnt, result);

                CaliumStorageAttrib.CaliumOperatorStorage caliumOperatorStorage = attrib.getCaliumOperatorStorage();
                caliumOperatorStorage.setOperatorTotalCalium(result.doubleValue());
                caliumOperatorStorage.setOperatorCaliumFillUpDate(now_data);

                attrib.setCaliumOperatorStorage(caliumOperatorStorage);

                afterDoc.setAttribValue(attrib);
                afterDoc.setUpdatedDateTime(now_data);

                update(afterDoc);

                log.info("CaliumStorageDoc Calium Total Update Success: {}", objectMapper.writeValueAsString(afterDoc));

                dynamodbHistoryLogService.updateHistoryLog(
                        HISTORYTYPE.CALIUM_TOTAL_UPDATE,
                        HISTORYTYPE.CALIUM_TOTAL_UPDATE.name(),
                        beforeDoc,
                        afterDoc
                );
            }
        }catch (Exception e){
            throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.DYNAMODB_CONNECTION_ERROR.getMessage());
        }
    }
}
