/**
 * Resolve the e-mail address of a lead / contact (AD_User) server-side, so the
 * mail routes never search the mailboxes for a client-supplied address.
 */
import { isValidEmail } from './leadMailbox'
import fetchHelper from '../fetchHelper'
import refreshTokenHelper from '../refreshTokenHelper'
import { isAdminRole } from '../changeLogHelper'

export const resolveLeadEmail = async (event: any, leadId: number, token: string): Promise<{ email: string; name: string }> => {
  if (!leadId) return { email: '', name: '' }
  const url = `models/ad_user/${leadId}?$select=Name,EMail`
  let u: any
  try {
    u = await fetchHelper(event, url, 'GET', token, null)
  } catch {
    const fresh = await refreshTokenHelper(event)
    u = await fetchHelper(event, url, 'GET', fresh, null)
  }
  const email = String(u?.EMail || u?.eMail || '').trim().toLowerCase()
  return { email: isValidEmail(email) ? email : '', name: String(u?.Name || u?.name || '') }
}

export interface MailAddress { email: string; label: string }

// Partner address sets are asked for once per (mailbox x address) request of the
// modal — a short cache keeps that from hitting iDempiere every time.
const PARTNER_TTL_MS = 60 * 1000
const MAX_PARTNER_ADDRESSES = 10
const partnerCache = new Map<number, { at: number; name: string; addresses: MailAddress[] }>()

/**
 * Every e-mail address of a business partner: C_BPartner.EMail / EMail_Invoice plus
 * the EMail of its active contacts (AD_User), de-duplicated, max. 10.
 */
export const resolvePartnerEmails = async (event: any, partnerId: number, token: string): Promise<{ name: string; addresses: MailAddress[] }> => {
  if (!partnerId) return { name: '', addresses: [] }
  const hit = partnerCache.get(partnerId)
  if (hit && Date.now() - hit.at < PARTNER_TTL_MS) return { name: hit.name, addresses: hit.addresses }

  const get = async (url: string) => {
    try {
      return await fetchHelper(event, url, 'GET', token, null)
    } catch {
      const fresh = await refreshTokenHelper(event)
      return await fetchHelper(event, url, 'GET', fresh, null)
    }
  }
  const bp: any = await get(`models/c_bpartner/${partnerId}?$select=Name,EMail,EMail_Invoice`)
  const users: any = await get(`models/ad_user?$filter=${encodeURIComponent(`C_BPartner_ID eq ${partnerId} AND IsActive eq true`)}&$select=Name,EMail&$orderby=${encodeURIComponent('Name asc')}&$top=50`)

  const name = String(bp?.Name || bp?.name || '')
  const addresses: MailAddress[] = []
  const add = (raw: any, label: string) => {
    const email = String(raw || '').trim().toLowerCase()
    if (!isValidEmail(email) || addresses.some((a) => a.email === email)) return
    if (addresses.length < MAX_PARTNER_ADDRESSES) addresses.push({ email, label })
  }
  add(bp?.EMail ?? bp?.eMail, name)
  add(bp?.EMail_Invoice ?? bp?.Email_Invoice ?? bp?.eMail_Invoice, name)
  for (const u of (users?.records || [])) add(u?.EMail ?? u?.eMail, String(u?.Name || u?.name || ''))

  partnerCache.set(partnerId, { at: Date.now(), name, addresses })
  return { name, addresses }
}

/**
 * Whose mail history a /api/mail/lead-emails* request is about:
 *  - `leadId`    -> the one address of that AD_User (staff, as before)
 *  - `partnerId` -> the partner's address set, ADMIN roles only; `address` picks one
 *                   of them and is only accepted when it is in the server-resolved set.
 * `email` is '' when there is nothing to search (no address / unknown address).
 */
export const resolveMailTarget = async (event: any, q: any, token: string): Promise<{ email: string; name: string; addresses: MailAddress[]; isPartner: boolean }> => {
  const partnerId = Number(q?.partnerId) || 0
  if (partnerId) {
    if (!(await isAdminRole(event, token))) throw createError({ statusCode: 403, statusMessage: 'Forbidden' })
    const { name, addresses } = await resolvePartnerEmails(event, partnerId, token)
    const want = String(q?.address || '').trim().toLowerCase()
    const email = want ? (addresses.find((a) => a.email === want)?.email || '') : ''
    return { email, name, addresses, isPartner: true }
  }
  const { email, name } = await resolveLeadEmail(event, Number(q?.leadId) || 0, token)
  return { email, name, addresses: email ? [{ email, label: name }] : [], isPartner: false }
}
