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

import com.caliverse.admin.dynamodb.domain.atrrib.UserNicknameRegistryAttrib;
import com.caliverse.admin.dynamodb.domain.doc.UserNicknameRegistryDoc;
import com.caliverse.admin.dynamodb.repository.BaseDynamoDBRepository;
import com.caliverse.admin.dynamodb.repository.UserNicknameRegistryRepository;
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.JsonNode;
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;
import java.util.Objects;
import java.util.stream.Collectors;

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

    @Override
    public UserNicknameRegistryAttrib findUser(String nickname) {
        Key key = Key.builder()
                .partitionValue(DynamoDBConstants.PK_KEY_USER_NICKNAME_REGISTRY)
                .sortValue(nickname)
                .build();

        UserNicknameRegistryDoc doc = findById(key);
        if(doc == null) return null;
        return CommonUtils.stringByObject(doc.getAttribValue(), UserNicknameRegistryAttrib.class);
    }

    @Override
    public List<String> findAllNicknameByGuid() {
        Key key = Key.builder()
                .partitionValue(DynamoDBConstants.PK_KEY_USER_NICKNAME_REGISTRY)
                .build();

        List<UserNicknameRegistryDoc> doc = findAll(key);
        if(doc == null) return null;

        return doc.stream()
                .map(UserNicknameRegistryDoc::getAttribValue)
                .map(attribJson -> {
                    try {
                        JsonNode jsonNode = objectMapper.readTree(attribJson);
                        UserNicknameRegistryAttrib attrib = objectMapper.convertValue(jsonNode, UserNicknameRegistryAttrib.class);
                        return attrib.getUserGuid();
                    } catch (JsonProcessingException e) {
                        log.error("JSON parsing failed: {}", e.getMessage());
                        return null;
                    }
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    @Override
    public List<UserNicknameRegistryAttrib> findAllAttrib() {
        Key key = Key.builder()
                .partitionValue(DynamoDBConstants.PK_KEY_USER_NICKNAME_REGISTRY)
                .build();

        List<UserNicknameRegistryDoc> doc = findAll(key);

        return doc.stream()
                .map(UserNicknameRegistryDoc::getAttribValue)
                .map(attribJson -> {
                    try {
                        JsonNode jsonNode = objectMapper.readTree(attribJson);
                        return objectMapper.convertValue(jsonNode, UserNicknameRegistryAttrib.class);
                    } catch (JsonProcessingException e) {
                        log.error("JSON parsing failed: {}", e.getMessage());
                        return null;
                    }
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    @Override
    public void deleteNickname(String nickname) {
        Key key = Key.builder()
                .partitionValue(DynamoDBConstants.PK_KEY_USER_NICKNAME_REGISTRY)
                .sortValue(nickname.toLowerCase())
                .build();

        try {
            UserNicknameRegistryDoc beforeDoc = findById(key);

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

                log.info("UserNicknameRegistryDoc Delete Success: {}", objectMapper.writeValueAsString(beforeDoc));

            }
        }catch (Exception e){
            log.error("Delete UserNicknameRegistry Error: {}", e.getMessage());
            throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.DYNAMODB_CONNECTION_ERROR.getMessage());
        }
    }

    @Override
    public void insertChangesNickname(UserNicknameRegistryDoc beforeDoc, String newNickname) {
        LocalDateTime nowDate = LocalDateTime.now();

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

                UserNicknameRegistryAttrib attrib = CommonUtils.stringByObject(afterDoc.getAttribValue(), UserNicknameRegistryAttrib.class);
                attrib.setNickname(newNickname.toLowerCase());

                afterDoc.setSK(newNickname.toLowerCase());
                afterDoc.setAttribValue(CommonUtils.objectByString(attrib));
                afterDoc.setCreatedDateTime(CommonUtils.convertUTCDate(nowDate));
                afterDoc.setUpdatedDateTime(CommonUtils.convertUTCDate(nowDate));

                save(afterDoc);

                log.info("UserNicknameRegistryDoc Insert Success: {}", objectMapper.writeValueAsString(afterDoc));

            }
        }catch (Exception e){
            log.error("Insert UserNicknameRegistry Error: {}", e.getMessage());
            throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.DYNAMODB_CONNECTION_ERROR.getMessage());
        }
    }
}
