local A=game:GetService("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101")local p=A:WaitForChild("\077\111\100\117\108\101\115")local f=require(p.src.assets)local R=require(p.src.utils.Logger)local u=require(p.src.actions.toClient.clientSendNotification)local K="\077\111\115\116\080\108\097\121\101\100"local d="\080\108\097\121\101\114\067\111\105\110\115"local i="\080\108\097\121\101\114\086\105\115\105\116\115"local g=game:GetService("\068\097\116\097\083\116\111\114\101\083\101\114\118\105\099\101")local S=g:GetOrderedDataStore(d)local T=g:GetOrderedDataStore(i)local J=require(p.Promise)local c=require(p.src.GameDatastore)local s={}local W=50 local O=1000 local M=100 function s.connectPlayerVisits(K,A,p)local d=A.Name local i local g,S=pcall(function()i=T:IncrementAsync(d,1)end)local J=c:getLastLogin(A)local s=((os.time()-J)/60)/60 wait(7)if s>=24 then R:d("\080\108\097\121\101\114 "..(A.Name..(" \108\097\115\116 \108\111\103\105\110 \119\097\115 "..(tostring(s).." \097\103\111\046 \071\105\118\101 \114\101\119\097\114\100\046"))),J)c:incrementCoins(A,M)p:dispatch(u(A,"\068\097\105\108\121 \118\105\115\105\116\046 \082\101\119\097\114\100\058 "..(M.." \099\111\105\110\115"),f.money["\099\111\105\110\115-\112\105\108\101"]))end if g and i==10 then R:d("\080\108\097\121\101\114 "..(A.Name..(" \104\097\115 \118\105\115\105\116\101\100  "..(tostring(i).." \116\105\109\101\115\046 \071\105\118\101 \114\101\119\097\114\100\046"))))c:incrementCoins(A,O)p:dispatch(u(A,"\089\111\117 \118\105\115\105\116\101\100 \049\048 \116\105\109\101\115\046 \082\101\119\097\114\100\058 "..(O.." \099\111\105\110\115"),f.money["\099\111\105\110\115-\112\105\108\101"]))end c:setLastLogin(A)R:d("\080\108\097\121\101\114 "..(A.Name..(" \104\097\115 \118\105\115\105\116\101\100 "..(i.." \116\105\109\101\115\046"))))end local function Q(A,p)return J.async(function(f,u)local K=A.Name R:d("\068\097\116\097\083\116\111\114\101 \076\101\097\100\101\114\098\111\097\114\100\058 \085\112\100\097\116\101 \112\108\097\121\101\114 "..(A.Name.." \109\111\115\116 \099\111\105\110\115"))local d,i=pcall(S.SetAsync,S,K,p.coins)if not d then R:e("\070\097\105\108\117\114\101 \100\117\114\105\110\103 \117\112\100\097\116\105\110\103 \116\111\112 \099\111\105\110\115\058 "..i)u(i)else f(i)end end)end function s.connectMostCoins(p,A)local f=function(p)R:d("\068\097\116\097\083\116\111\114\101 \076\101\097\100\101\114\098\111\097\114\100\058 \080\108\097\121\101\114 "..(A.Name..(" \101\097\114\110\101\100 "..(p.coins.." \099\111\105\110\115\046"))),p);((Q(A,p)):andThen(function(A)R:d("\068\097\116\097\083\116\111\114\101 \076\101\097\100\101\114\098\111\097\114\100\058 \083\097\118\101\100 \116\111\112 \099\111\105\110\115",A)end)):catch(function(A)R:e(A)end)end c:coinsAfterSave(A,f)end function s.updateMostPlayed(f,A,p)local u=p or""local d=g:GetOrderedDataStore(K..u)local i=A.Name R:d("\068\097\116\097\083\116\111\114\101 \076\101\097\100\101\114\098\111\097\114\100\058 \085\112\100\097\116\101 \080\108\097\121\101\114 "..(A.Name.." \077\111\115\116 \080\108\097\121\101\100 \102\111\114 \114\111\111\109\058"),p)d:IncrementAsync(i,1)end function s.getMostPlayed(p,A)local f=A or""local u=g:GetOrderedDataStore(K..f)local d=u:GetSortedAsync(false,W)local i=d:GetCurrentPage()R:d("\068\097\116\097\083\116\111\114\101 \076\101\097\100\101\114\098\111\097\114\100\058 \071\101\116 \114\111\111\109 \077\111\115\116 \080\108\097\121\101\100",A)return i end function s.getMostVisited(A)local p=T:GetSortedAsync(false,W)local f=p:GetCurrentPage()R:d("\068\097\116\097\083\116\111\114\101 \076\101\097\100\101\114\098\111\097\114\100\058 \071\101\116  \077\111\115\116 \086\105\115\105\116\101\100")return f end function s.getMostCoins(A)local p=S:GetSortedAsync(false,W)local f=p:GetCurrentPage()R:d("\068\097\116\097\083\116\111\114\101 \076\101\097\100\101\114\098\111\097\114\100\058 \071\101\116  \077\111\115\116 \067\111\105\110\115")return f end return s
local ReplicatedStorage = game:GetService('ReplicatedStorage')
local Modules = ReplicatedStorage:WaitForChild('Modules')
local assets = require(Modules.src.assets)
local logger = require(Modules.src.utils.Logger)

local clientSendNotification = require(Modules.src.actions.toClient.clientSendNotification)

local STORE_MOST_PLAYED = 'MostPlayed'
local STORE_MOST_COINS = 'PlayerCoins'
local STORE_PLAYER_VISITS = 'PlayerVisits'

local datastore = game:GetService('DataStoreService')

local mostCoinsStore = datastore:GetOrderedDataStore(STORE_MOST_COINS)
local visitsDataStore = datastore:GetOrderedDataStore(STORE_PLAYER_VISITS)

local Promise = require(Modules.Promise)

local GameDatastore = require(Modules.src.GameDatastore)

local Leaderboards = {}

local LEADERBOARD_SIZE = 50

local REWARD_10TIMES = 1000
local REWARD_DAILY = 100

function Leaderboards:connectPlayerVisits(player, store)
	local playerKey = player.Name
	local visits
	local success, err = pcall(function()
		visits = visitsDataStore:IncrementAsync(playerKey, 1)
	end)

	local lastLogin = GameDatastore:getLastLogin(player)
	local hours = (os.time() - lastLogin) / 60 / 60

	wait(7)

	if hours >= 24 then
		logger:d(
			'Player ' .. player.Name .. ' last login was ' .. tostring(
				hours
			) .. ' ago. Give reward.',
			lastLogin
		)
		GameDatastore:incrementCoins(player, REWARD_DAILY)
		store:dispatch(
			clientSendNotification(
				player,
				'Daily visit. Reward: ' .. REWARD_DAILY .. ' coins',
				assets.money['coins-pile']
			)
		)
	end

	if success and visits == 10 then
		logger:d(
			'Player ' .. player.Name .. ' has visited  ' .. tostring(
				visits
			) .. ' times. Give reward.'
		)
		GameDatastore:incrementCoins(player, REWARD_10TIMES)
		store:dispatch(
			clientSendNotification(
				player,
				'You visited 10 times. Reward: ' .. REWARD_10TIMES .. ' coins',
				assets.money['coins-pile']
			)
		)
	end

	GameDatastore:setLastLogin(player)

	logger:d('Player ' .. player.Name .. ' has visited ' .. visits .. ' times.')
end

local function updateMostCoins(player, playerData)
	return Promise.async(function(resolve, reject)
		local playerKey = player.Name

		logger:d('DataStore Leaderboard: Update player ' .. player.Name .. ' most coins')
		local success, response =
			pcall(mostCoinsStore.SetAsync, mostCoinsStore, playerKey, playerData.coins)

		if not success then
			logger:e('Failure during updating top coins: ' .. response)
			reject(response)
		else
			resolve(response)
		end
	end)
end

function Leaderboards:connectMostCoins(player)
	local updateLeaderboard = function(playerData)
		--[[	mostCoinsStore:UpdateAsync(playerKey, function(oldValue)
					local newValue = oldValue or 0
					newValue = newValue + playerData.coins
	
					return newValue
				end)]]
		logger:d(
			'DataStore Leaderboard: Player ' .. player.Name .. ' earned ' .. playerData.coins .. ' coins.',
			playerData
		)

		updateMostCoins(player, playerData):andThen(function(body)
			logger:d('DataStore Leaderboard: Saved top coins', body)
		end):catch(function(err)
			logger:e(err)
		end)
	end

	GameDatastore:coinsAfterSave(player, updateLeaderboard)
end

function Leaderboards:updateMostPlayed(player, roomId)
	local key = roomId or ''
	local mostPlayedStore = datastore:GetOrderedDataStore(STORE_MOST_PLAYED .. key)
	local playerKey = player.Name

	logger:d(
		'DataStore Leaderboard: Update Player ' .. player.Name .. ' Most Played for room:',
		roomId
	)

	mostPlayedStore:IncrementAsync(playerKey, 1)
end

function Leaderboards:getMostPlayed(roomId)
	local key = roomId or ''
	local mostPlayedStore = datastore:GetOrderedDataStore(STORE_MOST_PLAYED .. key)
	local pages = mostPlayedStore:GetSortedAsync(false, LEADERBOARD_SIZE)
	local data = pages:GetCurrentPage()
	logger:d('DataStore Leaderboard: Get room Most Played', roomId)
	return data
end

function Leaderboards:getMostVisited()
	local pages = visitsDataStore:GetSortedAsync(false, LEADERBOARD_SIZE)
	local data = pages:GetCurrentPage()
	logger:d('DataStore Leaderboard: Get  Most Visited')
	return data
end

function Leaderboards:getMostCoins()
	local pages = mostCoinsStore:GetSortedAsync(false, LEADERBOARD_SIZE)
	local data = pages:GetCurrentPage()
	logger:d('DataStore Leaderboard: Get  Most Coins')
	return data
end

return Leaderboards