package com.caliverse.admin.domain.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import com.caliverse.admin.domain.entity.FriendRequest;
import com.caliverse.admin.domain.entity.HISTORYTYPE;
import com.caliverse.admin.domain.request.MailRequest;
import com.caliverse.admin.redis.service.RedisUserInfoService;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.caliverse.admin.domain.datacomponent.MetaDataHandler;
import com.caliverse.admin.domain.request.UsersRequest;
import com.caliverse.admin.domain.response.UsersResponse;
import com.caliverse.admin.global.common.code.CommonCode;
import com.caliverse.admin.global.common.code.ErrorCode;
import com.caliverse.admin.global.common.code.SuccessCode;
import com.caliverse.admin.global.common.exception.RestApiException;
import com.caliverse.admin.global.common.utils.CommonUtils;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
@Slf4j
public class UsersService {
    private static final Logger logger = LoggerFactory.getLogger(UsersService.class);

    private final DynamoDBService dynamoDBService;
    private final HistoryService historyService;
    private final UserGameSessionService userGameSessionService;
    private final RedisUserInfoService redisUserInfoService;
    
    //metadataHandler 어떻게 가져와야 되는가
    @Autowired
    private MetaDataHandler metaDataHandler;

    // 닉네임 변경
    public UsersResponse changeNickname(UsersRequest usersRequest){
        String guid = usersRequest.getGuid();
        String nickname = usersRequest.getNickname();
        String newNickname = usersRequest.getNewNickname();

        //신규 닉네임 유효성 체크
        ErrorCode check = CommonUtils.isValidNickname(newNickname);
        if(!check.equals(ErrorCode.SUCCESS)){
            throw new RestApiException(CommonCode.ERROR.getHttpStatus(), check.getMessage() );
        }

        Map<String, String> serachNickname = dynamoDBService.getUsersByName(newNickname);
        if(serachNickname != null){
            //변경 닉네임이 존재합니다. 다시 시도해주세요.
            throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.NICKNAME_EXIT_ERROR.getMessage() );
        }else{
            dynamoDBService.updateNickname(guid,nickname,newNickname);
        }

        return UsersResponse.builder()
                .resultData(UsersResponse.ResultData.builder()
                        .message(SuccessCode.UPDATE.getMessage())
                        .build())
                .status(CommonCode.SUCCESS.getHttpStatus())
                .result(CommonCode.SUCCESS.getResult())
                .build();

    }

    // GM 권한 변경
    public UsersResponse changeAdminLevel(UsersRequest usersRequest){
        String guid = usersRequest.getGuid();
        String type = usersRequest.getAdminLevel();

        dynamoDBService.updateAdminLevel(guid, type);

        return UsersResponse.builder()
                .resultData(UsersResponse.ResultData.builder()
                        .message(SuccessCode.UPDATE.getMessage())
                        .build())
                .status(CommonCode.SUCCESS.getHttpStatus())
                .result(CommonCode.SUCCESS.getResult())
                .build();

    }

    // 유정 정보 조회 닉네임,GUID,Account ID
    public UsersResponse findUsers(Map requestParam){

        String searchType = requestParam.get("search_type").toString();
        String searchKey = requestParam.get("search_key").toString();

        Map<String,String> res = dynamoDBService.findUsersBykey(searchType, searchKey);

        return UsersResponse.builder()
                .resultData(UsersResponse.ResultData.builder()
                        .result(res)
                        .build())
                .status(CommonCode.SUCCESS.getHttpStatus())
                .result(CommonCode.SUCCESS.getResult())
                .build();
    }
    public UsersResponse getBasicInfo(String guid){

        String account_id = dynamoDBService.getGuidByAccountId(guid);
        //userInfo
        Map<String, Object> userInfo = dynamoDBService.getAccountInfo(account_id);

        // charInfo
        Map<String, Object> charInfo = dynamoDBService.getCharInfo(guid);


        return UsersResponse.builder()
                .resultData(
                    UsersResponse.ResultData.builder()
                            .charInfo((UsersResponse.CharInfo) charInfo.get("charInfo"))
                            .userInfo((UsersResponse.UserInfo) userInfo.get("userInfo"))
                            .build()
                )
                .status(CommonCode.SUCCESS.getHttpStatus())
                .result(CommonCode.SUCCESS.getResult())
                .build();

    }

    public UsersResponse getAvatarInfo(String guid){

        //avatarInfo
        Map<String, Object> charInfo = dynamoDBService.getAvatarInfo(guid);

        return UsersResponse.builder()
                .resultData(
                        UsersResponse.ResultData.builder()
                            .avatarInfo((UsersResponse.AvatarInfo) charInfo.get("avatarInfo"))
                            .build()
                )
                .status(CommonCode.SUCCESS.getHttpStatus())
                .result(CommonCode.SUCCESS.getResult())
                .build();

    }

    public UsersResponse getClothInfo(String guid){

        //clothInfo
//        Map<String, Object> charInfo = dynamoDBService.getClothInfo(guid);
        Map<String, Object> charInfo = dynamoDBService.getCloth(guid);

        return UsersResponse.builder()
                .resultData(
                        UsersResponse.ResultData.builder()
                        .clothInfo((UsersResponse.ClothInfo) charInfo.get("clothInfo"))
                        .build()
                )
                .status(CommonCode.SUCCESS.getHttpStatus())
                .result(CommonCode.SUCCESS.getResult())
                .build();

    }

    public UsersResponse getToolSlotInfo(String guid){

        // toolslotInfo
//        List<UsersResponse.SlotInfo> toolSlot = dynamoDBService.getToolSlot(guid);
        Map<String, Object> toolSlot = dynamoDBService.getTools(guid);

        return UsersResponse.builder()
                .resultData(
                        UsersResponse.ResultData.builder()
                        .slotInfoList((UsersResponse.SlotInfo) toolSlot.get("toolSlotInfo"))
                        .build()
                )
                .status(CommonCode.SUCCESS.getHttpStatus())
                .result(CommonCode.SUCCESS.getResult())
                .build();

    }
    public UsersResponse getInventoryInfo(String guid){

//        List<List<UsersResponse.Inventory>> inventoryList = new ArrayList<>();
//        List<List<String>> item = dynamoDBService.getInvenItems(guid);
//        if(item != null){
//            for (List<String> list : item){
//                List<UsersResponse.Inventory> innerList = new ArrayList<>();
//                for (String key : list){
//                    Map<String, Object> resItem = dynamoDBService.getItemTable(key);
//
//                    //객체를 생성하고 값을 설정
//                    UsersResponse.Inventory inventory = new UsersResponse.Inventory();
//
//                    Object itemId = resItem.get("ItemId");
//                    String itemIdString = CommonUtils.objectToString(itemId);
//                    Integer itemIdInteger = CommonUtils.objectToInteger(itemId);
//
//
//                    inventory.setCount(Integer.valueOf(CommonUtils.objectToString(resItem.get("Count"))));
//                    inventory.setItemId(itemIdString);
//                    inventory.setItemName(metaDataHandler.getMetaItemData(itemIdInteger).getName());
//                    innerList.add(inventory);
//                }
//                inventoryList.add(innerList);
//            }
//        }
        UsersResponse.InventoryInfo inventoryInfo = dynamoDBService.getInvenItems(guid);
        logger.info("getInventoryInfo Inventory Items: {}", inventoryInfo);

        return UsersResponse.builder()
                .resultData(
                        UsersResponse.ResultData.builder()
                        .inventoryInfo(inventoryInfo)
                        .build()
                )
                .status(CommonCode.SUCCESS.getHttpStatus())
                .result(CommonCode.SUCCESS.getResult())
                .build();

    }

    public UsersResponse deleteInventoryItem(Map<String, String> requestParams){
        String guid = requestParams.get("guid");
        String item_guid = requestParams.get("item_guid");
        int current_cnt = Integer.parseInt(requestParams.get("current_cnt"));
        int update_cnt = Integer.parseInt(requestParams.get("cnt"));

        userGameSessionService.kickUserSession(guid);
        if(update_cnt >= current_cnt){
            String attrib = dynamoDBService.deleteItem(guid, item_guid);
            if(!attrib.isEmpty()){
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("data",attrib);
                historyService.setLog(HISTORYTYPE.INVENTORY_ITEM_DELETE, jsonObject);
            }
            return UsersResponse.builder()
                    .status(CommonCode.SUCCESS.getHttpStatus())
                    .result(CommonCode.SUCCESS.getResult())
                    .resultData(UsersResponse.ResultData.builder()
                            .message(SuccessCode.DELETE.getMessage())
                            .build())
                    .build();
        }else{
            int cnt = current_cnt - update_cnt;
            JSONObject json = dynamoDBService.updateItem(guid, item_guid, cnt);
            if(!json.isEmpty()){
                historyService.setLog(HISTORYTYPE.INVENTORY_ITEM_UPDATE, json);
            }
            return UsersResponse.builder()
                    .status(CommonCode.SUCCESS.getHttpStatus())
                    .result(CommonCode.SUCCESS.getResult())
                    .resultData(UsersResponse.ResultData.builder()
                            .message(SuccessCode.UPDATE.getMessage())
                            .build())
                    .build();
        }
    }

    public UsersResponse getMail(String guid, String type){

        List<UsersResponse.Mail> mailList = dynamoDBService.getMail(guid, type);;
        return UsersResponse.builder()
                .resultData(
                        UsersResponse.ResultData.builder()
                        .mailList(mailList)
                        .build()
                )
                .status(CommonCode.SUCCESS.getHttpStatus())
                .result(CommonCode.SUCCESS.getResult())
                .build();

    }

    public UsersResponse deleteMail(Map<String, String> requestParams){
        String guid = requestParams.get("guid");
        String mail_guid = requestParams.get("mail_guid");
        String type = requestParams.get("type");

        userGameSessionService.kickUserSession(guid);
        String attrib = dynamoDBService.deleteMail(type, guid, mail_guid);
        if(!attrib.isEmpty()){
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("data",attrib);
            historyService.setLog(HISTORYTYPE.USER_MAIL_DELETE, jsonObject);
        }

        return UsersResponse.builder()
                .status(CommonCode.SUCCESS.getHttpStatus())
                .result(CommonCode.SUCCESS.getResult())
                .resultData(UsersResponse.ResultData.builder()
                        .message(SuccessCode.DELETE.getMessage())
                        .build())
                .build();
    }

    public UsersResponse deleteMailItem(MailRequest.DeleteMailItem deleteMailItem){
        userGameSessionService.kickUserSession(deleteMailItem.getGuid());
        JSONObject json = dynamoDBService.updateMailItem(deleteMailItem.getType(), deleteMailItem.getGuid(),
                deleteMailItem.getMailGuid(), deleteMailItem.getItemId(), deleteMailItem.getParrentCount(), deleteMailItem.getCount());
        if(!json.isEmpty()){
            historyService.setLog(HISTORYTYPE.MAIL_ITEM_UPDATE, json);
        }
        return UsersResponse.builder()
                .status(CommonCode.SUCCESS.getHttpStatus())
                .result(CommonCode.SUCCESS.getResult())
                .resultData(UsersResponse.ResultData.builder()
                        .message(SuccessCode.UPDATE.getMessage())
                        .build())
                .build();
    }

    public UsersResponse getMyhome(String guid){

        UsersResponse.Myhome myhome = dynamoDBService.getMyhome(guid);

        return UsersResponse.builder()
                .resultData(
                        UsersResponse.ResultData.builder()
                                .myhomeInfo(myhome)
                                .build()
                )
                .status(CommonCode.SUCCESS.getHttpStatus())
                .result(CommonCode.SUCCESS.getResult())
                .build();

    }

    public UsersResponse getFriendList(String guid){

        List<UsersResponse.Friend> friendList = dynamoDBService.getFriendList(guid);
        List<UsersResponse.Friend> friendBlockList = dynamoDBService.getUserBlockList(guid);
        List<UsersResponse.Friend> friendSendList = new ArrayList<>();
        List<UsersResponse.Friend> friendReceiveList = new ArrayList<>();

        List<FriendRequest> sendRequestList = redisUserInfoService.getFriendRequestInfo("send", guid);
        List<FriendRequest> receiveRequestList = redisUserInfoService.getFriendRequestInfo("receive", guid);
        AtomicInteger idx = new AtomicInteger(1);
        for(FriendRequest friendReq : sendRequestList){
            UsersResponse.Friend friend = new UsersResponse.Friend();
            friend.setRowNum(idx.getAndIncrement());
            String receive_guid = friendReq.getReceiverGuid();
            friend.setFriendGuid(receive_guid);
            friend.setFriendName(dynamoDBService.getGuidByName(receive_guid));
            friend.setReceiveDt(friendReq.getRequestTime());
            friend.setLanguage(dynamoDBService.getUserLanguage(receive_guid));

            friendSendList.add(friend);
        }
        idx = new AtomicInteger(1);
        for(FriendRequest friendReq : receiveRequestList){
            UsersResponse.Friend friend = new UsersResponse.Friend();
            friend.setRowNum(idx.getAndIncrement());
            String send_guid = friendReq.getSenderGuid();
            friend.setFriendGuid(send_guid);
            friend.setFriendName(dynamoDBService.getGuidByName(send_guid));
            friend.setReceiveDt(friendReq.getRequestTime());
            friend.setLanguage(dynamoDBService.getUserLanguage(send_guid));

            friendReceiveList.add(friend);
        }

        return UsersResponse.builder()
                .resultData(
                        UsersResponse.ResultData.builder()
                        .friendList(friendList)
                        .friendSendList(friendSendList)
                        .friendReceiveList(friendReceiveList)
                        .friendBlockList(friendBlockList)
                        .build()
                )
                .status(CommonCode.SUCCESS.getHttpStatus())
                .result(CommonCode.SUCCESS.getResult())
                .build();
    }

    public UsersResponse getTattoo(String guid){
        List<UsersResponse.Tattoo> resTatto = dynamoDBService.getTattoo(guid);

        return UsersResponse.builder()
                .resultData(
                        UsersResponse.ResultData.builder()
                                .tattooList(resTatto)
                                .build()
                )
                .status(CommonCode.SUCCESS.getHttpStatus())
                .result(CommonCode.SUCCESS.getResult())
                .build();

    }

    public UsersResponse getQuest(String guid){
//        UsersResponse.Quest quest = new UsersResponse.Quest();
//
//        List<UsersResponse.Quest> questListQuest = new ArrayList<>();
//
//        Map<String, List<Map<String, Object>>> resMap= dynamoDBService.getQuest(guid);
//
//        //List<Map<String, Object>> endList = resMap.get("EndList");
//        List<Map<String, Object>> questList = resMap.get("QuestList");
//
//        int index = 1;
//        if(questList != null){
//            for (Map<String,Object> val : questList){
//                if(val != null){
//                    quest = new UsersResponse.Quest();
//                    quest.setQuestId(Integer.valueOf(CommonUtils.objectToString(val.get("QuestId"))));
//                    quest.setStatus(CommonUtils.objectToString(val.get("IsComplete")));
//                    quest.setRowNum((long)index);
//                    questListQuest.add(quest);
//                    index++;
//                }
//            }
//        }

        List<UsersResponse.QuestInfo> questList = dynamoDBService.getQuest(guid);

        return UsersResponse.builder()
                .resultData(
                        UsersResponse.ResultData.builder()
                                .questList(questList)
                                .build()
                )
                .status(CommonCode.SUCCESS.getHttpStatus())
                .result(CommonCode.SUCCESS.getResult())
                .build();

    }
    /*public UsersResponse getClaim(String guid){

        List<UsersResponse.Guid> tattoo = dynamoDBService.getTattoo(guid);

        return UsersResponse.builder()
                .resultData(
                        UsersResponse.ResultData.builder()
                                .tattooList(tattoo)
                                .build()
                )
                .status(CommonCode.SUCCESS.getHttpStatus())
                .result(CommonCode.SUCCESS.getResult())
                .build();

    }*/

}
