import { writeFileSync } from "node:fs"
import { Openmagicline } from "openmagicline"

// ---------------------------------------------------------------------------
// Config – set via environment variables or edit directly below
// ---------------------------------------------------------------------------
const GYM = process.env.MAGICLINE_GYM ?? "dieheldin"
const USERNAME = process.env.MAGICLINE_USER ?? "tanja.wild"
const PASSWORD = process.env.MAGICLINE_PASS ?? "Luna22111993"

if (!GYM || !USERNAME || !PASSWORD) {
  console.error(
    "Missing credentials. Set MAGICLINE_GYM, MAGICLINE_USER, and MAGICLINE_PASS.",
  )
  process.exit(1)
}

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

/** Escape a value for use in a CSV cell. */
function csvCell(value: unknown): string {
  if (value === null || value === undefined) return ""
  const str = String(value)
  if (str.includes(",") || str.includes('"') || str.includes("\n")) {
    return `"${str.replace(/"/g, '""')}"`
  }
  return str
}

/** Escape a value for use in HTML table cell content. */
function htmlEscape(value: unknown): string {
  if (value === null || value === undefined) return ""
  return String(value)
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
}

// ---------------------------------------------------------------------------
// Main
// ---------------------------------------------------------------------------

const mgl = new Openmagicline({ gym: GYM, username: USERNAME, password: PASSWORD })
await mgl.login()
console.log("Logged in.")

// Fetch the real facility/organization unit ID — searching with facility:0 returns nothing.
const facilityId = await mgl.util.getDefaultUnitID()
console.log(`Using facility ID: ${facilityId}`)

const SEARCH_CAP = 50

const seen = new Set<number>()
const customers: Record<string, unknown>[] = []

async function sweep(prefix: string): Promise<void> {
  const results = await mgl.customer.search(prefix, {
    facility: facilityId,
    showAllFacilities: false,
    searchInName: false,
    searchInCustomerNumber: true,
  })

  if (results.length === SEARCH_CAP) {
    for (const d of "0123456789") {
      await sweep(prefix + d)
    }
    return
  }

  for (const c of results) {
    if (!seen.has(c.databaseId) && c.customerStatus === 1) {
      seen.add(c.databaseId)
      customers.push(c as unknown as Record<string, unknown>)
    }
  }
}

for (const d of "0123456789") {
  const prefix = `1-${d}`
  process.stdout.write(`Sweeping '${prefix}'… `)
  const before = customers.length
  await sweep(prefix)
  console.log(`+${customers.length - before} (total: ${customers.length})`)
}

if (customers.length === 0) {
  console.error("No customers found.")
  process.exit(1)
}

// Collect the union of all keys across all customer records
const allKeys = Array.from(
  customers.reduce((keys, c) => {
    for (const k of Object.keys(c)) keys.add(k)
    return keys
  }, new Set<string>()),
)

// ---------------------------------------------------------------------------
// CSV export
// ---------------------------------------------------------------------------

const csvLines = [
  allKeys.map(csvCell).join(","),
  ...customers.map((c) => allKeys.map((k) => csvCell(c[k])).join(",")),
]
const csvPath = "customers.csv"
writeFileSync(csvPath, csvLines.join("\n"), "utf-8")
console.log(`CSV written to ${csvPath} (${customers.length} rows)`)

// ---------------------------------------------------------------------------
// HTML export
// ---------------------------------------------------------------------------

const headerCells = allKeys.map((k) => `<th>${htmlEscape(k)}</th>`).join("")
const bodyRows = customers
  .map(
    (c) =>
      `<tr>${allKeys.map((k) => `<td>${htmlEscape(c[k])}</td>`).join("")}</tr>`,
  )
  .join("\n")

const html = `<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>Customers – ${new Date().toLocaleDateString()}</title>
  <style>
    body { font-family: sans-serif; font-size: 13px; padding: 1rem; }
    h1 { margin-bottom: 0.5rem; }
    p.meta { color: #666; margin-bottom: 1rem; }
    table { border-collapse: collapse; width: 100%; }
    th, td { border: 1px solid #ccc; padding: 4px 8px; text-align: left; white-space: nowrap; }
    th { background: #f0f0f0; position: sticky; top: 0; }
    tr:nth-child(even) { background: #fafafa; }
  </style>
</head>
<body>
  <h1>Customer Export</h1>
  <p class="meta">Generated: ${new Date().toISOString()} &nbsp;|&nbsp; Total: ${customers.length}</p>
  <table>
    <thead><tr>${headerCells}</tr></thead>
    <tbody>
${bodyRows}
    </tbody>
  </table>
</body>
</html>`

const htmlPath = "customers.html"
writeFileSync(htmlPath, html, "utf-8")
console.log(`HTML written to ${htmlPath}`)
