#include "BlockManager.h"
#include <relationship/relationship_dto.pb.h>
#include "Common/CsdkStringConvert.h"
#include "Log/CsdkLogMacros.h"
#include "Log/LogChatSdk.h"
#include "Tools/CsdkCommonHttp.h"
#include "User/Tool/UserTool.h"

using namespace heroim::client::v3beta::dto::relationship;

void FBlockManager::Init()
{
	GetBlockList_Internal(nullptr);
}

void FBlockManager::Reset()
{
	BlockMap.Empty();

}

void FBlockManager::GetBlockList(const TFunction<void(const int32 ErrorCode, const FString& ErrorMsg, const TArray<FCsdkBlock>&)>& Callback)
{
	GetBlockList_Internal(Callback);
}

void FBlockManager::AddBlock(const FCsdkUserId& UserId,
	const TFunction<void(const int32 ErrorCode, const FString& ErrorMsg)>& Callback)
{
	BlockedAddRequest Request;
	Request.set_allocated_base(FCsdkCommonTools::MakePbBase());
	Request.set_allocated_userkey(CsdkUserTool::MakePbUserKey(UserId));
	
	auto RequestCallBack = [this,UserId,Callback](const int32 ErrorCode,const FString& ErrorMsg,const BlockedAddResponse& Resp)
	{
		if(ECsdkErrorCode::Success ==ErrorCode)
		{
			FCsdkBlock Block;
			Block.User = CsdkUserTool::ConvertUser(Resp.blocked().user());
			Block.BlockedInfo.blockTime = Resp.blocked().blocked().blocktime();
			for(const auto& ExtraItem:Resp.blocked().blocked().extra())
			{
				Block.BlockedInfo.Extra.Add(STD_STRING_TO_FSTRING(ExtraItem.first),STD_STRING_TO_FSTRING(ExtraItem.second));
			}
			BlockMap.Add(UserId,Block);
			FCsdkManager::GetInstance().Subsystem->OnBlockAdd.Broadcast(Block);
		}
		
		Callback(ErrorCode,ErrorMsg);
	};
	FCsdkCommonHttp<BlockedAddResponse>::Request(TEXT("/spi/v3beta/rs/blocked/add"),Request,RequestCallBack);
}

void FBlockManager::RemoveBlock(const FCsdkUserId& UserId,
	const TFunction<void(const int32 ErrorCode, const FString& ErrorMsg)>& Callback)
{
	BlockedDeleteRequest Request;
	Request.set_allocated_base(FCsdkCommonTools::MakePbBase());
	Request.set_allocated_userkey(CsdkUserTool::MakePbUserKey(UserId));
	
	auto RequestCallBack = [this,UserId,Callback](const int32 ErrorCode,const FString& ErrorMsg,const BlockedDeleteResponse& Resp)
	{
		if(ECsdkErrorCode::Success == ErrorCode )
		{
			BlockMap.Remove(UserId);
			FCsdkManager::GetInstance().Subsystem->OnBlockDeleted.Broadcast(UserId);
		}
		Callback(ErrorCode,ErrorMsg);
	};
	FCsdkCommonHttp<BlockedDeleteResponse>::Request(TEXT("/spi/v3beta/rs/blocked/delete"),Request,RequestCallBack);
}

bool FBlockManager::IsUserIdBlocked(const FCsdkUserId& UserId) const
{
	return BlockMap.Contains(UserId);
}

TArray<UCsdkMessageBase*> FBlockManager::FilterMsgsSenderNotBlocked(const TArray<UCsdkMessageBase*>& InMsgs) const
{
	TArray<UCsdkMessageBase*> Result;
	for(const auto& Msg:InMsgs)
	{
		if(!IsUserIdBlocked(Msg->Sender.Id))
		{
			Result.Add(Msg);
		};
	}
	CSDK_LOG(LogChatSdk,Log,TEXT("Filter No Block Msg. InMsgs.Length:%d,InMsgs.Result.Length:%d"),InMsgs.Num(),Result.Num());
	return Result;
}

void FBlockManager::GetBlockList_Internal(const TFunction<void(const int32 ErrorCode, const FString& ErrorMsg, const TArray<FCsdkBlock>&)>& Callback)
{
	BlockedListRequest Request;
	Request.set_allocated_base(FCsdkCommonTools::MakePbBase());
	auto RequestCallBack = [this,Callback](const int32 ErrorCode, const FString& ErrorMsg,
											const BlockedListResponse& Resp)
	{
		BlockMap.Empty();
		TArray<FCsdkBlock> Results;
		for (const auto& BlockItem : Resp.list())
		{
			FCsdkBlock Block;
			Block.User = CsdkUserTool::ConvertUser(BlockItem.user());
			Block.BlockedInfo.blockTime = BlockItem.blocked().blocktime();
			TMap<FString, FString> BlockExtraInfo;
			for (const auto& ExtraInfo : BlockItem.blocked().extra())
			{
				Block.BlockedInfo.Extra.Add(STD_STRING_TO_FSTRING(ExtraInfo.first),STD_STRING_TO_FSTRING(ExtraInfo.second));
			}

			BlockMap.Add(Block.User.Id,Block);
			Results.Add(Block);
			CSDK_LOG(LogChatSdk, Log, TEXT("Block Info: %s"), *Block.User.ToString());
		}
		if(Callback!= nullptr)
		{
			Callback(ErrorCode,ErrorMsg,Results);
		}
	};
	FCsdkCommonHttp<BlockedListResponse>::Request(TEXT("/spi/v3beta/rs/blocked/list"), Request, RequestCallBack);
}


