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

import com.caliverse.admin.domain.entity.HISTORYTYPEDETAIL;
import com.caliverse.admin.domain.entity.Mail;
import com.caliverse.admin.domain.entity.SEARCHTYPE;
import com.caliverse.admin.domain.entity.metadata.MetaSystemMailData;
import com.caliverse.admin.dynamodb.domain.atrrib.MailJsonAttrib;
import com.caliverse.admin.dynamodb.domain.doc.MailJsonDoc;
import com.caliverse.admin.dynamodb.dto.PageResult;
import com.caliverse.admin.dynamodb.entity.MailItem;
import com.caliverse.admin.dynamodb.repository.BaseDynamoDBRepository;
import com.caliverse.admin.dynamodb.repository.MailJsonRepository;
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.global.common.utils.DateUtils;
import com.caliverse.admin.mongodb.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 software.amazon.awssdk.services.dynamodb.model.AttributeValue;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

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

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

    @Override
    public void insertRecvSystemMail(String userGuid, String nickname, List<MailItem> mailItems, MetaSystemMailData systemMailData, List<String> arguments) {
        try {
            LocalDateTime nowDate = LocalDateTime.now();
            LocalDateTime maxDate = DateUtils.getMaxTime();

            String expireTime = DateUtils.stringToISODateTimeMillisNano(maxDate);

            String pk = DynamoDBConstants.PK_KEY_RECV_MAIL + userGuid;
            String sk = String.format("%s-%s", DateUtils.getMailDateFormat(nowDate), CommonUtils.getCreateGuId().replace("-",""));

            MailJsonAttrib attrib = new MailJsonAttrib();
            attrib.setMailGuid(sk);
            attrib.setRead(false);
            attrib.setGetItem(false);
            attrib.setSystemMail(true);
            attrib.setSenderNickName(systemMailData.getSender());
            attrib.setSenderGuid("");
            attrib.setReceiverNickName(nickname);
            attrib.setReceiverGuid(userGuid);
            attrib.setTitle(systemMailData.getMailTitle());
            attrib.setText(systemMailData.getMailDesc());
            attrib.setExpireTime(expireTime);
            attrib.setCreateTime(DateUtils.stringToISODateTimeMillisNano(nowDate));
            attrib.setTextByMetaData(true);
            attrib.setItemList(mailItems);
            attrib.setPackageOrderId("");
            attrib.setContentsArguments(arguments);

            MailJsonDoc doc = new MailJsonDoc();
            doc.setPK(pk);
            doc.setSK(sk);
            doc.setDocType(DynamoDBConstants.DOC_Mail);
            doc.setAttribValue(objectMapper.writeValueAsString(attrib));
            doc.setCreatedDateTime(convertUTCDate(nowDate));
            doc.setUpdatedDateTime(convertUTCDate(nowDate));
            doc.setDeletedDateTime(DynamoDBConstants.MIN_DATE);
            doc.setRestoredDateTime(DynamoDBConstants.MIN_DATE);
            doc.setTtl(DateUtils.dateToISOUnixTime(maxDate));

            save(doc);

            log.info("MailDoc Recv 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 insertSentMail(Mail mail) {

    }

    @Override
    public List<MailJsonDoc> getMailList(String type, String userGuid, String sortKeyPrefix) {
        String pk;

        if(type.equals(SEARCHTYPE.SEND.name())){
            pk = DynamoDBConstants.PK_KEY_RECV_MAIL + userGuid;
        }else{
            pk = DynamoDBConstants.PK_KEY_SENT_MAIL + userGuid;
        }

        List<MailJsonDoc> mailList = findByPrefix(pk, sortKeyPrefix);

        return mailList;
    }

    @Override
    public PageResult<MailJsonDoc> getMailListWithPaging(
            SEARCHTYPE type,
            String userGuid,
            String sortKeyPrefix,
            Map<String, AttributeValue> exclusiveStartKey
    ) {

        String pk;
        if(type.equals(SEARCHTYPE.SEND)){
            pk = DynamoDBConstants.PK_KEY_SENT_MAIL + userGuid;
        } else {
            pk = DynamoDBConstants.PK_KEY_RECV_MAIL + userGuid;
        }

        return findByPaging(
                pk,
                sortKeyPrefix,
                exclusiveStartKey
        );
    }

    @Override
    public void deleteMail(Key key) {
        try {
            MailJsonDoc beforeDoc = findById(key);

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

                log.info("MailJsonDoc Delete Success: {}", objectMapper.writeValueAsString(beforeDoc));
            }
        }catch (Exception e){
            log.error("Delete Mail Error: {}", e.getMessage());
            throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.DYNAMODB_PROCESS_ERROR.getMessage());
        }
    }

    @Override
    public void deleteMailItem(Key key, Integer itemId, double count, double newCount) {
        try {
            MailJsonDoc beforeDoc = findById(key);

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

                MailJsonAttrib attrib = CommonUtils.stringByObject(afterDoc.getAttribValue(), MailJsonAttrib.class);
                List<MailItem> itemList = attrib.getItemList();
                MailItem selectItem = itemList.stream()
                        .filter(item -> item.getItemId().equals(itemId))
                        .findFirst()
                        .orElse(null);

                if(selectItem == null){
                    throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.DYNAMODB_MAIL_NOT_ITEM_ERROR.toString());
                }

                if (count > newCount) {
                    double updateCount = count - newCount;
                    selectItem.setCount(updateCount);
                } else {
                    itemList.remove(selectItem);
                }

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

                update(afterDoc);

                log.info("MailJsonDoc Item Update Success: {}", objectMapper.writeValueAsString(beforeDoc));
            }
        }catch (Exception e){
            log.error("Update Mail Item Error: {}", e.getMessage());
            throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.DYNAMODB_PROCESS_ERROR.getMessage());
        }
    }
}
