/**
 * migrate-recipes.js
 * ----------------------------------------------------------
 * One-time migration: update every account's Weavy recipe to the
 * Kling 2.6 Standard flow template (locked: model=Standard, version=V2.6,
 * orientation=video, service=fal_imported).
 *
 * Usage:
 *   node scripts/migrate-recipes.js              # migrate all accounts
 *   node scripts/migrate-recipes.js --active     # only active (non-archived) accounts
 *   node scripts/migrate-recipes.js --dry-run    # show what would be done, no API calls
 *   node scripts/migrate-recipes.js --delay=500  # custom delay in ms between accounts
 *
 * Writes:
 *   data/migration-log.json — full per-account result
 *   data/accounts.json     — updated with new recipeIds (if any were recreated)
 */

import { readFileSync, writeFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import { dirname, join } from "node:path";
import { ensureKling26Recipe } from "../lib/auto-token.js";

const __dirname = dirname(fileURLToPath(import.meta.url));
const ROOT = join(__dirname, "..");

const args = new Set(process.argv.slice(2));
const ACTIVE_ONLY = args.has("--active");
const DRY_RUN = args.has("--dry-run");
const delayArg = [...args].find((a) => a.startsWith("--delay="));
const DELAY_MS = delayArg ? parseInt(delayArg.split("=")[1], 10) : 1200;

const ACCOUNTS_FILE = join(ROOT, "data", "accounts.json");
const LOG_FILE = join(ROOT, "data", "migration-log.json");

const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

async function main() {
  const startTime = Date.now();
  const allAccounts = JSON.parse(readFileSync(ACCOUNTS_FILE, "utf-8"));
  const accounts = ACTIVE_ONLY ? allAccounts.filter((a) => !a.archived) : allAccounts;

  console.log("============================================================");
  console.log("  Migration → Kling 2.6 Standard");
  console.log("============================================================");
  console.log(`Total accounts      : ${allAccounts.length}`);
  console.log(`Archived            : ${allAccounts.filter((a) => a.archived).length}`);
  console.log(`Active (non-archive): ${allAccounts.filter((a) => !a.archived).length}`);
  console.log(`Migrating now       : ${accounts.length}${ACTIVE_ONLY ? " (--active only)" : ""}`);
  console.log(`Mode                : ${DRY_RUN ? "DRY-RUN (no API calls)" : "LIVE"}`);
  console.log(`Delay between calls : ${DELAY_MS}ms`);
  console.log("------------------------------------------------------------\n");

  const results = [];
  let updated = 0, recreated = 0, failed = 0, skipped = 0;

  for (let i = 0; i < accounts.length; i++) {
    const acc = accounts[i];
    const no = `[${i + 1}/${accounts.length}]`;
    const archivedTag = acc.archived ? " (archived)" : "";
    console.log(`${no} ${acc.label}${archivedTag}`);
    console.log(`     account : ${acc.id}`);
    console.log(`     recipe  : ${acc.recipeId || "(none)"}`);
    console.log(`     token   : ${acc.token ? acc.token.substring(0, 20) + "..." : "(none)"}`);

    // Skip accounts without token or recipe
    if (!acc.token || !acc.recipeId) {
      console.log(`     ⏭️  Skipped (missing token or recipeId)\n`);
      skipped++;
      results.push({ accountId: acc.id, label: acc.label, status: "skipped", reason: "missing-token-or-recipe" });
      continue;
    }

    if (DRY_RUN) {
      console.log(`     🔍 Would call: ensureKling26Recipe(token, "${acc.recipeId}")\n`);
      results.push({ accountId: acc.id, label: acc.label, status: "dry-run", recipeId: acc.recipeId });
      continue;
    }

    const logs = [];
    try {
      const newRecipeId = await ensureKling26Recipe(acc.token, acc.recipeId, (msg, level) => {
        logs.push({ msg, level });
        // Comment out to keep output clean — set VERBOSE=1 to show
        if (process.env.VERBOSE === "1") {
          console.log(`     │ ${msg}`);
        }
      });

      if (!newRecipeId) {
        console.log(`     ❌ Failed (no recipeId returned)\n`);
        failed++;
        results.push({ accountId: acc.id, label: acc.label, status: "failed", recipeId: acc.recipeId, logs });
      } else if (newRecipeId === acc.recipeId) {
        console.log(`     ✅ Updated in-place → ${newRecipeId}\n`);
        updated++;
        results.push({ accountId: acc.id, label: acc.label, status: "updated", recipeId: newRecipeId, logs });
      } else {
        console.log(`     ✅ Recreated: ${acc.recipeId} → ${newRecipeId}\n`);
        // Update the account's recipeId
        const idx = allAccounts.findIndex((a) => a.id === acc.id);
        if (idx >= 0) allAccounts[idx].recipeId = newRecipeId;
        recreated++;
        results.push({ accountId: acc.id, label: acc.label, status: "recreated", oldRecipeId: acc.recipeId, newRecipeId, logs });
      }
    } catch (err) {
      console.log(`     ❌ Error: ${err.message}\n`);
      failed++;
      results.push({ accountId: acc.id, label: acc.label, status: "error", error: err.message, logs });
    }

    // Rate limit (skip after last)
    if (i < accounts.length - 1) {
      await sleep(DELAY_MS);
    }
  }

  // Save updated accounts.json (only if not dry-run and something changed)
  if (!DRY_RUN && recreated > 0) {
    writeFileSync(ACCOUNTS_FILE, JSON.stringify(allAccounts, null, 2), "utf-8");
    console.log(`📝 accounts.json updated (${recreated} recipeId changes)`);
  }

  // Save log
  const logData = {
    runAt: new Date().toISOString(),
    dryRun: DRY_RUN,
    activeOnly: ACTIVE_ONLY,
    delayMs: DELAY_MS,
    summary: { total: accounts.length, updated, recreated, failed, skipped },
    results,
  };
  writeFileSync(LOG_FILE, JSON.stringify(logData, null, 2), "utf-8");
  console.log(`📝 Log written to ${LOG_FILE.replace(ROOT + "\\", "")}`);

  const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
  console.log("\n============================================================");
  console.log("  Migration Summary");
  console.log("============================================================");
  console.log(`✅ Updated in-place : ${updated}`);
  console.log(`🔁 Recreated       : ${recreated}`);
  console.log(`❌ Failed          : ${failed}`);
  console.log(`⏭️  Skipped         : ${skipped}`);
  console.log(`⏱️  Duration        : ${elapsed}s`);
  console.log("============================================================\n");

  if (failed > 0) {
    console.log("⚠️  Some accounts failed. Possible reasons:");
    console.log("   • Token expired → run auto-revive first");
    console.log("   • Weavy rate limit → increase --delay");
    console.log("   • Network issue → re-run this script");
  }
}

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