local common = require "interactionmanip.common"
local utf8 = require "icu.utf8"
local web_sanitize = require "web_sanitize"
local mail = {}

local function FormatMailAddress (email, name)
	if name and name:len() > 0 and name ~= email then
		local address = ("'%s' <%s>"):format(name, email)
		return address
	else
		return email
	end
end

local function GetFirstMailEvent (interaction)
	assert(interaction)
	--LogDebug("[INTERACTIONMAINIP.GetFirstMailEvent] interaction: '%s',  ", json.encode(interaction))
	if not interaction.events then
		return
	end
	local firstMailEvent
	for i, event in ipairs(interaction.events) do
		if not common.isAutoResponseEvent(interaction, i) then
			firstMailEvent = event
			break
		end
	end
	--LogDebug("[INTERACTIONMAINIP.GetFirstMailEvent] interaction: '%s', firstMailEvent '%s'", interaction.id, json.encode(firstMailEvent or {}))
	return firstMailEvent
end

function mail.module_type ()
	return "mail"
end

function mail.getPlainBody (interaction, index)
	assert(type(index) == "number")
	if not interaction.events or not interaction.events[index] then
		return ""
	end
	local plainBody = mail.getBodyPart(interaction, index, "text/plain")
	if not plainBody then
		plainBody = mail.getBodyPart(interaction, index, "text/html")
		if not plainBody then
			return ""
		end
	end
	local sanitizedPlainBody = web_sanitize.extract_text(plainBody)
	--LogDebug("[INTERACTIONMAINIP.mail.getPlainBody] ---> interaction: '%s' event: '%s'\nplainBody: %s\nsanitizedPlainBody: %s.", interaction.id, index, plainBody, sanitizedPlainBody)
	return sanitizedPlainBody, plainBody
end

function mail.getBodyPart (interaction, index, content_type)
	assert(type(index) == "number")
	assert(type(content_type) == "string")
	content_type = content_type:lower()

	if not interaction.events or not interaction.events[index] then
		return nil
	end
	local event = interaction.events[index]
	if not event.body then return nil end

	if type(event.body) == "string" then return event.body end
	-- body is an array of parts
	for _, part in ipairs(event.body) do
		if part.type:lower() == content_type then
			return part.content
		end
	end
end

---
-- Dado un mail, trata de devolver un nombre, sacandolo del from o del to, segun 
-- sea inbound u outbound. Si no puede sacar un nombre, usa contactAddress.
-- TODO: No tendria que usar, si existe, el nombre del contacto?
-- segundo, por que puta esto se llama HumanReadableAddress??? Address!!!
function mail.getHumanReadableAddress (interaction, index)
	if not interaction.events or not interaction.events[index] then
		return interaction.contactAddress
	end
	if interaction.initiative == "OUTBOUND" then
		return interaction.events[1].to
		else
		local event = interaction.events[1]
		if event.name and #event.name > 0 then
			return event.name
		else
			return event.from
		end
	end
end

---
-- esta función devuelve true si al menos un evento de la interaccion tiene attachments
function mail.hasAttachments (interaction)
	if interaction.events then
		for _, event in ipairs(interaction.events) do
			if event.attachments and #event.attachments > 0 then
				for _, attachment in ipairs(event.attachments) do
					local current_content_disposition = attachment["content-disposition"] or "attachment"
					if current_content_disposition == "attachment" then
						return true
					end
				end
			end
		end
	end
	return false
end

---
-- esta función retorna la cantidad adjuntos del primero mail de la cadena
function mail.loadFirstMailAttachmentsCount (interaction)
	assert(interaction)
	--LogDebug("[INTERACTIONMAINIP.mail.loadFirstMailAttachmentsCount] Loading Total Attachments for first event of the interaction: '%s'", interaction.id)
	local firstMailEvent = GetFirstMailEvent(interaction)
	if not firstMailEvent then
		return
	end
	interaction.__firstMailAttachmentsCount = type(firstMailEvent.attachments) == "table" and #firstMailEvent.attachments or 0
	--LogDebug("[INTERACTIONMAINIP.mail.loadFirstMailAttachmentsCount] Total Attachments '%d' for first event of the interaction: '%s'", interaction.__firstMailAttachmentsCount, interaction.id)
end

---
-- Takes an interaction and precomputes properties based on events
--
function mail.updateInteraction (interaction)
	interaction.properties = interaction.properties or {}

	mail.updateReaders(interaction)
	mail.updateLabels(interaction)
	mail.isTransferred(interaction)
	mail.getLastAgentEndsConversation(interaction)
	mail.getLastStep(interaction)

	interaction.properties.subject = ""
	-- compute the subject, using the mail's subject plus a part of the body
	if interaction.events then
		interaction.properties.subject = utf8.sub(interaction.events[1].subject or "", 1, 150)
		interaction.properties.summary = interaction.events[1].subject or ""

		--Por temas de consumo del WH se quita el parseo del body.
		--local plain_body = mail.getPlainBody(interaction, 1)
		--local body_snippet = utf8.sub(plain_body, 1, 150)
		--interaction.properties.summary = interaction.properties.summary .. "\r\n" .. tostring(body_snippet)

		interaction.properties.human_readable_address = mail.getHumanReadableAddress(interaction, 1)
		interaction.properties.has_attachments = mail.hasAttachments(interaction)
		interaction.properties.event_count = mail.getEventsCountWithoutAutoResponse(interaction)
		interaction.properties.unread_event_count = mail.getUnreadEventCount(interaction)
		interaction.properties.unanswered_event_count = mail.getUnAnsweredContactEventCount(interaction)
	else
		-- provide some defaults
		interaction.properties.has_attachments = false
		interaction.properties.event_count = 0
		interaction.properties.unread_event_count = 0
		interaction.properties.unanswered_event_count = 0
	end

	return interaction
end

---
-- Takes an interaction and returns a block of text to be sent to the search engine
--
function mail.getSearchableContent (interaction)
	if not interaction.events then return "" end
	local data = {
		interaction.properties.subject
	}
	for i=1, #interaction.events do
		if not mail.isAutoResponseEvent(interaction, i) then
			local sanitizedPlainBody, plainBody = mail.getPlainBody(interaction, i)
			--LogDebug("[INTERACTIONMAINIP.mail.getSearchableContent] ---> interaction.id: '%s', event: %s, sanitizedPlainBody type: '%s'.", interaction.id, i, type(sanitizedPlainBody))
			table.insert(data, sanitizedPlainBody)
		end
	end
	if interaction.comments then
		for _, comment in pairs(interaction.comments) do
			table.insert(data, comment.comment)
			table.insert(data, comment.authorName)
		end
	end
	return table.concat(data, " ")
end

--[[
	Esta función retorna ????????????.

	La misma es utilizada desde la rocka de los reportes "reporter.redis_values".
--]]
function mail.loadDisplayFirstMailFrom (interaction)
	assert(interaction)

	--LogDebug("[INTERACTIONMAINIP.loadDisplayFirstMailFrom] interaction: '%s',  ", json.encode(interaction))

	local firstMailEvent = GetFirstMailEvent(interaction)
	if not firstMailEvent then
		return
	end

	if firstMailEvent.agent then
		interaction.__displayFirstMailFrom = firstMailEvent.agent
	else
		interaction.__displayFirstMailFrom = FormatMailAddress(firstMailEvent.from, firstMailEvent.name)
	end

	--LogDebug("[INTERACTIONMAINIP.loadDisplayFirstMailFrom] interaction: '%s',  interaction.__displayFirstMailFrom '%s'", interaction.id, interaction.__displayFirstMailFrom)

	return interaction
end

--[[
	Esta función retorna ????????????.

	La misma es utilizada desde la rocka de los reportes "reporter.redis_values".
--]]
function mail.loadDisplayFirstMailTo (interaction)
	assert(interaction)

	--LogDebug("[INTERACTIONMAINIP.loadDisplayFirstMailTo] interaction: '%s',  ", json.encode(interaction))
	local firstMailEvent = GetFirstMailEvent(interaction)
	if not firstMailEvent then
		return
	end

	local addresses = firstMailEvent.to
	if not addresses then
		return
	end

	local displayFirstMailTo
	if type(addresses) == "table" then
		--LogDebug("table addresses: %s", json.encode(addresses))
		-- Sample: {"cany.Prueba@outlook.com":"Test inconcert"}
		for emailAddress, emailInfo in pairs(addresses) do
			displayFirstMailTo = displayFirstMailTo or ""
			if displayFirstMailTo:len() > 0 then
				displayFirstMailTo = displayFirstMailTo .. "; "
			end
			displayFirstMailTo = displayFirstMailTo .. FormatMailAddress(emailAddress, emailInfo);
		end
	elseif type(addresses) == "string" then
		--LogDebug("string addresses: %s", addresses)
		-- Sample: emma@inconcertcc.com
		displayFirstMailTo = addresses
	end

	interaction.__displayFirstMailTo = displayFirstMailTo
	--LogDebug("[INTERACTIONMAINIP.loadDisplayFirstMailTo] interaction: '%s',  interaction.__displayFirstMailTo '%s'", interaction.id, interaction.__displayFirstMailTo)

	return interaction
end

--[[
	Esta función retorna ????????????.

	La misma es utilizada desde la rocka de los reportes "reporter.redis_values".
--]]
function mail.loadFirstMailSubject (interaction)
	assert(interaction)

	--LogDebug("[INTERACTIONMAINIP.loadFirstMailSubject] interaction: '%s',  ", json.encode(interaction))
	local firstMailEvent = GetFirstMailEvent(interaction)
	if not firstMailEvent then
		return
	end
	interaction.__firstMailSubject = firstMailEvent.subject
	--LogDebug("[INTERACTIONMAINIP.loadFirstMailSubject] interaction: '%s',  interaction.__firstMailSubject '%s'", interaction.id, interaction.__firstMailSubject)

	return interaction
end

--[[
	ATENCION:
		En las interacciones de mail no se puede hacer el conteo de palabras de forma exacta, ya que el el plain text queda con muchas palabras que el usuarios NO ha escrito.
--]]
function mail.calculateConversationTotalCharacters (interaction)
	assert(interaction)
	--LogDebug("[INTERACTIONMAINIP.mail.calculateConversationTotalCharacters] ENTRA interaction: '%s' ", interaction.id)
	--LogDebug("[INTERACTIONMAINIP.mail.calculateConversationTotalCharacters] interaction: '%s' ", json.encode(interaction))
	--LogDebug("[INTERACTIONMAINIP.mail.calculateConversationTotalCharacters] interaction.events: '%s' ", json.encode(interaction.events or {}))

	local function MustCalculate (interaction, eventIndex)
		if common.isAutoResponseEvent(interaction, eventIndex) then
			LogDebug("[INTERACTIONMAINIP.mail.calculateConversationTotalCharacters] NO calculate characters for autoresponse.")
			return false
		end
		return true
	end

	local totalCharacters = 0
	for i in pairs(interaction.events or {}) do
		if MustCalculate(interaction, i) then
			local plainBody = mail.getPlainBody(interaction, i)
			local length = #plainBody
			totalCharacters = totalCharacters + length
			--LogDebug("[INTERACTIONMAINIP.mail.calculateConversationTotalCharacters] length: '%s' in event: %s.", length, i)
		end
	end

	--LogDebug("[INTERACTIONMAINIP.mail.calculateConversationTotalCharacters] SALE totalCharacters: '%s', interaction: '%s' ", totalCharacters, interaction.id)
	return totalCharacters 
end

------------------------------------------------
mail.isTransferred                        = common.isTransferred
mail.isTaken                              = common.isTaken
mail.isWrappedUp                          = common.isWrappedUp
mail.isFinished                           = common.isFinished
mail.getConversationOwner                 = common.getConversationOwner
mail.getFirstAssignedAgent                = common.getFirstAssignedAgent
mail.getLastAgentEndsConversation         = common.getLastAgentEndsConversation
mail.getLastEventTimestamp                = common.getLastEventTimestamp
mail.updateReaders                        = common.updateReaders
mail.updateLabels                         = common.updateLabels
mail.getLastStep                          = common.getLastStep
mail.isAutoResponseEvent                  = common.isAutoResponseEvent
mail.getUnreadEventCount                  = common.getUnreadEventCount
mail.getUnAnsweredContactEventCount		 = common.getUnAnsweredContactEventCount
mail.getEventsCountWithoutAutoResponse    = common.getEventsCountWithoutAutoResponse
mail.getAllEventsCount                    = common.getAllEventsCount
mail.newInteractionEvent                  = common.newInteractionEvent
mail.newInteractionEvents                 = common.newInteractionEvents
mail.getSocialNetworkPostId               = common.getSocialNetworkPostId
mail.getBatchId                           = common.getBatchId
mail.getFirstTransferringInfo             = common.getFirstTransferringInfo
mail.getFirstResponseOfAgent              = common.getFirstResponseOfAgent
mail.loadFirstPendingStep                 = common.loadFirstPendingStep
mail.loadStatusInteraction                = common.loadStatusInteraction
mail.loadFirstTakenStep                   = common.loadFirstTakenStep
mail.loadStartAttention                   = common.loadStartAttention
mail.loadTicket                           = common.loadTicket
mail.loadFirstAgentResponse               = common.loadFirstAgentResponse
mail.loadLastAgentResponse                = common.loadLastAgentResponse
mail.getConversationTotals                = common.getConversationTotals
mail.calculateConversationTimeSec         = mail.calculateConversationTimeSec or common.calculateConversationTimeSec
mail.calculateConversationTotalCharacters = mail.calculateConversationTotalCharacters or common.calculateConversationTotalCharacters

return mail
