package com.caliverse.admin.dynamodb.service;

import com.caliverse.admin.domain.entity.BlackList;
import com.caliverse.admin.domain.response.UsersResponse;
import com.caliverse.admin.dynamodb.domain.atrrib.*;
import com.caliverse.admin.dynamodb.domain.doc.CharacterBaseDoc;
import com.caliverse.admin.dynamodb.domain.doc.UserNicknameRegistryDoc;
import com.caliverse.admin.dynamodb.entity.AppearanceProfile;
import com.caliverse.admin.dynamodb.entity.EAuthAdminLevelType;
import com.caliverse.admin.dynamodb.repository.*;
import com.caliverse.admin.global.common.annotation.DynamoDBTransaction;
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.fasterxml.jackson.databind.ObjectMapper;
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.util.HashMap;
import java.util.Map;


@Slf4j
@Service
@RequiredArgsConstructor
public class DynamodbUserService {
    private final AccountBaseRepository accountBaseRepository;
    private final CharacterBaseRepository characterBaseRepository;
    private final UserBaseRepository userBaseRepository;
    private final UserNicknameRegistryRepository userNicknameRegistryRepository;
    private final NicknameRepository nicknameRepository;
    private final MoneyRepository moneyRepository;

    private final ObjectMapper mapper = new ObjectMapper();

    public boolean isBlockUser(String guid){
        String account_id = getGuidByAccountId(guid);
        return accountBaseRepository.isBlockUser(account_id);
    }

    public boolean isUser(String guid){
        UserBaseAttrib userBaseAttrib = userBaseRepository.findUser(guid);
        if(userBaseAttrib == null){
            return false;
        }
        return true;
    }

    @DynamoDBTransaction
    public void updateBlockUser(BlackList.STATUSTYPE status, BlackList blackList){
        String guid = blackList.getGuid();
        String account_id = getGuidByAccountId(guid);

        if(status.equals(BlackList.STATUSTYPE.INPROGRESS)){
            accountBaseRepository.updateBlockUserStart(account_id, blackList);
        }
        else{
            accountBaseRepository.updateBlockUserEnd(account_id);
        }
    }

    public String getGuidByName(String guid){
        NicknameAttrib nicknameAttrib = nicknameRepository.findUser(guid);
        if(nicknameAttrib == null){
            log.error("getGuidByName Nickname Null guid: {}", guid);
            return "";
        }

        return nicknameAttrib.getNickname();
    }

    public String getGuidByAccountId(String guid){
        UserBaseAttrib userBaseAttrib = userBaseRepository.findUser(guid);
        if(userBaseAttrib == null){
            log.error("getGuidByAccountId UserBase Null guid: {}", guid);
            return "";
        }

        return userBaseAttrib.getAccountId();
    }

    public String getAccountIdByGuid(String accountId){
        AccountBaseAttrib accountBaseAttrib = accountBaseRepository.findUser(accountId);
        if(accountBaseAttrib == null){
            log.error("getAccountIdByGuid accountBase Null accountId: {}", accountId);
            return "";
        }

        return accountBaseAttrib.getUserGuid();
    }

    public String getAccountIdByName(String accountId){
        AccountBaseAttrib accountBaseAttrib = accountBaseRepository.findUser(accountId);
        if(accountBaseAttrib == null){
            log.error("getAccountIdByName accountBase Null accountId: {}", accountId);
            return "";
        }

        return getGuidByName(accountBaseAttrib.getUserGuid());
    }

    public String getNameByGuid(String nickname){
        UserNicknameRegistryAttrib nicknameRegistryAttrib = userNicknameRegistryRepository.findUser(nickname.toLowerCase());
        if(nicknameRegistryAttrib == null){
            log.error("getNameByGuid UserNicknameRegistry Null nickname: {}", nickname);
            return "";
        }

        return nicknameRegistryAttrib.getUserGuid();
    }

    public String getUserLanguage(String guid){
        String account_id = getGuidByAccountId(guid);
        AccountBaseAttrib accountBaseAttrib = accountBaseRepository.findUser(account_id);
        if(accountBaseAttrib == null){
            log.error("getUserLanguage accountBase Null accountId: {}", account_id);
            return "";
        }

        return accountBaseAttrib.getLanguageType().name();
    }

    @DynamoDBTransaction
    public void updateAdminLevel(String guid, EAuthAdminLevelType type){
        String account_id = getGuidByAccountId(guid);
        accountBaseRepository.updateAdminLevel(account_id, type);
    }

    public AccountBaseAttrib getAccountInfo(String accountId){
        return accountBaseRepository.findUser(accountId);
    }

    public MoneyAttrib getMoneyInfo(String guid){
        return moneyRepository.findAttrib(guid);
    }

    @DynamoDBTransaction
    public void changesNickname(String guid, String oldNickname, String newNickname){
        UserNicknameRegistryAttrib newNicknameAttrib = userNicknameRegistryRepository.findUser(newNickname.toLowerCase());
        if(newNicknameAttrib != null){
            throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.NICKNAME_EXIT_ERROR.toString());
        }

        Key key = Key.builder()
                .partitionValue(DynamoDBConstants.PK_KEY_USER_NICKNAME_REGISTRY)
                .sortValue(oldNickname.toLowerCase())
                .build();
        UserNicknameRegistryDoc beforeDoc = userNicknameRegistryRepository.findById(key);
        if(beforeDoc == null){
            throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.DYNAMODB_NOT_USER.toString());
        }

        userNicknameRegistryRepository.deleteNickname(oldNickname);
        userNicknameRegistryRepository.insertChangesNickname(beforeDoc, newNickname);

        nicknameRepository.updateNickname(guid, newNickname);
    }

    public Map<String, Object> getAvatarInfo(String guid){
        Map<String, Object> resMap = new HashMap<>();

        CharacterBaseAttrib characterBaseAttrib = characterBaseRepository.findCharacter(guid);
        if(characterBaseAttrib == null){
            log.error("getAvatarInfo characterBase Null guid: {}", guid);
            return null;
        }

        try {
            AppearanceProfile profile = characterBaseAttrib.getAppearanceProfile();

            resMap.put("avatarInfo", UsersResponse.AvatarInfo.builder()
                    .characterId(characterBaseAttrib.getCharacterGuid())
                    .basicstyle(profile.getBasicStyle())
                    .hairstyle(profile.getHairStyle())
                    .facesCustomizing(profile.getCustomValues())
                    .bodyshape(profile.getBodyShape())
                    .build());
            log.info("getAvatarInfo AvatarInfo: {}", resMap);

            return resMap;
        } catch (Exception e) {
            throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.DYNAMODB_CONNECTION_ERROR.getMessage());
        }
    }

}
