/**
 * seed.cjs — Populate database with realistic dev/test data.
 * Usage: node scripts/seed.cjs
 */
'use strict';

const fs = require('fs');
const path = require('path');
const { randomUUID } = require('crypto');
const argon2 = require('argon2');
const { Client } = require('pg');

const DEFAULT_STORE_ID = '00000000-0000-0000-0000-000000000001';

// ── Read DATABASE_URL from .env ──────────────────────────────────────────────
const envPath = path.join(__dirname, '..', '.env');
if (fs.existsSync(envPath)) {
  fs.readFileSync(envPath, 'utf8')
    .split('\n')
    .filter((l) => l.trim() && !l.startsWith('#'))
    .forEach((l) => {
      const eq = l.indexOf('=');
      if (eq === -1) return;
      const k = l.slice(0, eq).trim();
      const v = l.slice(eq + 1).trim();
      if (k && !process.env[k]) process.env[k] = v;
    });
}

const DATABASE_URL = process.env.DATABASE_URL;
if (!DATABASE_URL) {
  console.error('DATABASE_URL not set');
  process.exit(1);
}

// ── Helpers ────────────────────────────────────────────────────────────────
async function sql(client, text, params, label) {
  try {
    const result = await client.query(text, params);
    return result;
  } catch (err) {
    console.error(`SQL ERROR [${label}]: ${err.message}`);
    throw err;
  }
}

async function seed(client) {
  await client.query('BEGIN');
  console.log('Seeding database...\n');

  // ── Clear existing seed data ──────────────────────────────────────────
  await sql(client, 'DELETE FROM inventory_movements', [], 'clear-movements');
  await sql(client, 'DELETE FROM inventory_stock', [], 'clear-stock');
  await sql(client, 'DELETE FROM pricing_variant_prices', [], 'clear-prices');
  await sql(client, 'DELETE FROM catalog_product_variants', [], 'clear-variants');
  await sql(client, 'DELETE FROM catalog_product_categories', [], 'clear-prod-cats');
  await sql(client, 'DELETE FROM catalog_products', [], 'clear-products');
  await sql(
    client,
    'DELETE FROM categories_categories WHERE parent_id IS NOT NULL',
    [],
    'clear-children',
  );
  await sql(client, 'DELETE FROM categories_categories', [], 'clear-categories');
  await sql(client, 'DELETE FROM brands_brands', [], 'clear-brands');
  await sql(client, 'DELETE FROM shipping_methods', [], 'clear-methods');
  await sql(client, 'DELETE FROM shipping_zones', [], 'clear-zones');
  console.log('Cleared existing data\n');

  const catBySlug = {};
  const brandBySlug = {};

  // ── 1. Categories ─────────────────────────────────────────────────────
  const catData = [
    { name: 'Alimentacion', slug: 'alimentacion', parentSlug: null },
    { name: 'Suplementos', slug: 'suplementos', parentSlug: null },
    { name: 'Cosmetica Natural', slug: 'cosmetica-natural', parentSlug: null },
    { name: 'Limpieza Ecologica', slug: 'limpieza-ecologica', parentSlug: null },
    { name: 'Frutos Secos', slug: 'frutos-secos', parentSlug: 'alimentacion' },
    { name: 'Aceites', slug: 'aceites', parentSlug: 'alimentacion' },
    { name: 'Hierbas e Infusiones', slug: 'hierbas-infusiones', parentSlug: 'alimentacion' },
    { name: 'Vitaminas', slug: 'vitaminas', parentSlug: 'suplementos' },
    { name: 'Proteinas', slug: 'proteinas', parentSlug: 'suplementos' },
    { name: 'Cremas', slug: 'cremas', parentSlug: 'cosmetica-natural' },
    { name: 'Jabones', slug: 'jabones', parentSlug: 'cosmetica-natural' },
  ];

  // Parents first (no FK dep), then children
  const parents = catData.filter((c) => !c.parentSlug);
  const children = catData.filter((c) => c.parentSlug);
  for (const cat of [...parents, ...children]) {
    const parentId = cat.parentSlug ? catBySlug[cat.parentSlug] : null;
    await sql(
      client,
      'INSERT INTO categories_categories (id, parent_id, name, slug, seo_title) VALUES ($1,$2,$3,$4,$5) ON CONFLICT (slug) DO UPDATE SET name=EXCLUDED.name, seo_title=EXCLUDED.seo_title',
      [randomUUID(), parentId, cat.name, cat.slug, cat.name],
      `cat-${cat.slug}`,
    );
    const r = await client.query('SELECT id FROM categories_categories WHERE slug = $1', [
      cat.slug,
    ]);
    if (r.rows[0]) catBySlug[cat.slug] = r.rows[0].id;
  }
  console.log(`+ ${catData.length} categories`);

  // ── 2. Brands ────────────────────────────────────────────────────────
  const brandData = [
    { name: 'EcoVida', slug: 'ecovida' },
    { name: 'NaturGreen', slug: 'naturgreen' },
    { name: 'BioSana', slug: 'biosana' },
    { name: 'VerdePura', slug: 'verdepura' },
    { name: 'TierraNatural', slug: 'tierranatural' },
    { name: 'SolNatural', slug: 'solnatural' },
  ];

  for (const brand of brandData) {
    await sql(
      client,
      'INSERT INTO brands_brands (id, name, slug, seo_title) VALUES ($1,$2,$3,$4) ON CONFLICT (slug) DO UPDATE SET name=EXCLUDED.name, seo_title=EXCLUDED.seo_title',
      [randomUUID(), brand.name, brand.slug, brand.name],
      `brand-${brand.slug}`,
    );
    const r = await client.query('SELECT id FROM brands_brands WHERE slug = $1', [brand.slug]);
    if (r.rows[0]) brandBySlug[brand.slug] = r.rows[0].id;
  }
  console.log(`+ ${brandData.length} brands`);

  // ── 3. Products + variants + prices + stock ───────────────────────────
  const productData = [
    {
      name: 'Almendras Crudas Ecologicas',
      slug: 'almendras-crudas-ecologicas',
      brandSlug: 'ecovida',
      catSlug: 'frutos-secos',
      price: 895,
      vat: 'general',
    },
    {
      name: 'Aceite de Oliva Virgen Extra Bio',
      slug: 'aceite-oliva-virgen-extra-bio',
      brandSlug: 'naturgreen',
      catSlug: 'aceites',
      price: 1290,
      vat: 'general',
    },
    {
      name: 'Te Verde Matcha Premium',
      slug: 'te-verde-matcha-premium',
      brandSlug: 'biosana',
      catSlug: 'hierbas-infusiones',
      price: 1590,
      vat: 'general',
    },
    {
      name: 'Vitamina D3 + K2',
      slug: 'vitamina-d3-k2',
      brandSlug: 'verdepura',
      catSlug: 'vitaminas',
      price: 1890,
      vat: 'reduced',
    },
    {
      name: 'Proteina Guisante Ecologica',
      slug: 'proteina-guisante-ecologica',
      brandSlug: 'tierranatural',
      catSlug: 'proteinas',
      price: 2490,
      vat: 'reduced',
    },
    {
      name: 'Complejo B Natural',
      slug: 'complejo-b-natural',
      brandSlug: 'ecovida',
      catSlug: 'vitaminas',
      price: 1190,
      vat: 'reduced',
    },
    {
      name: 'Crema Facial Hidratante Aloe Vera',
      slug: 'crema-facial-aloe-vera',
      brandSlug: 'solnatural',
      catSlug: 'cremas',
      price: 2190,
      vat: 'general',
    },
    {
      name: 'Jabon Negro Africano',
      slug: 'jabon-negro-africano',
      brandSlug: 'biosana',
      catSlug: 'jabones',
      price: 790,
      vat: 'general',
    },
    {
      name: 'Serum Antioxidante Rosa Mosqueta',
      slug: 'serum-rosa-mosqueta',
      brandSlug: 'naturgreen',
      catSlug: 'cremas',
      price: 2690,
      vat: 'general',
    },
    {
      name: 'Detergente Ecologico Ropa',
      slug: 'detergente-ecologico-ropa',
      brandSlug: 'verdepura',
      catSlug: 'limpieza-ecologica',
      price: 990,
      vat: 'general',
    },
    {
      name: 'Limpiador Multiusos Bio',
      slug: 'limpiador-multiusos-bio',
      brandSlug: 'tierranatural',
      catSlug: 'limpieza-ecologica',
      price: 890,
      vat: 'general',
    },
    {
      name: 'Desinfectante Natural Superficies',
      slug: 'desinfectante-natural-superficies',
      brandSlug: 'solnatural',
      catSlug: 'limpieza-ecologica',
      price: 1190,
      vat: 'general',
    },
  ];

  for (let pi = 0; pi < productData.length; pi++) {
    const p = productData[pi];
    const brandId = brandBySlug[p.brandSlug];
    const catId = catBySlug[p.catSlug];
    if (!brandId || !catId) {
      console.warn(`  Skipping ${p.slug}: missing brand or cat`);
      continue;
    }

    const productId = randomUUID();
    const variantId = randomUUID();
    const sku = `SKU-${p.slug.replace(/-/g, '').toUpperCase().slice(0, 8)}-001`;
    const ean = `590123412345${String(pi + 1).padStart(2, '0')}`;
    const desc = `${p.name} de primera calidad. Producto 100% natural y ecologico.`;

    await sql(
      client,
      'INSERT INTO catalog_products (id, brand_id, name, slug, state, seo_title, description) VALUES ($1,$2,$3,$4,$5,$6,$7) ON CONFLICT (slug) DO UPDATE SET name=EXCLUDED.name, brand_id=EXCLUDED.brand_id, description=EXCLUDED.description',
      [productId, brandId, p.name, p.slug, 'active', p.name, desc],
      `product-${p.slug}`,
    );
    await sql(
      client,
      'INSERT INTO catalog_product_categories (product_id, category_id) VALUES ($1,$2) ON CONFLICT DO NOTHING',
      [productId, catId],
      `prodcat-${p.slug}`,
    );
    await sql(
      client,
      'INSERT INTO catalog_product_variants (id, product_id, sku, ean) VALUES ($1,$2,$3,$4) ON CONFLICT (sku) DO UPDATE SET ean=EXCLUDED.ean',
      [variantId, productId, sku, ean],
      `variant-${sku}`,
    );
    await sql(
      client,
      'INSERT INTO pricing_variant_prices (variant_id, vat_rate, net_unit_amount_cents) VALUES ($1,$2,$3) ON CONFLICT (variant_id) DO UPDATE SET net_unit_amount_cents=EXCLUDED.net_unit_amount_cents, vat_rate=EXCLUDED.vat_rate',
      [variantId, p.vat, p.price],
      `price-${sku}`,
    );
    await sql(
      client,
      'INSERT INTO inventory_stock (variant_id, store_id, available, reserved) VALUES ($1,$2,$3,$4) ON CONFLICT (variant_id, store_id) DO UPDATE SET available=EXCLUDED.available, reserved=EXCLUDED.reserved',
      [variantId, DEFAULT_STORE_ID, 25, 0],
      `stock-${sku}`,
    );
  }
  console.log(`+ ${productData.length} products (variants, prices, stock)`);

  // ── 4. Shipping ───────────────────────────────────────────────────
  const zoneId = randomUUID();
  await sql(
    client,
    'INSERT INTO shipping_zones (id, name, country, postal_code_prefix) VALUES ($1,$2,$3,$4) ON CONFLICT (id) DO UPDATE SET name=EXCLUDED.name',
    [zoneId, 'Espania Peninsular', 'ES', null],
    'zone-es',
  );
  await sql(
    client,
    'INSERT INTO shipping_methods (id, zone_id, name, base_cost_cents, free_shipping_threshold_cents) VALUES ($1,$2,$3,$4,$5)',
    [randomUUID(), zoneId, 'Estandar', 499, 4900],
    'method-std',
  );
  await sql(
    client,
    'INSERT INTO shipping_methods (id, zone_id, name, base_cost_cents, free_shipping_threshold_cents) VALUES ($1,$2,$3,$4,$5)',
    [randomUUID(), zoneId, 'Express 24h', 899, null],
    'method-express',
  );
  console.log('+ 1 shipping zone + 2 methods');

  // ── 5. Backoffice admin ────────────────────────────────────────────
  const adminEmail = process.env.SEED_ADMIN_EMAIL || 'admin@mdv.local';
  const adminPassword = process.env.SEED_ADMIN_PASSWORD || 'Admin123456!';
  if (process.env.NODE_ENV === 'production' && !process.env.SEED_ADMIN_PASSWORD) {
    throw new Error('SEED_ADMIN_PASSWORD must be set when NODE_ENV=production');
  }
  const adminHash = await argon2.hash(adminPassword);
  await sql(
    client,
    `INSERT INTO backoffice_users (email, password_hash, role, mfa_enrolled)
     VALUES ($1, $2, 'admin', false)
     ON CONFLICT (email) DO UPDATE
       SET password_hash = EXCLUDED.password_hash,
           role = 'admin',
           updated_at = now()`,
    [adminEmail, adminHash],
    'backoffice-admin',
  );
  console.log(`+ backoffice admin (${adminEmail})`);

  await client.query('COMMIT');
  console.log('\nSeed complete!');
}

// ── Run ──────────────────────────────────────────────────────────────────
async function main() {
  const client = new Client({ connectionString: DATABASE_URL });
  try {
    await client.connect();
    await seed(client);
  } catch (err) {
    await client.query('ROLLBACK').catch(() => {});
    console.error('Seed failed:', err.message);
    process.exit(1);
  } finally {
    await client.end();
  }
}

main();
