/**
 * Post-Migration Verification
 *
 * Checks that the database and storage are intact after migration.
 *
 * Usage:
 *   DATABASE_URL="postgresql://..." \
 *   STORAGE_ENDPOINT="https://..." \
 *   STORAGE_ACCESS_KEY="..." \
 *   STORAGE_SECRET_KEY="..." \
 *   STORAGE_BUCKET="echos-ocr" \
 *   npx tsx scripts/verify-migration.ts
 */

import "dotenv/config";
import pg from "pg";
import { S3Client, ListObjectsV2Command, HeadObjectCommand } from "@aws-sdk/client-s3";

const pool = new pg.Pool({
  connectionString: process.env.DATABASE_URL,
  max: 3,
});

const s3 = new S3Client({
  endpoint: process.env.STORAGE_ENDPOINT || "",
  region: process.env.STORAGE_REGION || "us-east-1",
  credentials: {
    accessKeyId: process.env.STORAGE_ACCESS_KEY || "",
    secretAccessKey: process.env.STORAGE_SECRET_KEY || "",
  },
  forcePathStyle: true,
});

const BUCKET = process.env.STORAGE_BUCKET || "echos-ocr";

async function countTable(table: string): Promise<number> {
  const res = await pool.query(`SELECT count(*)::int as cnt FROM "${table}"`);
  return res.rows[0].cnt;
}

async function countStorageObjects(prefix: string): Promise<number> {
  let count = 0;
  let continuationToken: string | undefined;

  do {
    const res = await s3.send(
      new ListObjectsV2Command({
        Bucket: BUCKET,
        Prefix: prefix,
        ContinuationToken: continuationToken,
      })
    );
    count += res.KeyCount || 0;
    continuationToken = res.NextContinuationToken;
  } while (continuationToken);

  return count;
}

async function spotCheck(): Promise<{ checked: number; ok: number; missing: number }> {
  const res = await pool.query(`
    SELECT id, "frontImagePath", "backImagePath"
    FROM "ResponseCard"
    WHERE "frontImagePath" IS NOT NULL OR "backImagePath" IS NOT NULL
    ORDER BY "createdAt" DESC
    LIMIT 10
  `);

  let checked = 0;
  let ok = 0;
  let missing = 0;

  for (const row of res.rows) {
    for (const path of [row.frontImagePath, row.backImagePath]) {
      if (!path) continue;
      checked++;
      try {
        await s3.send(new HeadObjectCommand({ Bucket: BUCKET, Key: path }));
        ok++;
      } catch {
        console.log(`  MISSING: ${path} (card ${row.id})`);
        missing++;
      }
    }
  }

  return { checked, ok, missing };
}

async function main() {
  console.log("=== Post-Migration Verification ===\n");

  console.log("--- Database Row Counts ---");
  const tables = [
    "User", "Organization", "OrgMember", "Location",
    "ResponseCard", "ProcessingJob", "ActivityLog",
    "Notification", "Integration", "AppSettings",
  ];
  for (const table of tables) {
    try {
      const count = await countTable(table);
      console.log(`  ${table.padEnd(20)} ${count}`);
    } catch (err) {
      console.log(`  ${table.padEnd(20)} ERROR: ${(err as Error).message}`);
    }
  }

  console.log("\n--- Storage Object Counts ---");
  const imageCount = await countStorageObjects("images/");
  const sourceCount = await countStorageObjects("sources/");
  console.log(`  images/   ${imageCount}`);
  console.log(`  sources/  ${sourceCount}`);

  console.log("\n--- Spot Check: 10 newest cards ---");
  const spotResult = await spotCheck();
  console.log(`  Checked: ${spotResult.checked}, OK: ${spotResult.ok}, Missing: ${spotResult.missing}`);

  if (spotResult.missing > 0) {
    console.log("\n  WARNING: Some storage objects are missing. Storage migration may be incomplete.");
  } else {
    console.log("\n  All spot-checked objects found in storage.");
  }

  console.log("\n=== Verification Complete ===");
  await pool.end();
}

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