import { fullContactDisplayName, type FullContact } from "./types"

function escapeVCardValue(value: string): string {
  return value
    .replace(/\\/g, "\\\\")
    .replace(/;/g, "\\;")
    .replace(/,/g, "\\,")
    .replace(/\n/g, "\\n")
}

function escapeCsvField(value: string): string {
  if (/[",\n\r]/.test(value)) {
    return `"${value.replace(/"/g, '""')}"`
  }
  return value
}

function sanitizeFilename(name: string): string {
  return name.replace(/[/\\?%*:|"<>]/g, "-").trim() || "contact"
}

export function contactToVCard(contact: FullContact): string {
  const lines: string[] = ["BEGIN:VCARD", "VERSION:3.0"]

  const last = contact.lastName ?? ""
  const first = contact.firstName ?? ""
  const middle = contact.middleName ?? ""
  const prefix = contact.namePrefix ?? ""
  const suffix = contact.nameSuffix ?? ""
  lines.push(
    `N:${escapeVCardValue(last)};${escapeVCardValue(first)};${escapeVCardValue(middle)};${escapeVCardValue(prefix)};${escapeVCardValue(suffix)}`
  )

  const fn = fullContactDisplayName(contact) || contact.emails[0]?.value || contact.phones[0]?.value
  if (fn) lines.push(`FN:${escapeVCardValue(fn)}`)

  for (const e of contact.emails) {
    if (e.value.trim()) {
      lines.push(`EMAIL;TYPE=${escapeVCardValue(e.label || "INTERNET")}:${escapeVCardValue(e.value.trim())}`)
    }
  }

  for (const p of contact.phones) {
    if (p.value.trim()) {
      lines.push(`TEL;TYPE=${escapeVCardValue(p.label || "VOICE")}:${escapeVCardValue(p.value.trim())}`)
    }
  }

  if (contact.company?.trim()) {
    const org = contact.jobTitle?.trim()
      ? `${escapeVCardValue(contact.company.trim())};${escapeVCardValue(contact.jobTitle.trim())}`
      : escapeVCardValue(contact.company.trim())
    lines.push(`ORG:${org}`)
  } else if (contact.jobTitle?.trim()) {
    lines.push(`TITLE:${escapeVCardValue(contact.jobTitle.trim())}`)
  }

  if (contact.department?.trim()) {
    lines.push(`X-ABLabel:${escapeVCardValue(contact.department.trim())}`)
  }

  if (contact.birthday?.month && contact.birthday?.day) {
    const y = contact.birthday.year ?? 1900
    const m = String(contact.birthday.month).padStart(2, "0")
    const d = String(contact.birthday.day).padStart(2, "0")
    lines.push(`BDAY:${y}${m}${d}`)
  }

  if (contact.notes?.trim()) {
    lines.push(`NOTE:${escapeVCardValue(contact.notes.trim())}`)
  }

  lines.push("END:VCARD")
  return lines.join("\r\n")
}

export function contactsToVCard(contacts: FullContact[]): string {
  return contacts.map(contactToVCard).join("\r\n")
}

export function contactsToCsv(contacts: FullContact[]): string {
  const header = ["Name", "Email", "Phone", "Company", "Job Title", "Notes"]
  const rows = contacts.map((c) => {
    const name = fullContactDisplayName(c)
    const email = c.emails.map((e) => e.value).join("; ")
    const phone = c.phones.map((p) => p.value).join("; ")
    const company = c.company ?? ""
    const jobTitle = c.jobTitle ?? ""
    const notes = c.notes ?? ""
    return [name, email, phone, company, jobTitle, notes].map(escapeCsvField).join(",")
  })
  return [header.join(","), ...rows].join("\r\n")
}

export function downloadTextFile(content: string, filename: string, mimeType: string): void {
  const blob = new Blob([content], { type: mimeType })
  const url = URL.createObjectURL(blob)
  const link = document.createElement("a")
  link.href = url
  link.download = filename
  link.click()
  URL.revokeObjectURL(url)
}

export function downloadContactVCard(contact: FullContact): void {
  const base = sanitizeFilename(
    fullContactDisplayName(contact) || contact.emails[0]?.value || "contact"
  )
  downloadTextFile(contactToVCard(contact), `${base}.vcf`, "text/vcard;charset=utf-8")
}

export function downloadContactsVCard(contacts: FullContact[], filename = "contacts.vcf"): void {
  downloadTextFile(contactsToVCard(contacts), filename, "text/vcard;charset=utf-8")
}

export function downloadContactsCsv(contacts: FullContact[], filename = "contacts.csv"): void {
  downloadTextFile(contactsToCsv(contacts), filename, "text/csv;charset=utf-8")
}
