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

import com.caliverse.admin.domain.RabbitMq.message.BannerType;
import com.caliverse.admin.domain.entity.MenuBanner;
import com.caliverse.admin.dynamodb.domain.atrrib.BannerAttrib;
import com.caliverse.admin.dynamodb.domain.doc.BannerDoc;
import com.caliverse.admin.dynamodb.entity.DynamodbOperationResult;
import com.caliverse.admin.dynamodb.entity.ELanguageType;
import com.caliverse.admin.dynamodb.repository.BannerRepository;
import com.caliverse.admin.dynamodb.repository.BaseDynamoDBRepository;
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.mongodb.service.DynamodbHistoryLogService;
import com.fasterxml.jackson.core.JsonProcessingException;
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.HashMap;
import java.util.Map;

import static com.caliverse.admin.global.common.utils.CommonUtils.convertUTCDate;

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

    @Override
    public BannerAttrib findBannerAttrib(Integer bannerId) {
        Key key = Key.builder()
                .partitionValue(DynamoDBConstants.PK_KEY_BANNER)
                .sortValue(bannerId.toString())
                .build();

        BannerDoc doc = findById(key);
        if (doc == null) return null;
        String attribJson = doc.getAttribValue();
        try {
            return objectMapper.readValue(attribJson, BannerAttrib.class);
        } catch (JsonProcessingException e) {
            throw new RestApiException(CommonCode.ERROR.getHttpStatus(),
                    ErrorCode.DYNAMODB_JSON_PARSE_ERROR.getMessage());
        }
    }

    @Override
    public void insertBanner(MenuBanner banner) {
        try {
            LocalDateTime nowDate = LocalDateTime.now();

            Integer banner_id = banner.getId().intValue();

            Map<ELanguageType,String> imageList = new HashMap<>();
            banner.getImageList().forEach(image -> {
                if(image.getTitle().isEmpty()) return;
                ELanguageType languageType = ELanguageType.valueOf(image.getLanguage());
                imageList.put(languageType, image.getTitle());
            });
            Map<ELanguageType,String> linkList = new HashMap<>();
            banner.getImageList().forEach(link -> {
                if(link.getContent().isEmpty()) return;
                ELanguageType languageType = ELanguageType.valueOf(link.getLanguage());
                linkList.put(languageType, link.getContent());
            });

            BannerAttrib attrib = new BannerAttrib();
            attrib.setAttribType(DynamoDBConstants.ATTRIB_BANNER);
            attrib.setBannerId(banner_id);
            attrib.setBannerType(BannerType.BannerType_MainMenu.getNumber());
            attrib.setOrderId(banner.getOrderId());
            attrib.setStartTime(convertUTCDate(banner.getStartDt()));
            attrib.setEndTime(convertUTCDate(banner.getEndDt()));
            attrib.setImageUrl(imageList);
            attrib.setLinkAddress(linkList);

            BannerDoc doc = new BannerDoc();
            doc.setPK(DynamoDBConstants.PK_KEY_BANNER);
            doc.setSK(banner_id.toString());
            doc.setDocType(DynamoDBConstants.DOC_BANNER);
            doc.setAttribValue(objectMapper.writeValueAsString(attrib));
            doc.setCreatedDateTime(convertUTCDate(nowDate));
            doc.setUpdatedDateTime(convertUTCDate(nowDate));
            doc.setDeletedDateTime(DynamoDBConstants.MIN_DATE);
            doc.setRestoredDateTime(DynamoDBConstants.MIN_DATE);

            save(doc);

            log.info("BannerDoc Insert Success: {}", objectMapper.writeValueAsString(doc));

        }catch (Exception e){
            log.error("insert Error: {}", e.getMessage());

            throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.DYNAMODB_CONNECTION_ERROR.getMessage());
        }
    }

    @Override
    public void updateBanner(MenuBanner banner) {
        LocalDateTime nowDate = LocalDateTime.now();

        try {
            Key key = Key.builder()
                    .partitionValue(DynamoDBConstants.PK_KEY_BANNER)
                    .sortValue(banner.getId().toString())
                    .build();

            BannerDoc beforeDoc = findById(key);

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

                BannerAttrib attrib = objectMapper.readValue(afterDoc.getAttribValue(), BannerAttrib.class);
                attrib.setOrderId(banner.getOrderId());
                attrib.setStartTime(convertUTCDate(banner.getStartDt()));
                attrib.setEndTime(convertUTCDate(banner.getEndDt()));

                afterDoc.setAttribValue(objectMapper.writeValueAsString(attrib));
                afterDoc.setUpdatedDateTime(CommonUtils.convertUTCDate(nowDate));

                update(afterDoc);

                log.info("BannerDoc Update Success: {}", objectMapper.writeValueAsString(afterDoc));
            }
        }catch (Exception e){
            log.error("Update Error: {}", e.getMessage());

            throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.DYNAMODB_CONNECTION_ERROR.getMessage());
        }
    }

    @Override
    public DynamodbOperationResult deleteBanner(Integer bannerId) {
        try{
            Key key = Key.builder()
                    .partitionValue(DynamoDBConstants.PK_KEY_BANNER)
                    .sortValue(String.format(bannerId.toString()))
                    .build();
            BannerDoc doc = findById(key);

            if(doc != null) {
                delete(key);

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

                return new DynamodbOperationResult(true, "", doc);
            }
            return new DynamodbOperationResult(true, "null", doc);
        }catch (Exception e){
            log.error("Delete Error: {}", e.getMessage());

            return new DynamodbOperationResult(false, e.getMessage(), null);
        }
    }
}
