#!/usr/bin/env node

import fs from "node:fs";
import path from "node:path";

const rootDir = process.cwd();
const dbPath = path.join(rootDir, "data", "local-db.json");
const unknownCsvPath = path.join(rootDir, "data", "brand-unknowns.csv");

const shouldWrite = process.argv.includes("--write");

function normalizeText(value) {
  return String(value ?? "").toUpperCase();
}

function tokenize(value) {
  const compact = normalizeText(value).replace(/[^A-Z0-9]+/g, " ").trim();
  if (!compact) return [];
  return compact.split(/\s+/);
}

function inferBrand(documentName, sentEmailName) {
  const tokens = new Set([...tokenize(documentName), ...tokenize(sentEmailName)]);
  const matches = new Set();

  for (const token of tokens) {
    if (token === "LUP" || token === "LUPKYNIS" || token.startsWith("LUPKYN")) {
      matches.add("Lupkynis");
    }
    if (token === "INA" || token === "INAQOVI" || token.startsWith("INAQOVI")) {
      matches.add("Inaqovi");
    }
    if (token === "RXU" || token === "RXULTI" || token.startsWith("RXULTI")) {
      matches.add("Rexulti");
    }
    if (
      token === "AM2" ||
      token === "AM2M" ||
      token === "AM960" ||
      token === "ABILIFY" ||
      token === "ARIPIPRAZOLE"
    ) {
      matches.add("Abilify Maintena");
    }
  }

  if (matches.size === 1) {
    return [...matches][0];
  }

  return null;
}

function currentBrand(metadataRow) {
  return String(metadataRow?.brand ?? "").trim() || "Unspecified";
}

function toIsoNow() {
  return new Date().toISOString();
}

function escapeCsv(value) {
  const str = String(value ?? "");
  if (/[",\n]/.test(str)) {
    return `"${str.replace(/"/g, '""')}"`;
  }
  return str;
}

if (!fs.existsSync(dbPath)) {
  console.error(`Missing DB file: ${dbPath}`);
  process.exit(1);
}

const db = JSON.parse(fs.readFileSync(dbPath, "utf8"));
const events = Array.isArray(db.raw_email_events) ? db.raw_email_events : [];
const metadata = Array.isArray(db.email_metadata) ? db.email_metadata : [];

const metadataByDoc = new Map(metadata.map((row) => [row.approved_document_name, row]));

const docAgg = new Map();
for (const event of events) {
  const doc = String(event.approved_document_name ?? "").trim();
  if (!doc) continue;

  const existing = metadataByDoc.get(doc);
  const brand = currentBrand(existing);
  const bucket = docAgg.get(doc) ?? {
    approved_document_name: doc,
    count: 0,
    current_brand: brand,
    sample_sent_email_name: "",
  };

  bucket.count += 1;
  if (!bucket.sample_sent_email_name && event.sent_email_name) {
    bucket.sample_sent_email_name = String(event.sent_email_name);
  }
  if (bucket.current_brand === "Unspecified" && brand !== "Unspecified") {
    bucket.current_brand = brand;
  }

  docAgg.set(doc, bucket);
}

const unspecified = [...docAgg.values()].filter((row) => row.current_brand === "Unspecified");

const updates = [];
const inserts = [];
const unknown = [];

for (const row of unspecified) {
  const inferred = inferBrand(row.approved_document_name, row.sample_sent_email_name);
  if (!inferred) {
    unknown.push(row);
    continue;
  }

  const existing = metadataByDoc.get(row.approved_document_name);
  if (existing) {
    updates.push({
      approved_document_name: row.approved_document_name,
      old_brand: currentBrand(existing),
      new_brand: inferred,
      count: row.count,
    });

    existing.brand = inferred;
    existing.updated_at = toIsoNow();
  } else {
    inserts.push({
      approved_document_name: row.approved_document_name,
      new_brand: inferred,
      count: row.count,
    });

    const inserted = {
      approved_document_name: row.approved_document_name,
      friendly_title: null,
      brand: inferred,
      notes: null,
      thumbnail_path: null,
      campaign_group: null,
      updated_at: toIsoNow(),
    };

    metadata.push(inserted);
    metadataByDoc.set(row.approved_document_name, inserted);
  }
}

unknown.sort((a, b) => b.count - a.count || a.approved_document_name.localeCompare(b.approved_document_name));
updates.sort((a, b) => b.count - a.count || a.approved_document_name.localeCompare(b.approved_document_name));
inserts.sort((a, b) => b.count - a.count || a.approved_document_name.localeCompare(b.approved_document_name));

const unknownCsv = [
  "count,approved_document_name,sample_sent_email_name",
  ...unknown.map((row) =>
    [row.count, escapeCsv(row.approved_document_name), escapeCsv(row.sample_sent_email_name)].join(","),
  ),
].join("\n");

fs.writeFileSync(unknownCsvPath, unknownCsv, "utf8");

console.log("=== Brand Autofill Summary ===");
console.log(`DB: ${dbPath}`);
console.log(`Unspecified docs scanned: ${unspecified.length}`);
console.log(`Will update existing metadata rows: ${updates.length}`);
console.log(`Will insert new metadata rows: ${inserts.length}`);
console.log(`Unknown docs requiring manual mapping: ${unknown.length}`);
console.log(`Unknown list written: ${unknownCsvPath}`);
console.log("");
console.log("Top updates:");
for (const row of updates.slice(0, 20)) {
  console.log(`  ${row.count.toString().padStart(5)}  ${row.new_brand.padEnd(17)}  ${row.approved_document_name}`);
}
console.log("");
console.log("Top inserts:");
for (const row of inserts.slice(0, 20)) {
  console.log(`  ${row.count.toString().padStart(5)}  ${row.new_brand.padEnd(17)}  ${row.approved_document_name}`);
}
console.log("");
console.log("Top unknowns:");
for (const row of unknown.slice(0, 30)) {
  console.log(`  ${row.count.toString().padStart(5)}  ${row.approved_document_name}`);
}

if (!shouldWrite) {
  console.log("");
  console.log("Dry run only. Re-run with --write to persist changes.");
  process.exit(0);
}

const backupPath = `${dbPath}.bak.${Date.now()}`;
fs.copyFileSync(dbPath, backupPath);
fs.writeFileSync(dbPath, `${JSON.stringify(db, null, 2)}\n`, "utf8");

console.log("");
console.log(`Backup created: ${backupPath}`);
console.log("Changes written to local-db.json");
