local request = require "luis.request"

module(..., package.seeall)

local m_instanceOwner
function SetOwner (instanceOwner)
	m_instanceOwner = instanceOwner
end

local m_defaultAppVersion = "2022-10-01-preview"

local function GetBaseURI (id)
	id = id or "AZUREACCOUNTS"
	return m_instanceOwner:GetBaseURI(id)
end

-- *******************************************************************************
-- API AZURE ACCOUNTS
-- *******************************************************************************

function LoadVCCTenant (vcc)
	local api = require "luis"
	return api.LoadVCCTenantAzureAccount(vcc)
end

function LoadVCCAccounts (vcc)
	local api = require "luis"
	return api.LoadVCCAzureAccounts(vcc)
end

function LoadDefaultTenantAzureAccount ()
	return {
		tenant_id = "359e9065-2b08-4aae-9504-38e2a3b4b356",
		client_id = "d336fabc-9804-4186-8f8f-b40c52f39c6e",
		client_secret = "J]Z/1@x/4PJXG9K1+SIj96GaIQ:iLS1s",
		resource = "https://management.azure.com/"
	}
end

function GetAzureResourceManagerToken (tenantInfo)
	assert(type(tenantInfo) == "table")
	assert(type(tenantInfo.tenant_id) == "string")
	assert(type(tenantInfo.client_id) == "string")
	assert(type(tenantInfo.client_secret) == "string")
	assert(type(tenantInfo.resource) == "string")

	local uri = "https://login.microsoftonline.com/%s/oauth2/token"
	uri = string.format(uri, tenantInfo.tenant_id)

	local additionalHeaders = {
		["Cache-Control"] = "no-cache"
	}

	local body = "grant_type=client_credentials&" ..
		"client_id=%s&" ..
		"client_secret=%s&" ..
		"resource=%s"

	body = string.format(body, tenantInfo.client_id, request.UrlEncode(tenantInfo.client_secret), request.UrlEncode(tenantInfo.resource))

	local contentType = "application/x-www-form-urlencoded"

	local success, response = request.Post(uri, body, contentType, additionalHeaders)
	if not success then
		local err = response
		LogError("[LUIS_AZURE:GetAzureResourceManagerToken] Get an Azure Resource Manager token. Error: '%s'", json.encode(err))
		return false, err
	end

	LogInfo("[LUIS_AZURE:GetAzureResourceManagerToken] Success Get an Azure Resource Manager token:\n%s.", json.encode(response))
	local encodedTokenInfo = response[1]
	--LogDebug("[LUIS_AZURE:GetAzureResourceManagerToken] encodedTokenInfo: '%s'", encodedTokenInfo)

	return true, json.decode(encodedTokenInfo)
end

--[[

]]--
function LoadAzureAccountAndToken (vcc)
	assert(type(vcc) == "string")

	local vccAzureAccounts, total = LoadVCCAccounts(vcc)
	if total == 0 then
		local err = {reason = "VCC has not assigned Azure Accounts", vcc = vcc}
		LogError("[LUIS_AZURE:LoadAzureAccountAndToken] VCC %s has not assigned Azure Accounts.", vcc)
		return false, err
	end
	local vccAzureSubscriptionId = next(vccAzureAccounts)
	local vccAzureAccount = vccAzureAccounts[vccAzureSubscriptionId]

	--LogDebug("1 LoadAzureAccountAndToken vccAzureAccount %s -> %s", vcc, json.encode(vccAzureAccount))

	local vccTenants, total = LoadVCCTenant(vcc)
	if total == 0 then
		local err = {reason = "VCC has not assigned Tenant Azure Accounts", vcc = vcc}
		LogError("[LUIS_AZURE:LoadAzureAccountAndToken] VCC %s has not assigned Tenant Azure Accounts.", vcc)
		return false, err
	end
	local vccTenantId = next(vccTenants)
	local tenantInfo = vccTenants[vccTenantId]
	LogDebug("2 LoadAzureAccountAndToken tenantInfo %s -> %s", vcc, json.encode(tenantInfo))

	local success, tokenInfo = GetAzureResourceManagerToken(tenantInfo)
--	LogDebug("[LoadAzureAccountAndToken] Azure Resource Manager Token. success: '%s', token: '%s'", success, tokenInfo)

	if not success then
		local err = tokenInfo
		LogError("[LUIS_AZURE:LoadAzureAccountAndToken] Error Retrieving Azure Token. Error: '%s'", err)
		return false, err
	end

	--LogDebug("[LUIS_AZURE:LoadAzureAccountAndToken] Success Loaded Azure Account & Token. Azure '%s', Token: '%s'.", json.encode(vccAzureAccounts), json.encode(tokenInfo))

	return true, vccAzureAccount, tokenInfo, vccTenants
end

function LoadAzureAccounts (tenantInfo)
	assert(type(tenantInfo) == "table")
	assert(type(tenantInfo.tenant_id) == "string")
	assert(type(tenantInfo.client_id) == "string")
	assert(type(tenantInfo.client_secret) == "string")
	assert(type(tenantInfo.resource) == "string")

	local success, tokenInfo = GetAzureResourceManagerToken(tenantInfo)
	LogDebug("[LUIS_AZURE:LoadAzureAccounts] Azure Resource Manager Token. success: '%s', token: '%s'", success, tokenInfo)

	if not success then
		local err = tokenInfo
		LogError("[LUIS_AZURE:LoadAzureAccounts] Error Retrieving Azure Token. Error: '%s'", err)
		return false, err
	end

	-- "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJ .... .... ... qaApUOSYbuMKsiD9Z7088dXwA"
	local additionalHeaders = {
		["Authorization"] = tokenInfo.token_type .. " " .. tokenInfo.access_token
	}

	local uri = GetBaseURI()

	local success, response = request.Get(uri, additionalHeaders)
	if not success then
		LogError("[LUIS_AZURE:LoadAzureAccounts] Error Loading Azure Accounts Error: '%s'", json.encode(response))
		return false, response
	end

	LogInfo("[LUIS_AZURE:LoadAzureAccounts] Success Loaded Azure Accounts.")
	local encodedAzureAccounts = table.concat(response)
	--LogDebug("[LUIS_AZURE:LoadAzureAccounts] encodedAzureAccounts: '%s'", encodedAzureAccounts)

	return true, encodedAzureAccounts
end
