package com.caliverse.admin.dynamodb.service;

import com.caliverse.admin.domain.datacomponent.MetaDataHandler;
import com.caliverse.admin.domain.entity.RewardEvent;
import com.caliverse.admin.domain.entity.SEARCHTYPE;
import com.caliverse.admin.domain.entity.metadata.MetaLandData;
import com.caliverse.admin.domain.entity.metadata.MetaSystemMailData;
import com.caliverse.admin.domain.request.LandRequest;
import com.caliverse.admin.dynamodb.domain.atrrib.*;
import com.caliverse.admin.dynamodb.domain.doc.MailDoc;
import com.caliverse.admin.dynamodb.domain.doc.MailJsonDoc;
import com.caliverse.admin.dynamodb.domain.doc.SystemMetaMailDoc;
import com.caliverse.admin.dynamodb.dto.PageResult;
import com.caliverse.admin.dynamodb.entity.KeyParam;
import com.caliverse.admin.dynamodb.repository.*;
import com.caliverse.admin.global.common.annotation.DynamoDBTransaction;
import com.caliverse.admin.global.common.constants.CommonConstants;
import com.caliverse.admin.global.common.constants.DynamoDBConstants;
import com.caliverse.admin.global.common.utils.CommonUtils;
import com.caliverse.admin.global.common.utils.DateUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import software.amazon.awssdk.enhanced.dynamodb.Key;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;

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

@Slf4j
@Service
@RequiredArgsConstructor
public class DynamodbMailService {
    private final SystemMetaMailRepository systemMetaMailRepository;
    private final MailRepository mailRepository;
    private final MailJsonRepository mailJsonRepository;

    private final MetaDataHandler metaDataHandler;

    @DynamoDBTransaction
    public void insertSystemMail(RewardEvent rewardEvent){
        systemMetaMailRepository.insert(rewardEvent);
    }

    @DynamoDBTransaction
    public void insertLandChangesMail(LandRequest landRequest){
        MetaSystemMailData systemMailData = metaDataHandler.getMetaSystemMailListData().stream()
                .filter(data -> data.getKey().equals(CommonConstants.SYSTEM_MAIL_LAND_TRANS_KEY)).findFirst().orElse(null);
        MetaLandData landData = metaDataHandler.getMetaLandData(landRequest.getLandId());

        List<String> arguments = new ArrayList<>();
        arguments.add(landRequest.getUserName());
        arguments.add(landData.getLandName());

        String guid = landRequest.getUserGuid();
        String nickname = landRequest.getUserName();
        List<MailItemAttrib> items = new ArrayList<>();
        items.add(MailItemAttrib.builder()
                .itemId(landData.getLinkedItem())
                .count(1.0)
                .productId(0)
                .isRepeatProduct(CommonConstants.FALSE)
                .build()
        );

        mailRepository.insertRecvSystemMail(guid, nickname, items, systemMailData, arguments);
    }

    public PageResult<MailDoc> getMail(SEARCHTYPE type, String guid, String sortKey, KeyParam pageKey){
        Map<String, AttributeValue> pagingKey = null;
        if(pageKey != null){
            pagingKey = new HashMap<>();
            pagingKey.put(DynamoDBConstants.PK_KEY_NAME, AttributeValue.builder().s(pageKey.getPk()).build());
            pagingKey.put(DynamoDBConstants.SK_KEY_NAME, AttributeValue.builder().s(pageKey.getSk()).build());
        }
        PageResult<MailDoc> mailList = mailRepository.getMailListWithPaging(type, guid, sortKey, pagingKey);
        return mailList;
    }

    public MailJsonAttrib getMailJsonAttrib(String pk, String sk){
        try {
            Key key = Key.builder()
                    .partitionValue(pk)
                    .sortValue(sk)
                    .build();
            MailJsonDoc mailDoc = mailJsonRepository.findById(key);
            return CommonUtils.stringByObject(mailDoc.getAttribValue(), MailJsonAttrib.class);
        }catch (Exception e){
            log.error(e.getMessage());
        }
        return null;
    }

    @DynamoDBTransaction
    public void deleteMail(String type, String userGuid, String mailGuid){
        Key key;
        if(type.equals("SEND")){
            key = Key.builder()
                    .partitionValue(DynamoDBConstants.PK_KEY_SENT_MAIL + userGuid)
                    .sortValue(mailGuid)
                    .build();
        }else{
            key = Key.builder()
                    .partitionValue(DynamoDBConstants.PK_KEY_RECV_MAIL + userGuid)
                    .sortValue(mailGuid)
                    .build();
        }
        MailDoc mailDoc = mailRepository.findById(key);
        MailAttrib attrib = mailDoc.getAttribValue();
        if(attrib == null){
            mailJsonRepository.deleteMail(key);
        }else{
            mailRepository.deleteMail(key);
        }
    }

    @DynamoDBTransaction
    public void deleteMailItem(String type, String userGuid, String mailGuid, Integer itemId, double count, double newCount){
        Key key;
        if(type.equals("SEND")){
            key = Key.builder()
                    .partitionValue(DynamoDBConstants.PK_KEY_SENT_MAIL + userGuid)
                    .sortValue(mailGuid)
                    .build();
        }else{
            key = Key.builder()
                    .partitionValue(DynamoDBConstants.PK_KEY_RECV_MAIL + userGuid)
                    .sortValue(mailGuid)
                    .build();
        }
        MailDoc mailDoc = mailRepository.findById(key);
        MailAttrib attrib = mailDoc.getAttribValue();
        if(attrib == null){
            mailJsonRepository.deleteMailItem(key, itemId, count, newCount);
        }else{
            mailRepository.deleteMailItem(key, itemId, count, newCount);
        }
    }

    @DynamoDBTransaction
    public void oldSystemMetaMailClear(){
        Key key = Key.builder()
                .partitionValue(DynamoDBConstants.PK_KEY_SYSTEM_MAIL)
                .build();
        List<SystemMetaMailDoc> mailList = systemMetaMailRepository.findAll(key);
        mailList.forEach(mail -> {
            try {
                SystemMetaMailAttrib attrib = CommonUtils.stringByObject(mail.getAttribValue(), SystemMetaMailAttrib.class);
                LocalDateTime endTime = DateUtils.stringISOToLocalDateTime(attrib.getEndTime());
                LocalDateTime expiredTime = LocalDateTime.now().minusMonths(1);
                if(endTime.isBefore(expiredTime)){
                    systemMetaMailRepository.delete(mail.getSK());
                }
            }catch (Exception e){
                log.error("oldSystemMetaMail Clear Fail: {}",e.getMessage());
            }
        });
    }
}
