/**
 * Migration script to upload card hashes from SQLite to Convex.
 *
 * Usage:
 *   npx tsx scripts/migrate-hashes.ts
 *
 * Prerequisites:
 *   - Run `npx convex dev` first to set up the Convex project
 *   - Ensure CONVEX_URL is set in .env.local
 */

import { ConvexHttpClient } from "convex/browser";
import Database from "better-sqlite3";
import { api } from "../convex/_generated/api";
import * as dotenv from "dotenv";
import * as path from "path";
import * as fs from "fs";

// Load environment variables
dotenv.config({ path: path.join(__dirname, "..", ".env.local") });

const CONVEX_URL = process.env.EXPO_PUBLIC_CONVEX_URL || process.env.CONVEX_URL;
const DB_PATH =
  process.env.DB_PATH || path.join(__dirname, "..", "card_hashes.db");
const BATCH_SIZE = 50;
const HASH_VERSION = 1;

interface CardRow {
  id: string;
  oracle_id: string;
  name: string;
  set_code: string;
  collector_number: string | null;
  rarity: string | null;
  artist: string | null;
  image_uri: string | null;
  hash: Buffer;
}

async function main() {
  if (!CONVEX_URL) {
    console.error("Error: CONVEX_URL not set in .env.local");
    console.error("Run 'npx convex dev --once --configure=new' first");
    process.exit(1);
  }

  if (!fs.existsSync(DB_PATH)) {
    console.error(`Error: Database not found at ${DB_PATH}`);
    process.exit(1);
  }

  console.log(`Connecting to Convex: ${CONVEX_URL}`);
  console.log(`Reading from SQLite: ${DB_PATH}`);

  const client = new ConvexHttpClient(CONVEX_URL);
  const db = new Database(DB_PATH, { readonly: true });

  try {
    // Get total count
    const countRow = db
      .prepare("SELECT COUNT(*) as count FROM cards WHERE hash IS NOT NULL")
      .get() as { count: number };
    const totalCards = countRow.count;
    console.log(`Found ${totalCards} cards with hashes to migrate`);

    // Query cards with hashes
    const stmt = db.prepare(`
      SELECT id, oracle_id, name, set_code, collector_number, rarity, artist, image_uri, hash
      FROM cards
      WHERE hash IS NOT NULL
      ORDER BY name
    `);

    const cards = stmt.all() as CardRow[];
    let migrated = 0;
    let errors = 0;

    // Process in batches
    for (let i = 0; i < cards.length; i += BATCH_SIZE) {
      const batch = cards.slice(i, i + BATCH_SIZE);
      const convexCards = batch.map((card) => ({
        scryfallId: card.id,
        oracleId: card.oracle_id,
        name: card.name,
        setCode: card.set_code,
        collectorNumber: card.collector_number || "",
        rarity: card.rarity || "common",
        artist: card.artist || undefined,
        imageUri: card.image_uri || undefined,
        hash: new Uint8Array(card.hash).buffer as ArrayBuffer,
        hashVersion: HASH_VERSION,
      }));

      try {
        await client.mutation(api.cards.insertBatch, { cards: convexCards });
        migrated += batch.length;
        const pct = ((migrated / totalCards) * 100).toFixed(1);
        process.stdout.write(`\rMigrated ${migrated}/${totalCards} (${pct}%)`);
      } catch (err) {
        console.error(`\nError migrating batch starting at ${i}:`, err);
        errors += batch.length;
      }
    }

    console.log(`\n\nMigration complete!`);
    console.log(`  Migrated: ${migrated}`);
    console.log(`  Errors: ${errors}`);
  } finally {
    db.close();
  }
}

main().catch((err) => {
  console.error("Migration failed:", err);
  process.exit(1);
});
