/**
 * One-time script: migrates email/password hashes from a Clerk CSV export into
 * BetterAuth's accounts table.
 *
 * Usage:
 *   DATABASE_URL=... CLERK_SECRET_KEY=... node scripts/migrate-clerk-passwords.mjs
 *
 * Before running:
 *   1. Go to Clerk dashboard → Users → Export → Download CSV
 *   2. Save the file as exported_users.csv in the project root
 *
 * The script is idempotent — safe to run multiple times.
 * Delete exported_users.csv after confirming the migration succeeded.
 */

import { readFileSync, existsSync } from "fs";
import { resolve } from "path";
import postgres from "postgres";

const DATABASE_URL = process.env.DATABASE_DIRECT_URL || process.env.DATABASE_URL;
if (!DATABASE_URL) {
  console.error("ERROR: DATABASE_URL (or DATABASE_DIRECT_URL) is required");
  process.exit(1);
}

const CSV_PATH = resolve(process.cwd(), "exported_users.csv");
if (!existsSync(CSV_PATH)) {
  console.error(`ERROR: exported_users.csv not found at ${CSV_PATH}`);
  console.error("Export users from the Clerk dashboard (Users → Export) and save as exported_users.csv");
  process.exit(1);
}

const sql = postgres(DATABASE_URL, { max: 1 });

try {
  await migratePasswords();
} catch (err) {
  console.error("Migration failed:", err);
  await sql.end().catch(() => {});
  process.exit(1);
}

await sql.end().catch(() => {});
process.exit(0);

// ─────────────────────────────────────────────────────────────────────────────

function parseCSV(content) {
  const lines = content.split("\n").filter((line) => line.trim());
  if (lines.length < 2) return [];

  const headers = lines[0].split(",").map((h) => h.trim().replace(/^"|"$/g, ""));

  return lines.slice(1).map((line) => {
    // Handle quoted fields that may contain commas
    const values = [];
    let current = "";
    let inQuotes = false;
    for (const char of line) {
      if (char === '"') {
        inQuotes = !inQuotes;
      } else if (char === "," && !inQuotes) {
        values.push(current.trim());
        current = "";
      } else {
        current += char;
      }
    }
    values.push(current.trim());

    return headers.reduce((obj, header, i) => {
      obj[header] = (values[i] ?? "").replace(/^"|"$/g, "");
      return obj;
    }, {});
  });
}

async function migratePasswords() {
  const csvContent = readFileSync(CSV_PATH, "utf-8");
  const rows = parseCSV(csvContent);
  console.log(`Parsed ${rows.length} users from CSV`);

  // Only process rows with a password hash
  const passwordRows = rows.filter((r) => r.password_digest && r.password_hasher === "bcrypt");
  console.log(`Found ${passwordRows.length} users with bcrypt password hashes`);

  if (passwordRows.length === 0) {
    console.log("Nothing to migrate.");
    return;
  }

  let created = 0;
  let skipped = 0;
  let notFound = 0;

  for (const row of passwordRows) {
    const clerkId = row.id;
    const passwordHash = row.password_digest;

    // Find the user in our DB by their Clerk ID
    const [dbUser] = await sql`
      SELECT id FROM users WHERE clerk_id = ${clerkId} LIMIT 1
    `;

    if (!dbUser) {
      notFound++;
      continue;
    }

    // Check if a credential account already exists for this user
    const [existing] = await sql`
      SELECT 1 FROM accounts
      WHERE user_id = ${dbUser.id}::uuid AND provider_id = 'credential'
      LIMIT 1
    `;

    if (existing) {
      skipped++;
      continue;
    }

    // Insert credential account with the migrated bcrypt hash
    await sql`
      INSERT INTO accounts (id, account_id, provider_id, user_id, password, created_at, updated_at)
      VALUES (
        gen_random_uuid()::text,
        ${dbUser.id},
        'credential',
        ${dbUser.id}::uuid,
        ${passwordHash},
        now(),
        now()
      )
    `;
    created++;
  }

  console.log(`Done: ${created} credential accounts created, ${skipped} already existed, ${notFound} Clerk users not found in DB`);
  if (notFound > 0) {
    console.log("  (notFound users may have been deleted or never synced via webhook)");
  }
  console.log("\nIMPORTANT: Delete exported_users.csv now — it contains password hashes.");
}
