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

import com.caliverse.admin.domain.entity.HISTORYTYPE;
import com.caliverse.admin.domain.request.LandRequest;
import com.caliverse.admin.dynamodb.domain.atrrib.LandAuctionActivityAttrib;
import com.caliverse.admin.dynamodb.domain.doc.LandAuctionActivityDoc;
import com.caliverse.admin.dynamodb.domain.doc.LandAuctionRegistryDoc;
import com.caliverse.admin.dynamodb.entity.DynamodbOperationResult;
import com.caliverse.admin.dynamodb.repository.BaseDynamoDBRepository;
import com.caliverse.admin.dynamodb.repository.LandAuctionActivityRepository;
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.time.LocalDateTime;
import java.util.List;

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

    @Override
    public void upsertActivity(LandRequest landRequest) {
        Key key = Key.builder()
                .partitionValue(DynamoDBConstants.PK_KEY_LAND_AUCTION_ACTIVE)
                .sortValue(landRequest.getLandId().toString())
                .build();

        LandAuctionActivityDoc doc = findById(key);

        if (doc == null) {
            insertLandAuctionActive(landRequest);
        }else{
            updateLandAuctionActive(landRequest, doc);
        }
    }

    @Override
    public int findAuctionNumber(Integer landId) {
        Key key = Key.builder()
                .partitionValue(DynamoDBConstants.PK_KEY_LAND_AUCTION_ACTIVE)
                .sortValue(landId.toString())
                .build();

        LandAuctionActivityDoc doc = findById(key);
        if(doc == null) return 0;
        LandAuctionActivityAttrib attrib = doc.getAttribValue();

        return attrib.getAuctionNumber();
    }

    @Override
    public DynamodbOperationResult initLandAuctionActivity(Integer landId, Integer auctionSeq) {
        try{
            Key key = Key.builder()
                    .partitionValue(DynamoDBConstants.PK_KEY_LAND_AUCTION_ACTIVE)
                    .sortValue(landId.toString())
                    .build();
            LandAuctionActivityDoc doc = findById(key);

            if(doc != null && doc.getAttribValue().getAuctionNumber().equals(auctionSeq)) {
                delete(key);

                log.info("LandAuctionActivityDoc Delete Success: {}", objectMapper.writeValueAsString(doc));

                dynamodbHistoryLogService.deleteHistoryLog(
                        HISTORYTYPE.LAND_AUCTION_INITIALIZE,
                        HISTORYTYPE.LAND_AUCTION_INITIALIZE.name(),
                        doc
                );

                return new DynamodbOperationResult(true, "delete success", doc);
            }
            return new DynamodbOperationResult(true, "null", doc);
        }catch (Exception e){
            log.error("Init LandAuctionActivity Error: {}", e.getMessage());
            return new DynamodbOperationResult(false, e.getMessage(), null);
        }
    }

    private void insertLandAuctionActive(LandRequest landRequest){
        try {
            LocalDateTime nowDate = LocalDateTime.now();

            LandAuctionActivityAttrib attrib = new LandAuctionActivityAttrib();
            attrib.setLandMetaId(landRequest.getLandId());
            attrib.setAuctionNumber(landRequest.getAuctionSeq());

            LandAuctionActivityDoc activityDoc = new LandAuctionActivityDoc();
            activityDoc.setPK(DynamoDBConstants.PK_KEY_LAND_AUCTION_ACTIVE);
            activityDoc.setSK(landRequest.getLandId().toString());
            activityDoc.setDocType(DynamoDBConstants.DOC_LANDAUCTION_ACTIVE);
            activityDoc.setAttribValue(attrib);
            activityDoc.setCreatedDateTime(CommonUtils.convertUTCDate(nowDate));
            activityDoc.setUpdatedDateTime(CommonUtils.convertUTCDate(nowDate));

            save(activityDoc);

            log.info("LandAuctionActivityDoc Insert Success: {}", objectMapper.writeValueAsString(activityDoc));

            dynamodbHistoryLogService.insertHistoryLog(
                    HISTORYTYPE.LAND_AUCTION_ADD,
                    HISTORYTYPE.LAND_AUCTION_ADD.name(),
                    activityDoc
            );
        }catch (Exception e){
            throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.DYNAMODB_CONNECTION_ERROR.getMessage());
        }
    }

    private void updateLandAuctionActive(LandRequest landRequest, LandAuctionActivityDoc existingDoc){
        try {
            LandAuctionActivityDoc afterDoc = deepCopy(existingDoc, LandAuctionActivityDoc.class);

            LandAuctionActivityAttrib attrib = afterDoc.getAttribValue();
            attrib.setAuctionNumber(landRequest.getAuctionSeq());

            afterDoc.setAttribValue(attrib);
            afterDoc.setUpdatedDateTime(CommonUtils.convertUTCDate(LocalDateTime.now()));

            update(afterDoc);

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

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