import dotenv from "dotenv";
import { createDBPool } from "@/internal/datastore/index";
import { EDMService } from "@/v1/services/admin/edm/edm.service";
import { EDMRepository } from "@/internal/edm/edm.repository";
import { EDM_ASSET_ROOT } from "@/lib/storage/edm-storage";

dotenv.config();

/**
 * Repair asset URLs already saved into templates.
 *
 * A misconfigured EDM_ASSET_BASE_URL (set to a bare host, with no scheme and no
 * bucket) produced image sources like:
 *
 *   storage.googleapis.com/console2-edm-assets/…
 *
 * That is a RELATIVE path. A mail client resolves it against its own origin and
 * the image is broken in every inbox, while the console preview still renders
 * it because the page has an origin to resolve against — so it looks fine
 * locally and fails everywhere that matters.
 *
 * Fixing the env stops new templates being written wrong; it does not touch
 * html already stored. This does.
 *
 * Each fix is saved through EDMService.updateTemplate, so it lands as a new
 * immutable version rather than mutating history — the broken version stays
 * reconstructable and rollback is re-pointing at it.
 *
 *   tsx src/cmd/fix-edm-asset-urls.ts              # dry run, reports only
 *   tsx src/cmd/fix-edm-asset-urls.ts --apply
 *   tsx src/cmd/fix-edm-asset-urls.ts --apply --limit 5
 */

const APPLY = process.argv.includes("--apply");
const limitArg = process.argv.indexOf("--limit");
const LIMIT = limitArg > -1 ? parseInt(process.argv[limitArg + 1] ?? "0", 10) : 0;

const config = {
  host: process.env.DATABASE_HOST,
  port: parseInt(process.env.DATABASE_PORT || "5432"),
  database: process.env.DATABASE_NAME,
  user: process.env.DATABASE_USER,
  password: process.env.DATABASE_PWD,
  ssl:
    process.env.DATABASE_HOST !== "localhost" &&
    process.env.DATABASE_HOST !== "127.0.0.1"
      ? { rejectUnauthorized: false }
      : undefined,
};

/**
 * Anything pointing at the asset root that is not already an absolute URL
 * carrying the bucket. Covers the scheme-less case and a bare root-relative
 * "/console2-edm-assets/…" too.
 */
const buildPatterns = (bucket: string) => {
  const good = `https://storage.googleapis.com/${bucket}/${EDM_ASSET_ROOT}/`;
  return {
    good,
    // Order matters: the most specific broken form is replaced first so a
    // later, looser pattern cannot re-mangle what was just fixed.
    patterns: [
      {
        // "storage.googleapis.com/console2-edm-assets/" — no scheme, no bucket
        re: new RegExp(`(?<!//)\\\\bstorage\\\\.googleapis\\\\.com/${EDM_ASSET_ROOT}/`, "g"),
        label: "scheme-less, bucket missing",
      },
      {
        // "https://storage.googleapis.com/console2-edm-assets/" — bucket missing
        re: new RegExp(`https?://storage\\\\.googleapis\\\\.com/${EDM_ASSET_ROOT}/`, "g"),
        label: "bucket missing",
      },
      {
        // src="/console2-edm-assets/…" or src="console2-edm-assets/…"
        re: new RegExp(`(?<=["'(])/?${EDM_ASSET_ROOT}/`, "g"),
        label: "root-relative",
      },
    ],
  };
};

async function run() {
  const bucket = process.env.GOOGLE_CLOUD_STORAGE_BUCKET_NAME;
  if (!bucket) {
    console.error("GOOGLE_CLOUD_STORAGE_BUCKET_NAME is not set — cannot build correct URLs.");
    process.exit(1);
  }

  const { good, patterns } = buildPatterns(bucket);

  console.log(
    APPLY
      ? "▶ REPAIR — saving a new version per fixed template"
      : "▶ DRY RUN — nothing will be written. Pass --apply to commit.",
  );
  console.log(`  database: ${config.database}@${config.host}`);
  console.log(`  target  : ${good}\n`);

  const db = createDBPool(config);
  const stats = { scanned: 0, broken: 0, fixed: 0, failed: 0 };

  try {
    let rows = await EDMRepository.ListTemplatesWithVersions(db);
    if (LIMIT > 0) rows = rows.slice(0, LIMIT);

    for (const row of rows as { id: string; name: string }[]) {
      stats.scanned++;

      const full = await EDMService.getInstance().getTemplate(db, row.id);
      if (!full.success) continue;

      const version =
        full.data.versions.find((v) => v.active === 1) ?? full.data.versions[0];
      const html = version?.html_content ?? "";
      if (!html) continue;

      let fixed = html;
      const hits: string[] = [];
      for (const { re, label } of patterns) {
        const before = fixed;
        fixed = fixed.replace(re, good);
        if (fixed !== before) hits.push(label);
      }

      if (fixed === html) continue;

      stats.broken++;
      const count = (html.match(new RegExp(EDM_ASSET_ROOT, "g")) ?? []).length;
      console.log(`  ${row.id}  ${row.name}`);
      console.log(`    ${hits.join(", ")} — ${count} asset reference(s)`);

      if (!APPLY) continue;

      const res = await EDMService.getInstance().updateTemplate(db, row.id, {
        html_content: fixed,
      });
      if (res.success) {
        stats.fixed++;
        console.log("    ✓ saved as a new version");
      } else {
        stats.failed++;
        console.error(`    ✗ ${res.message}`);
      }
    }
  } finally {
    await db.destroy();
  }

  console.log("\n── summary ──");
  console.log(`  scanned : ${stats.scanned}`);
  console.log(`  broken  : ${stats.broken}`);
  if (APPLY) {
    console.log(`  fixed   : ${stats.fixed}`);
    console.log(`  failed  : ${stats.failed}`);
  } else if (stats.broken > 0) {
    console.log("\n  DRY RUN — re-run with --apply to write the fixes.");
  }
  if (stats.broken === 0) console.log("\n  Nothing to repair.");
}

run().catch((err) => {
  console.error(err);
  process.exit(1);
});
