#!/usr/bin/env node
/**
 * seed-legacy-categories — F-114
 *
 * Imports the legacy OpenCart `oc_category_description` rows into the
 * current catalog and brand tables. Reads the legacy list from the
 * pure helper at `src/modules/categories/legacy/legacy-catalog` so the
 * mapping stays in sync with the tests.
 *
 * Idempotent: skips entries whose name (case-insensitive) already exists in
 * the target table, and uniquifies slugs against existing ones.
 *
 * Usage:
 *   npm run seed:legacy-categories            # apply
 *   DATABASE_URL=... node scripts/seed-legacy-categories.mjs --dry-run
 */
import pg from 'pg';
import { buildImportPlan, buildRenamePlan } from '../dist/modules/categories/legacy/legacy-catalog.js';

const DATABASE_URL = process.env.DATABASE_URL;
if (!DATABASE_URL) {
  console.error('DATABASE_URL is required');
  process.exit(2);
}

const args = new Set(process.argv.slice(2));
const dryRun = args.has('--dry-run');

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

try {
  const categories = await pool.query('SELECT id, name, slug FROM categories_categories');
  const brands = await pool.query('SELECT id, name, slug FROM brands_brands');
  const categoryNameIndex = new Set(categories.rows.map((r) => r.name.toLowerCase()));
  const brandNameIndex = new Set(brands.rows.map((r) => r.name.toLowerCase()));
  const slugIndex = new Set(
    [...categories.rows, ...brands.rows].map((r) => r.slug.toLowerCase()),
  );
  const parentBySlug = new Map(categories.rows.map((r) => [r.slug, r.id]));

  const plan = buildImportPlan(categoryNameIndex, brandNameIndex, slugIndex);
  const renamePlan = buildRenamePlan(categoryNameIndex);

  // Validate that every parentSlug resolves to an existing category.
  const missingParents = new Set();
  for (const cat of plan.categories) {
    if (cat.parentSlug && !parentBySlug.has(cat.parentSlug)) missingParents.add(cat.parentSlug);
  }
  if (missingParents.size > 0) {
    console.error(`Missing parent categories: ${[...missingParents].join(', ')}`);
    process.exit(1);
  }

  console.log(`Planned: ${plan.categories.length} categories, ${plan.brands.length} brands`);
  console.log(`Planned renames: ${renamePlan.length}`);
  if (dryRun) {
    console.log('DRY RUN — nothing will be written.');
    for (const cat of plan.categories) {
      console.log(`  + category ${cat.name} (slug=${cat.slug}, parent=${cat.parentSlug ?? 'ROOT'})`);
    }
    for (const brand of plan.brands) {
      console.log(`  + brand    ${brand.name} (slug=${brand.slug})`);
    }
    for (const rename of renamePlan) {
      console.log(`  ~ rename ${rename.oldName} → ${rename.newName}`);
    }
    process.exit(0);
  }

  for (const cat of plan.categories) {
    const parentId = cat.parentSlug ? parentBySlug.get(cat.parentSlug) : null;
    await pool.query(
      `INSERT INTO categories_categories (parent_id, name, slug, is_parent)
       VALUES ($1, $2, $3, false)
       ON CONFLICT (slug) DO NOTHING`,
      [parentId, cat.name, cat.slug],
    );
    console.log(`  + category ${cat.name} (slug=${cat.slug}, parent=${cat.parentSlug ?? 'ROOT'})`);
  }

  for (const brand of plan.brands) {
    await pool.query(
      `INSERT INTO brands_brands (name, slug) VALUES ($1, $2)
       ON CONFLICT (slug) DO NOTHING`,
      [brand.name, brand.slug],
    );
    console.log(`  + brand    ${brand.name} (slug=${brand.slug})`);
  }

  let renamedCount = 0;
  for (const rename of renamePlan) {
    const result = await pool.query(
      `UPDATE categories_categories SET name = $1, updated_at = now()
       WHERE name = $2`,
      [rename.newName, rename.oldName],
    );
    if (result.rowCount > 0) {
      renamedCount += result.rowCount;
      console.log(`  ~ rename ${rename.oldName} → ${rename.newName}`);
    }
  }
  // Also handle case-only renames for legacy Spanish entries that are
  // already in the catalog but with the wrong casing (FRUTAS Y VERDURAS,
  // SNACKS, GRANOLA). The UPDATE above is case-sensitive so it cannot
  // match these. We re-query the DB for the actual stored names.
  const storedNames = await pool.query('SELECT id, name FROM categories_categories');
  const storedLower = new Map(storedNames.rows.map((r) => [r.name.toLowerCase(), r.id]));
  for (const rename of renamePlan) {
    const oldLower = rename.oldName.toLowerCase();
    if (oldLower !== rename.newName.toLowerCase()) continue;
    const id = storedLower.get(oldLower);
    if (!id) continue;
    const r2 = await pool.query(
      `UPDATE categories_categories SET name = $1, updated_at = now()
       WHERE id = $2 AND name <> $1`,
      [rename.newName, id],
    );
    if (r2.rowCount > 0) {
      renamedCount += r2.rowCount;
      console.log(`  ~ rename → ${rename.newName} (case-only)`);
    }
  }

  console.log(`\nDone. Inserted ${plan.categories.length} categories and ${plan.brands.length} brands. Renamed ${renamedCount} categories.`);
} catch (error) {
  console.error('Error:', error.message);
  process.exit(1);
} finally {
  await pool.end();
}
