local g=game:GetService("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101")local n=game:GetService("\072\116\116\112\083\101\114\118\105\099\101")local K=require(script.Parent.Parent.Promise)local f={Firestore=function(g)return("\104\116\116\112\115\058\047\047\102\105\114\101\115\116\111\114\101\046\103\111\111\103\108\101\097\112\105\115\046\099\111\109\047\118\049\047\112\114\111\106\101\099\116\115\047\037\115\047\100\097\116\097\098\097\115\101\115\047\040\100\101\102\097\117\108\116\041\047\100\111\099\117\109\101\110\116\115\047"):format(g.ProjectId)end;IdentityToolKit=function()return"\104\116\116\112\115\058\047\047\105\100\101\110\116\105\116\121\116\111\111\108\107\105\116\046\103\111\111\103\108\101\097\112\105\115\046\099\111\109\047\118\049\047\097\099\099\111\117\110\116\115"end}local k={}local L={}L.__index=L function k.new(g)local n={}n.App=g return setmetatable(n,L)end local function A(g,n,K)local f=g..n if K then local g={}for n,K in pairs(K)do if type(n)=="\110\117\109\098\101\114"then table.insert(g,K)else table.insert(g,("\037\115\061\037\115"):format(n,K))end end if#g>0 then f=f..("\063"..table.concat(g,"\038"))end end return f end local function F(g,K)K.Headers=K.Headers or{}if g._auth then K.Headers.Authorization="\066\101\097\114\101\114 "..g._auth.IdToken end local f=K.Body if f and type(f)=="\116\097\098\108\101"then K.Headers["\099\111\110\116\101\110\116-\116\121\112\101"]="\097\112\112\108\105\099\097\116\105\111\110\047\106\115\111\110"K.Body=n:JSONEncode(f)end local k=n:RequestAsync(K)if k.StatusCode==401 then g._auth=(g._authentication:SignInWithEmailAndPassword(g.Email,g.Password)):expect()K.Headers.Authorization="\066\101\097\114\101\114 "..g._auth.IdToken k=n:RequestAsync(K)end if k.Headers["\099\111\110\116\101\110\116-\116\121\112\101"]:find("\097\112\112\108\105\099\097\116\105\111\110\047\106\115\111\110")then k.Body=n:JSONDecode(k.Body)end return k end function L.GET(L,g,n,k)return K.new(function(K,s)local x=L.App local m=F(x,{Url=A(f[g](x),n,k);Method="\071\069\084"})if m.StatusCode==200 then K(m.Body)else s(m.Body)end end)end function L.POST(s,g,n,k,L)return K.new(function(K,x)local m=s.App local R=F(s.App,{Url=A(f[g](m),n,k),Method="\080\079\083\084",Body=L})if R.StatusCode==200 then K(R.Body)else x(R.Body)end end)end function L.DELETE(s,g,n,k,L)return K.new(function(K,x)local m=s.App local R=F(s.App,{Url=A(f[g](m),n,k);Method="\068\069\076\069\084\069",Body=L})if R.StatusCode==200 then K(R.Body)else x(R.Body)end end)end function L.PATCH(s,g,n,k,L)return K.new(function(K,x)local m=s.App local R=F(s.App,{Url=A(f[g](m),n,k),Method="\080\065\084\067\072",Body=L})if R.StatusCode==200 then K(R.Body)else x(R.Body)end end)end return k
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local HttpService = game:GetService("HttpService")

local Promise = require(script.Parent.Parent.Promise)

local BASE_URLs = {
    Firestore = function(app)
        return ("https://firestore.googleapis.com/v1/projects/%s/databases/(default)/documents/"):format(app.ProjectId)
    end,
    IdentityToolKit = function()
        return "https://identitytoolkit.googleapis.com/v1/accounts"
    end,
}

local Http = {}
local HTTP_METATABLE = {}
HTTP_METATABLE.__index = HTTP_METATABLE

function Http.new(app)
    local self = {}

    self.App = app

    return setmetatable(self, HTTP_METATABLE)
end

local function formatUrl(baseUrl, path, queries)
    local url = baseUrl.. path

    if queries then
        local queryStrings = {}

        for key, value in pairs(queries) do
            if type(key) == "number" then
                table.insert(queryStrings, value)
            else
                table.insert(queryStrings, ("%s=%s"):format(key, value))
            end
        end

        if #queryStrings > 0 then
            url = url.. "?".. table.concat(queryStrings, "&")
        end
    end

    return url
end

local function requestAsync(app, requestParams)
    requestParams.Headers = requestParams.Headers or {}

    if app._auth then
        requestParams.Headers.Authorization = "Bearer ".. app._auth.IdToken
    end

    local requestBody = requestParams.Body
    if requestBody and type(requestBody) == "table" then
        requestParams.Headers["content-type"] = "application/json"
        requestParams.Body = HttpService:JSONEncode(requestBody)
    end

    local response = HttpService:RequestAsync(requestParams)
    if response.StatusCode == 401 then
        app._auth = app._authentication:SignInWithEmailAndPassword(app.Email, app.Password):expect()
        requestParams.Headers.Authorization = "Bearer ".. app._auth.IdToken
        response = HttpService:RequestAsync(requestParams)
    end
    if response.Headers["content-type"]:find("application/json") then
        response.Body = HttpService:JSONDecode(response.Body)
    end

    return response
end

function HTTP_METATABLE:GET(serviceName, path, queries)
    return Promise.new(function(resolve, reject)
        local app = self.App

        local response = requestAsync(app, {
            Url = formatUrl(BASE_URLs[serviceName](app), path, queries),
            Method = "GET",
        })

        if response.StatusCode == 200 then
            resolve(response.Body)
        else
            reject(response.Body)
        end
    end)
end

function HTTP_METATABLE:POST(serviceName, path, queries, body)
    return Promise.new(function(resolve, reject)
        local app = self.App

        local response = requestAsync(self.App, {
            Url = formatUrl(BASE_URLs[serviceName](app), path, queries),
            Method = "POST",
            Body = body,
        })

        if response.StatusCode == 200 then
            resolve(response.Body)
        else
            reject(response.Body)
        end
    end)
end

function HTTP_METATABLE:DELETE(serviceName, path, queries, body)
    return Promise.new(function(resolve, reject)
        local app = self.App

        local response = requestAsync(self.App, {
            Url = formatUrl(BASE_URLs[serviceName](app), path, queries),
            Method = "DELETE",
            Body = body,
        })

        if response.StatusCode == 200 then
            resolve(response.Body)
        else
            reject(response.Body)
        end
    end)
end

function HTTP_METATABLE:PATCH(serviceName, path, queries, body)
    return Promise.new(function(resolve, reject)
        local app = self.App

        local response = requestAsync(self.App, {
            Url = formatUrl(BASE_URLs[serviceName](app), path, queries),
            Method = "PATCH",
            Body = body,
        })

        if response.StatusCode == 200 then
            resolve(response.Body)
        else
            reject(response.Body)
        end
    end)
end

return Http
