var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));

// server.ts
var import_express = __toESM(require("express"), 1);
var import_path = __toESM(require("path"), 1);
var import_fs = __toESM(require("fs"), 1);
var import_vite = require("vite");
var import_genai = require("@google/genai");
var import_dotenv = __toESM(require("dotenv"), 1);
var import_supabase_js = require("@supabase/supabase-js");

// db-mysql.ts
var import_promise = __toESM(require("mysql2/promise"), 1);
var pool;
var DEFAULT_PRODUCTS = [
  {
    id: "prod-1",
    name: "Ew\xE9 Moringa Premium Tea Blend",
    description: "Handpicked high-altitude Moringa leaf infusion sourced from sustainable farms in Northern Nigeria, blended with Lemongrass and a warm hint of Ginger. Naturally caffeine-free and rich in vitamins to sustain your metabolic vitality and focus.",
    price: 8500,
    image: "https://images.unsplash.com/photo-1597481499750-3e6b22637e12?auto=format&fit=crop&q=80&w=800",
    category: "herbal-teas",
    ingredients: ["100% Organic Moringa Oleifera Leaves", "Nigerian Lemongrass (Telem)", "Sun-dried Ginger root"],
    benefits: [
      "Natural energy boost without the caffeine crash",
      "Immune system support via high concentration of Vitamin C and Iron",
      "Assists gentle metabolic cleansing and digestion"
    ],
    usageGuide: "Steep 1 tea bag or 1 tablespoon of loose leaf blend in hot boiled water for 5-7 minutes. Enjoy warm in the morning or early afternoon for natural energy.",
    stock: 25,
    isBestSeller: true,
    rating: 4.9,
    reviewsCount: 42
  },
  {
    id: "prod-2",
    name: "Ori Luxury Whipped Shea Butter",
    description: "Pure, grade-A cold-pressed shea butter from premium Oyo state nuts, whipped to a velvet finish. Subtly perfumed with organic calming lavender and chamomile essences, providing an African luxury answer to skin repair and barrier hydration.",
    price: 12500,
    image: "https://images.unsplash.com/photo-1620916566398-39f1143ab7be?auto=format&fit=crop&q=80&w=800",
    category: "beauty-skincare",
    ingredients: ["West African Butyrospermum Parkii (Shea) Butter", "Cold-pressed Moroccan Argan Oil", "Organic Lavender Essential Oil", "Roman Chamomile Extract"],
    benefits: [
      "Intense deep skin barrier hydration and cellular restoration",
      "Rich in vitamins A, E, and F to improve texture and tone",
      "Soothes extreme dry patches, eczema flareups, and sensitive skin"
    ],
    usageGuide: "Warm a pea-sized amount between clean hands and gently massage into skin or hair damp from bathing. Ideal for absolute overnight moisture sealing.",
    stock: 18,
    isBestSeller: true,
    rating: 4.8,
    reviewsCount: 31
  },
  {
    id: "prod-3",
    name: "Dongoyaro Pure Neem Clarifying Oil",
    description: "An authentic Nigerian herbal remedy. High-potency clarify oil double-filtered from indigenous Neem (Dongoyaro) leaves and seeds. Renowned for its rapid calming of troubled skin and purifying scalp wellness.",
    price: 9500,
    image: "https://images.unsplash.com/photo-1608571423902-eed4a5ad8108?auto=format&fit=crop&q=80&w=800",
    category: "wellness-oils",
    ingredients: ["Double-Filtered Azadirachta Indica (Neem) Seed Oil", "Rosehip Seed Carrier Oil", "Organic Tea Tree Extract"],
    benefits: [
      "Purifies skin, soothing acne, blemishes, and occasional microbial flare-ups",
      "Soothes dry, itchy, or flaky scalp when massaged in as a serum",
      "Rich in essential fatty acids to naturally balance oil production"
    ],
    usageGuide: "Apply 2-3 drops to localized dry or troubled spots on clean skin. For hair treatment, massage 1-2 droppers into the scalp 30 minutes before washing.",
    stock: 15,
    isBestSeller: false,
    rating: 4.6,
    reviewsCount: 19
  },
  {
    id: "prod-4",
    name: "Zobo Hibiscus Glow Elixir",
    description: "A highly concentrated herbal nutritional elixir featuring nutrient-dense organic Nigerian Hibiscus (Zobo) calyces. Packed with natural alpha-hydroxy acids (AHAs) and anthocyanins, designed to support heart health and promote a youthful skin complexion radiating from the inside out.",
    price: 7500,
    image: "https://images.unsplash.com/photo-1555529633-fc9d99d3a451?auto=format&fit=crop&q=80&w=800",
    category: "lifestyle-powders",
    ingredients: ["Dehydrated Organic Hibiscus Sabdariffa Calyces", "Sweet Cinnamon Bark extract", "Cloves (Kanafuru)", "Dried Orange Peel extract"],
    benefits: [
      "Promotes inner antioxidant cellular health",
      "A natural source of plant AHAs that helps revitalize skin tone and elasticity",
      "Aids blood pressure support and cardiovascular vitality"
    ],
    usageGuide: "Mix 1-2 capfuls into cold water or sparkling club soda, or stir into a warm mug of morning water. Savor the delightfully tart, tangy fruit flavor profiles.",
    stock: 30,
    isBestSeller: true,
    rating: 4.9,
    reviewsCount: 56
  },
  {
    id: "prod-5",
    name: "Iyan Lemongrass & Ginger Infusion",
    description: "A soothing herbal nighttime tea designed to unwind the mind and ease daily tension. Sourced from organic gardens in Plateau State, Nigeria, this sweet blend of Lemongrass and wild botanical spices supports gentle sleep and respiratory pathways.",
    price: 6e3,
    image: "https://images.unsplash.com/photo-1576092768241-dec231879fc3?auto=format&fit=crop&q=80&w=800",
    category: "herbal-teas",
    ingredients: ["Sustainable Cymbopogon Citratus (Lemongrass)", "Zingiber Officinale (Ginger) Root", "Wild Mint Leaves (Minta)"],
    benefits: [
      "Induces calm and alleviates evening anxiety",
      "Encourages restorative sleep and relaxes stomach tension",
      "Soothes tickly throats and supports respiratory pathways"
    ],
    usageGuide: "Brew 1 bag in freshly boiled hot water. Steep covered for 8-10 minutes to preserve volatile calming essential oils. Sip warm just before bed.",
    stock: 22,
    isBestSeller: false,
    rating: 4.7,
    reviewsCount: 24
  },
  {
    id: "prod-6",
    name: "\xC0d\xF9n Dark Cocoa & Turmeric Mask",
    description: "An anti-inflammatory skin brightening and polishing mask. Made from premium, raw organic West African cocoa powder harvested in Edo state, mixed with high-curcumin yellow Turmeric (Igun). Restores a luxurious natural gold radiance.",
    price: 11e3,
    image: "https://images.unsplash.com/photo-1512290923902-8a9f81dc236c?auto=format&fit=crop&q=80&w=800",
    category: "beauty-skincare",
    ingredients: ["Raw West African Theobroma Cacao Powder", "Organic Curcuma Longa (Turmeric) Root Powder", "Fine Kaolin Clay", "Wild Forest Honey Extract powder"],
    benefits: [
      "Instantly revives sluggish, tired skin complexions with vital mineral copper",
      "Minimizes skin hyperpigmentation dark spots",
      "Polishes dry flake layers, revealing a baby-smooth touch"
    ],
    usageGuide: "Stir 1 tablespoon of powder mask with equal parts hot water, rosewater, or milk until a smooth paste forms. Cleanse skin, apply evenly for 10-15 mins, and rinse with warm water.",
    stock: 12,
    isBestSeller: false,
    rating: 4.8,
    reviewsCount: 14
  }
];
var DEFAULT_FAQS = [
  {
    id: "faq-1",
    question: "What products are best for dry or eczema-prone skin?",
    answer: "Our 'Ori Luxury Whipped Shea Butter' is highly recommended as it provides deep moisture barrier restoration with all-natural Oyo-state Shea butter blended with soothing Lavender and Chamomile."
  },
  {
    id: "faq-2",
    question: "How do I take the Ew\xE9 Moringa Tea blend?",
    answer: "For optimal metabolic vitality and energy, steep 1 bag in freshly boiled hot water for 5-7 minutes. Enjoy it first thing in the morning or as an early afternoon refresher."
  },
  {
    id: "faq-3",
    question: "Can I use Dongoyaro Neem Oil directly on my face?",
    answer: "Yes, our Dongoyaro Neem Oil is pre-blended with high-purity Rosehip Seed carrier oil to bring down pure Neem's strength, making it perfectly safe for direct application on facial acne blemishes, dry spots, or massaging onto the scalp."
  },
  {
    id: "faq-4",
    question: "Are there any side effects or spiritual claims with these products?",
    answer: "None of our products claim medical cures or spiritual outcomes. We focus purely on organic nutritional wellness, ancient West African herbal synergy, and natural botanical science for beautiful modern skin and lifestyle balance."
  }
];
var DEFAULT_CATEGORIES = [
  { id: "herbal-medicine", label: "Herbal Medicine", img: "https://images.unsplash.com/photo-1540555700478-4be289fbecef?auto=format&fit=crop&q=80&w=300" },
  { id: "body-enhancement", label: "Body Enhancement", img: "https://images.unsplash.com/photo-1620916566398-39f1143ab7be?auto=format&fit=crop&q=80&w=300" },
  { id: "kayanmata", label: "Kayanmata", img: "https://images.unsplash.com/photo-1512290923902-8a9f81dc236c?auto=format&fit=crop&q=80&w=300" },
  { id: "spiritual-products", label: "Spiritual Products", img: "https://images.unsplash.com/photo-1608571423902-eed4a5ad8108?auto=format&fit=crop&q=80&w=300" },
  { id: "herbal-teas", label: "Herbal Teas", img: "https://images.unsplash.com/photo-1597481499750-3e6b22637e12?auto=format&fit=crop&q=80&w=300" },
  { id: "oils-lotions", label: "Oils & Lotions", img: "https://images.unsplash.com/photo-1601049541289-9b1b7bbbfe19?auto=format&fit=crop&q=80&w=300" },
  { id: "others", label: "Others", img: "https://images.unsplash.com/photo-1473448912268-2022ce9509d8?auto=format&fit=crop&q=80&w=300" }
];
var DEFAULT_SETTINGS = {
  bankEnabled: true,
  monnifyEnabled: true,
  bankName: "Sterling Bank PLC",
  accountName: "MUMMCY AYOFE HERBAL CARE LTD",
  accountNumber: "1024451121",
  monnifyApiKey: "",
  monnifyContractCode: "",
  monnifySecretKey: "",
  storeAddress: "Plot 24B, Admiralty Way, Lekki Phase 1, Lagos, Nigeria",
  storePhone: "+234 908 445 1121",
  storeEmail: "wellness@eweandori.com",
  homepageImage: "/images/model_homepage.jpg",
  ceoImage: "/src/assets/images/mummy_ayofe_bags_1779911520990.png",
  adminPassword: "admin",
  deliveryLocations: [
    { id: "lagos-mainland", label: "Lagos Mainland", charge: 2e3 },
    { id: "lagos-island", label: "Lagos Island / Lekki", charge: 3e3 },
    { id: "abuja-fct", label: "Abuja / FCT Express", charge: 4500 },
    { id: "rivers-ph", label: "Rivers State (Port Harcourt)", charge: 4e3 },
    { id: "oyo-ibadan", label: "Oyo State (Ibadan)", charge: 3e3 },
    { id: "rest-of-nigeria", label: "Rest of Nigeria (Nationwide Shipping)", charge: 5500 }
  ]
};
function parseJsonColumn(val) {
  if (val === null || val === void 0) return [];
  if (typeof val === "string") {
    try {
      return JSON.parse(val);
    } catch {
      return [];
    }
  }
  return val;
}
async function initDb() {
  const host = process.env.DB_HOST || "localhost";
  const port = parseInt(process.env.DB_PORT || "3306", 10);
  const user = process.env.DB_USER || "root";
  const password = process.env.DB_PASSWORD || "";
  const database = process.env.DB_NAME || "mummy_ayofe";
  console.log(`Connecting to MySQL server at ${host}:${port}...`);
  try {
    const connection = await import_promise.default.createConnection({
      host,
      port,
      user,
      password
    });
    await connection.query(`CREATE DATABASE IF NOT EXISTS \`${database}\``);
    await connection.end();
    console.log(`Database "${database}" verified/created successfully.`);
  } catch (err) {
    console.warn(`Skipping CREATE DATABASE step (this is normal on managed hosting like cPanel):`, err.message);
  }
  pool = import_promise.default.createPool({
    host,
    port,
    user,
    password,
    database,
    waitForConnections: true,
    connectionLimit: 10,
    queueLimit: 0
  });
  await pool.query(`
    CREATE TABLE IF NOT EXISTS categories (
      id VARCHAR(255) PRIMARY KEY,
      label VARCHAR(255) NOT NULL,
      img VARCHAR(1000)
    )
  `);
  await pool.query(`
    CREATE TABLE IF NOT EXISTS products (
      id VARCHAR(255) PRIMARY KEY,
      name VARCHAR(255) NOT NULL,
      description TEXT,
      price INT NOT NULL,
      image VARCHAR(1000),
      category VARCHAR(255),
      ingredients JSON,
      benefits JSON,
      usageGuide TEXT,
      stock INT NOT NULL DEFAULT 0,
      isBestSeller BOOLEAN DEFAULT FALSE,
      rating DECIMAL(3, 2) DEFAULT 4.5,
      reviewsCount INT DEFAULT 0
    )
  `);
  try {
    await pool.query("ALTER TABLE products ADD COLUMN isBestSeller BOOLEAN DEFAULT FALSE");
  } catch (e) {
  }
  try {
    await pool.query("ALTER TABLE products ADD COLUMN rating DECIMAL(3, 2) DEFAULT 4.5");
  } catch (e) {
  }
  try {
    await pool.query("ALTER TABLE products ADD COLUMN reviewsCount INT DEFAULT 0");
  } catch (e) {
  }
  await pool.query(`
    CREATE TABLE IF NOT EXISTS bookings (
      id VARCHAR(255) PRIMARY KEY,
      name VARCHAR(255) NOT NULL,
      email VARCHAR(255),
      phone VARCHAR(255),
      date VARCHAR(255) NOT NULL,
      time VARCHAR(255) NOT NULL,
      consultationType VARCHAR(255) NOT NULL,
      message TEXT,
      status VARCHAR(50) DEFAULT 'pending',
      createdAt VARCHAR(255) NOT NULL
    )
  `);
  await pool.query(`
    CREATE TABLE IF NOT EXISTS orders (
      id VARCHAR(255) PRIMARY KEY,
      orderNumber VARCHAR(50) UNIQUE,
      orderDate VARCHAR(255) NOT NULL,
      status VARCHAR(50) DEFAULT 'pending-verification',
      customerName VARCHAR(255) NOT NULL,
      customerEmail VARCHAR(255),
      customerPhone VARCHAR(255) NOT NULL,
      deliveryLocation VARCHAR(255) NOT NULL,
      deliveryCharge INT NOT NULL,
      paymentMethod VARCHAR(50) NOT NULL,
      totalAmount INT NOT NULL,
      items JSON NOT NULL,
      billingAddress JSON
    )
  `);
  const orderCols = [
    "orderNumber VARCHAR(50) UNIQUE",
    "orderDate VARCHAR(255)",
    "status VARCHAR(50) DEFAULT 'pending-verification'",
    "customerEmail VARCHAR(255)",
    "deliveryLocation VARCHAR(255)",
    "deliveryCharge INT DEFAULT 0",
    "paymentMethod VARCHAR(50)",
    "totalAmount INT DEFAULT 0",
    "billingAddress JSON"
  ];
  for (const col of orderCols) {
    try {
      await pool.query(`ALTER TABLE orders ADD COLUMN ${col}`);
    } catch (e) {
    }
  }
  await pool.query(`
    CREATE TABLE IF NOT EXISTS faqs (
      id VARCHAR(255) PRIMARY KEY,
      question TEXT NOT NULL,
      answer TEXT NOT NULL
    )
  `);
  await pool.query(`
    CREATE TABLE IF NOT EXISTS settings (
      id VARCHAR(50) PRIMARY KEY,
      bankEnabled BOOLEAN DEFAULT TRUE,
      monnifyEnabled BOOLEAN DEFAULT TRUE,
      bankName VARCHAR(255),
      accountName VARCHAR(255),
      accountNumber VARCHAR(50),
      monnifyApiKey VARCHAR(255),
      monnifyContractCode VARCHAR(255),
      monnifySecretKey VARCHAR(255),
      storeAddress TEXT,
      storePhone VARCHAR(50),
      storeEmail VARCHAR(255),
      deliveryLocations JSON,
      homepageImage VARCHAR(1000),
      ceoImage VARCHAR(1000),
      adminPassword VARCHAR(255)
    )
  `);
  try {
    await pool.query("ALTER TABLE settings ADD COLUMN homepageImage VARCHAR(1000)");
  } catch (e) {
    if (e.code !== "ER_DUP_FIELDNAME") {
      console.error("Warning: could not add homepageImage column:", e.message);
    }
  }
  try {
    await pool.query("ALTER TABLE settings ADD COLUMN ceoImage VARCHAR(1000)");
  } catch (e) {
    if (e.code !== "ER_DUP_FIELDNAME") {
      console.error("Warning: could not add ceoImage column:", e.message);
    }
  }
  try {
    await pool.query("ALTER TABLE settings ADD COLUMN adminPassword VARCHAR(255)");
  } catch (e) {
    if (e.code !== "ER_DUP_FIELDNAME") {
      console.error("Warning: could not add adminPassword column:", e.message);
    }
  }
  console.log("Database tables verified/created successfully.");
  const [categoriesRows] = await pool.query("SELECT COUNT(*) as count FROM categories");
  if (categoriesRows[0].count === 0) {
    console.log("Seeding default categories...");
    for (const cat of DEFAULT_CATEGORIES) {
      await pool.query(
        "INSERT INTO categories (id, label, img) VALUES (?, ?, ?)",
        [cat.id, cat.label, cat.img]
      );
    }
  }
  const [productsRows] = await pool.query("SELECT COUNT(*) as count FROM products");
  if (productsRows[0].count === 0) {
    console.log("Seeding default products...");
    for (const p of DEFAULT_PRODUCTS) {
      await pool.query(
        `INSERT INTO products 
         (id, name, description, price, image, category, ingredients, benefits, usageGuide, stock, isBestSeller, rating, reviewsCount) 
         VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
        [
          p.id,
          p.name,
          p.description,
          p.price,
          p.image,
          p.category,
          JSON.stringify(p.ingredients),
          JSON.stringify(p.benefits),
          p.usageGuide,
          p.stock,
          p.isBestSeller,
          p.rating,
          p.reviewsCount
        ]
      );
    }
  }
  const [faqsRows] = await pool.query("SELECT COUNT(*) as count FROM faqs");
  if (faqsRows[0].count === 0) {
    console.log("Seeding default FAQs...");
    for (const faq of DEFAULT_FAQS) {
      await pool.query(
        "INSERT INTO faqs (id, question, answer) VALUES (?, ?, ?)",
        [faq.id, faq.question, faq.answer]
      );
    }
  }
  const [settingsRows] = await pool.query("SELECT COUNT(*) as count FROM settings WHERE id = 'global'");
  if (settingsRows[0].count === 0) {
    console.log("Seeding default settings...");
    await pool.query(
      `INSERT INTO settings 
       (id, bankEnabled, monnifyEnabled, bankName, accountName, accountNumber, monnifyApiKey, monnifyContractCode, monnifySecretKey, storeAddress, storePhone, storeEmail, deliveryLocations, homepageImage, ceoImage, adminPassword) 
       VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
      [
        "global",
        DEFAULT_SETTINGS.bankEnabled,
        DEFAULT_SETTINGS.monnifyEnabled,
        DEFAULT_SETTINGS.bankName,
        DEFAULT_SETTINGS.accountName,
        DEFAULT_SETTINGS.accountNumber,
        DEFAULT_SETTINGS.monnifyApiKey,
        DEFAULT_SETTINGS.monnifyContractCode,
        DEFAULT_SETTINGS.monnifySecretKey,
        DEFAULT_SETTINGS.storeAddress,
        DEFAULT_SETTINGS.storePhone,
        DEFAULT_SETTINGS.storeEmail,
        JSON.stringify(DEFAULT_SETTINGS.deliveryLocations),
        DEFAULT_SETTINGS.homepageImage,
        DEFAULT_SETTINGS.ceoImage,
        DEFAULT_SETTINGS.adminPassword
      ]
    );
  }
  console.log("Database initial seeding complete.");
}
async function getCategories() {
  const [rows] = await pool.query("SELECT * FROM categories");
  return rows;
}
async function addCategory(category) {
  const id = category.id || `cat-${Date.now()}`;
  await pool.query(
    "INSERT INTO categories (id, label, img) VALUES (?, ?, ?)",
    [id, category.label, category.img || null]
  );
  return { ...category, id };
}
async function updateCategory(id, data) {
  const fields = [];
  const values = [];
  if (data.label !== void 0) {
    fields.push("label = ?");
    values.push(data.label);
  }
  if (data.img !== void 0) {
    fields.push("img = ?");
    values.push(data.img);
  }
  if (fields.length === 0) return null;
  values.push(id);
  await pool.query(
    `UPDATE categories SET ${fields.join(", ")} WHERE id = ?`,
    values
  );
  const [rows] = await pool.query("SELECT * FROM categories WHERE id = ?", [id]);
  return rows[0] || null;
}
async function deleteCategory(id) {
  const [result] = await pool.query("DELETE FROM categories WHERE id = ?", [id]);
  return result.affectedRows > 0;
}
async function getProducts() {
  const [rows] = await pool.query("SELECT * FROM products");
  return rows.map((row) => ({
    ...row,
    isBestSeller: !!row.isBestSeller,
    price: Number(row.price),
    rating: Number(row.rating),
    reviewsCount: Number(row.reviewsCount),
    ingredients: parseJsonColumn(row.ingredients),
    benefits: parseJsonColumn(row.benefits)
  }));
}
async function addProduct(p) {
  const id = p.id || `prod-${Date.now()}`;
  const rating = p.rating || 4.5;
  const reviewsCount = p.reviewsCount || 0;
  await pool.query(
    `INSERT INTO products 
     (id, name, description, price, image, category, ingredients, benefits, usageGuide, stock, isBestSeller, rating, reviewsCount) 
     VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
    [
      id,
      p.name,
      p.description || null,
      p.price || 0,
      p.image || null,
      p.category || null,
      JSON.stringify(p.ingredients || []),
      JSON.stringify(p.benefits || []),
      p.usageGuide || null,
      p.stock || 0,
      p.isBestSeller ? 1 : 0,
      rating,
      reviewsCount
    ]
  );
  return { ...p, id, rating, reviewsCount };
}
async function updateProduct(id, data) {
  const fields = [];
  const values = [];
  const allowedKeys = [
    "name",
    "description",
    "price",
    "image",
    "category",
    "ingredients",
    "benefits",
    "usageGuide",
    "stock",
    "isBestSeller",
    "rating",
    "reviewsCount"
  ];
  for (const key of allowedKeys) {
    if (data[key] !== void 0) {
      fields.push(`\`${key}\` = ?`);
      if (key === "ingredients" || key === "benefits") {
        values.push(JSON.stringify(data[key]));
      } else if (key === "isBestSeller") {
        values.push(data[key] ? 1 : 0);
      } else {
        values.push(data[key]);
      }
    }
  }
  if (fields.length === 0) return null;
  values.push(id);
  await pool.query(
    `UPDATE products SET ${fields.join(", ")} WHERE id = ?`,
    values
  );
  const [rows] = await pool.query("SELECT * FROM products WHERE id = ?", [id]);
  if (!rows[0]) return null;
  return {
    ...rows[0],
    isBestSeller: !!rows[0].isBestSeller,
    price: Number(rows[0].price),
    rating: Number(rows[0].rating),
    reviewsCount: Number(rows[0].reviewsCount),
    ingredients: parseJsonColumn(rows[0].ingredients),
    benefits: parseJsonColumn(rows[0].benefits)
  };
}
async function deleteProduct(id) {
  const [result] = await pool.query("DELETE FROM products WHERE id = ?", [id]);
  return result.affectedRows > 0;
}
async function getBookings() {
  const [rows] = await pool.query("SELECT * FROM bookings ORDER BY createdAt DESC");
  return rows;
}
async function addBooking(b) {
  const id = `book-${Date.now()}`;
  const createdAt = (/* @__PURE__ */ new Date()).toISOString();
  const status = b.status || "pending";
  await pool.query(
    `INSERT INTO bookings (id, name, email, phone, date, time, consultationType, message, status, createdAt) 
     VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
    [
      id,
      b.name,
      b.email || null,
      b.phone || null,
      b.date,
      b.time,
      b.consultationType,
      b.message || null,
      status,
      createdAt
    ]
  );
  return { ...b, id, status, createdAt };
}
async function updateBooking(id, data) {
  const fields = [];
  const values = [];
  const allowedKeys = ["name", "email", "phone", "date", "time", "consultationType", "message", "status"];
  for (const key of allowedKeys) {
    if (data[key] !== void 0) {
      fields.push(`\`${key}\` = ?`);
      values.push(data[key]);
    }
  }
  if (fields.length === 0) return null;
  values.push(id);
  await pool.query(
    `UPDATE bookings SET ${fields.join(", ")} WHERE id = ?`,
    values
  );
  const [rows] = await pool.query("SELECT * FROM bookings WHERE id = ?", [id]);
  return rows[0] || null;
}
async function getOrders() {
  const [rows] = await pool.query("SELECT * FROM orders ORDER BY orderDate DESC");
  return rows.map((row) => ({
    ...row,
    totalAmount: Number(row.totalAmount),
    deliveryCharge: Number(row.deliveryCharge),
    items: parseJsonColumn(row.items),
    billingAddress: parseJsonColumn(row.billingAddress)
  }));
}
async function addOrder(o) {
  const id = `order-${Date.now()}`;
  const orderNumber = `NGA-${Math.floor(1e5 + Math.random() * 9e5)}`;
  const orderDate = (/* @__PURE__ */ new Date()).toISOString();
  const status = o.status || "pending-verification";
  await pool.query(
    `INSERT INTO orders 
     (id, orderNumber, orderDate, status, customerName, customerEmail, customerPhone, deliveryLocation, deliveryCharge, paymentMethod, totalAmount, items, billingAddress) 
     VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
    [
      id,
      orderNumber,
      orderDate,
      status,
      o.customerName,
      o.customerEmail || null,
      o.customerPhone,
      o.deliveryLocation,
      o.deliveryCharge || 0,
      o.paymentMethod,
      o.totalAmount || 0,
      JSON.stringify(o.items || []),
      JSON.stringify(o.billingAddress || null)
    ]
  );
  return { ...o, id, orderNumber, orderDate, status };
}
async function updateOrder(id, data) {
  const fields = [];
  const values = [];
  const allowedKeys = [
    "status",
    "customerName",
    "customerEmail",
    "customerPhone",
    "deliveryLocation",
    "deliveryCharge",
    "paymentMethod",
    "totalAmount",
    "items",
    "billingAddress"
  ];
  for (const key of allowedKeys) {
    if (data[key] !== void 0) {
      fields.push(`\`${key}\` = ?`);
      if (key === "items" || key === "billingAddress") {
        values.push(JSON.stringify(data[key]));
      } else {
        values.push(data[key]);
      }
    }
  }
  if (fields.length === 0) return null;
  values.push(id);
  await pool.query(
    `UPDATE orders SET ${fields.join(", ")} WHERE id = ?`,
    values
  );
  const [rows] = await pool.query("SELECT * FROM orders WHERE id = ?", [id]);
  if (!rows[0]) return null;
  return {
    ...rows[0],
    totalAmount: Number(rows[0].totalAmount),
    deliveryCharge: Number(rows[0].deliveryCharge),
    items: parseJsonColumn(rows[0].items),
    billingAddress: parseJsonColumn(rows[0].billingAddress)
  };
}
async function getFaqs() {
  const [rows] = await pool.query("SELECT * FROM faqs");
  return rows;
}
async function setFaqs(faqsList) {
  await pool.query("DELETE FROM faqs");
  for (const faq of faqsList) {
    const id = faq.id || `faq-${Date.now()}-${Math.random()}`;
    await pool.query(
      "INSERT INTO faqs (id, question, answer) VALUES (?, ?, ?)",
      [id, faq.question, faq.answer]
    );
  }
  return getFaqs();
}
async function getSettings() {
  const [rows] = await pool.query("SELECT * FROM settings WHERE id = 'global'");
  if (rows.length === 0) {
    return DEFAULT_SETTINGS;
  }
  const row = rows[0];
  return {
    bankEnabled: !!row.bankEnabled,
    monnifyEnabled: !!row.monnifyEnabled,
    bankName: row.bankName,
    accountName: row.accountName,
    accountNumber: row.accountNumber,
    monnifyApiKey: row.monnifyApiKey,
    monnifyContractCode: row.monnifyContractCode,
    monnifySecretKey: row.monnifySecretKey,
    storeAddress: row.storeAddress,
    storePhone: row.storePhone,
    storeEmail: row.storeEmail,
    homepageImage: row.homepageImage,
    ceoImage: row.ceoImage,
    adminPassword: row.adminPassword,
    deliveryLocations: parseJsonColumn(row.deliveryLocations)
  };
}
async function saveSettings(data) {
  const [rows] = await pool.query("SELECT COUNT(*) as count FROM settings WHERE id = 'global'");
  const bankEnabled = data.bankEnabled !== void 0 ? data.bankEnabled ? 1 : 0 : 1;
  const monnifyEnabled = data.monnifyEnabled !== void 0 ? data.monnifyEnabled ? 1 : 0 : 1;
  const bankName = data.bankName || DEFAULT_SETTINGS.bankName;
  const accountName = data.accountName || DEFAULT_SETTINGS.accountName;
  const accountNumber = data.accountNumber || DEFAULT_SETTINGS.accountNumber;
  const monnifyApiKey = data.monnifyApiKey || DEFAULT_SETTINGS.monnifyApiKey;
  const monnifyContractCode = data.monnifyContractCode || DEFAULT_SETTINGS.monnifyContractCode;
  const monnifySecretKey = data.monnifySecretKey || DEFAULT_SETTINGS.monnifySecretKey;
  const storeAddress = data.storeAddress || DEFAULT_SETTINGS.storeAddress;
  const storePhone = data.storePhone || DEFAULT_SETTINGS.storePhone;
  const storeEmail = data.storeEmail || DEFAULT_SETTINGS.storeEmail;
  const deliveryLocations = JSON.stringify(data.deliveryLocations || DEFAULT_SETTINGS.deliveryLocations);
  const homepageImage = data.homepageImage || DEFAULT_SETTINGS.homepageImage;
  const ceoImage = data.ceoImage || DEFAULT_SETTINGS.ceoImage;
  const adminPassword = data.adminPassword || DEFAULT_SETTINGS.adminPassword;
  if (rows[0].count === 0) {
    await pool.query(
      `INSERT INTO settings 
       (id, bankEnabled, monnifyEnabled, bankName, accountName, accountNumber, monnifyApiKey, monnifyContractCode, monnifySecretKey, storeAddress, storePhone, storeEmail, deliveryLocations, homepageImage, ceoImage, adminPassword) 
       VALUES ('global', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
      [
        bankEnabled,
        monnifyEnabled,
        bankName,
        accountName,
        accountNumber,
        monnifyApiKey,
        monnifyContractCode,
        monnifySecretKey,
        storeAddress,
        storePhone,
        storeEmail,
        deliveryLocations,
        homepageImage,
        ceoImage,
        adminPassword
      ]
    );
  } else {
    await pool.query(
      `UPDATE settings SET 
       bankEnabled = ?, monnifyEnabled = ?, bankName = ?, accountName = ?, accountNumber = ?, 
       monnifyApiKey = ?, monnifyContractCode = ?, monnifySecretKey = ?, 
       storeAddress = ?, storePhone = ?, storeEmail = ?, deliveryLocations = ?, homepageImage = ?, ceoImage = ?, adminPassword = ? 
       WHERE id = 'global'`,
      [
        bankEnabled,
        monnifyEnabled,
        bankName,
        accountName,
        accountNumber,
        monnifyApiKey,
        monnifyContractCode,
        monnifySecretKey,
        storeAddress,
        storePhone,
        storeEmail,
        deliveryLocations,
        homepageImage,
        ceoImage,
        adminPassword
      ]
    );
  }
  return getSettings();
}

// server.ts
var import_url = require("url");
var import_multer = __toESM(require("multer"), 1);
var import_promise2 = __toESM(require("mysql2/promise"), 1);
var import_meta = {};
import_dotenv.default.config();
var _dirname;
try {
  _dirname = __dirname;
} catch {
  _dirname = import_path.default.dirname((0, import_url.fileURLToPath)(import_meta.url));
}
var app = (0, import_express.default)();
var PORT = process.env.PORT || 3e3;
var supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL;
var supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY;
var supabase = null;
var supabaseStatus = "disconnected";
var supabaseError = "";
if (supabaseUrl && supabaseUrl.startsWith("http") && supabaseKey && supabaseKey !== "your-supabase-key") {
  try {
    supabase = (0, import_supabase_js.createClient)(supabaseUrl, supabaseKey, {
      auth: { persistSession: false }
    });
    supabaseStatus = "initialized";
    console.log("Supabase client initialized successfully with URL:", supabaseUrl);
  } catch (err) {
    supabaseStatus = "error";
    supabaseError = err.message || String(err);
    console.error("Failed to initialize Supabase client:", err);
  }
} else {
  supabaseStatus = "not_configured";
  console.log("Supabase environment variables not defined. Standalone local DB only.");
}
app.use(import_express.default.json({ limit: "50mb" }));
app.use(import_express.default.urlencoded({ limit: "50mb", extended: true }));
app.use("/uploads", import_express.default.static(import_path.default.join(process.cwd(), "uploads")));
var storage = import_multer.default.diskStorage({
  destination: function(req, file, cb) {
    cb(null, import_path.default.join(process.cwd(), "uploads"));
  },
  filename: function(req, file, cb) {
    const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9);
    cb(null, uniqueSuffix + import_path.default.extname(file.originalname));
  }
});
var upload = (0, import_multer.default)({
  storage,
  fileFilter: (req, file, cb) => {
    if (file.mimetype.startsWith("image/")) {
      cb(null, true);
    } else {
      cb(new Error("Only images are allowed"));
    }
  },
  limits: { fileSize: 10 * 1024 * 1024 }
  // 10MB limit
});
var DATA_FILE = import_path.default.join(process.cwd(), "db.json");
async function loadDatabase() {
  try {
    await initDb();
    console.log("MySQL Database & Schema successfully initialized.");
  } catch (err) {
    console.error("Failed to load/initialize MySQL database:", err);
  }
}
async function syncFromSupabase() {
  if (!supabase) return;
  console.log("Attempting to warm database from Supabase cloud...");
  try {
    const { data: cats, error: catErr } = await supabase.from("categories").select("*");
    if (catErr) {
      console.warn("Could not fetch categories from Supabase (it might not exist yet):", catErr.message);
    } else if (cats && cats.length > 0) {
      for (const cat of cats) {
        await updateCategory(cat.id, cat).then((res) => {
          if (!res) return addCategory(cat);
        });
      }
      console.log(`Synced ${cats.length} categories from Supabase`);
    }
    const { data: prods, error: prodErr } = await supabase.from("products").select("*");
    if (prodErr) {
      console.warn("Could not fetch products from Supabase:", prodErr.message);
    } else if (prods && prods.length > 0) {
      for (const p of prods) {
        const ingredients = typeof p.ingredients === "string" ? JSON.parse(p.ingredients) : p.ingredients || [];
        const benefits = typeof p.benefits === "string" ? JSON.parse(p.benefits) : p.benefits || [];
        const pMapped = { ...p, ingredients, benefits };
        await updateProduct(p.id, pMapped).then((res) => {
          if (!res) return addProduct(pMapped);
        });
      }
      console.log(`Synced ${prods.length} products from Supabase`);
    }
    const { data: books, error: bookErr } = await supabase.from("bookings").select("*");
    if (bookErr) {
      console.warn("Could not fetch bookings from Supabase:", bookErr.message);
    } else if (books) {
      for (const b of books) {
        await updateBooking(b.id, b).then((res) => {
          if (!res) return addBooking(b);
        });
      }
      console.log(`Synced ${books.length} bookings from Supabase`);
    }
    const { data: ords, error: ordErr } = await supabase.from("orders").select("*");
    if (ordErr) {
      console.warn("Could not fetch orders from Supabase:", ordErr.message);
    } else if (ords) {
      for (const o of ords) {
        const items = typeof o.items === "string" ? JSON.parse(o.items) : o.items || [];
        const billingAddress = typeof o.billingAddress === "string" ? JSON.parse(o.billingAddress) : o.billingAddress || null;
        const oMapped = { ...o, items, billingAddress };
        await updateOrder(o.id, oMapped).then((res) => {
          if (!res) return addOrder(oMapped);
        });
      }
      console.log(`Synced ${ords.length} orders from Supabase`);
    }
    const { data: faqs, error: faqErr } = await supabase.from("faqs").select("*");
    if (faqErr) {
      console.warn("Could not fetch faqs from Supabase:", faqErr.message);
    } else if (faqs && faqs.length > 0) {
      await setFaqs(faqs);
      console.log(`Synced ${faqs.length} FAQs from Supabase`);
    }
    supabaseStatus = "connected";
  } catch (err) {
    supabaseStatus = "error";
    supabaseError = err.message || String(err);
    console.error("Error during Supabase sync session:", err.message || err);
  }
}
async function replicateUpsert(table, record) {
  if (!supabase) return;
  try {
    let payload = { ...record };
    if (table === "products") {
      payload.ingredients = typeof record.ingredients === "object" ? JSON.stringify(record.ingredients) : record.ingredients;
      payload.benefits = typeof record.benefits === "object" ? JSON.stringify(record.benefits) : record.benefits;
    }
    if (table === "orders") {
      payload.items = typeof record.items === "object" ? JSON.stringify(record.items) : record.items;
      payload.billingAddress = typeof record.billingAddress === "object" ? JSON.stringify(record.billingAddress) : record.billingAddress;
    }
    const { error } = await supabase.from(table).upsert(payload);
    if (error) {
      console.error(`[Supabase Error] failed to upsert on table ${table}:`, error.message);
    } else {
      console.log(`[Supabase Sync] successfully replicated upsert to table ${table} for id: ${record.id}`);
    }
  } catch (err) {
    console.error(`[Supabase Sync Exception] on table ${table}:`, err.message || err);
  }
}
async function replicateDelete(table, id) {
  if (!supabase) return;
  try {
    const { error } = await supabase.from(table).delete().eq("id", id);
    if (error) {
      console.error(`[Supabase Error] failed to delete from table ${table}:`, error.message);
    } else {
      console.log(`[Supabase Sync] successfully replicated delete from table ${table} for id: ${id}`);
    }
  } catch (err) {
    console.error(`[Supabase Sync Exception] on table ${table}:`, err.message || err);
  }
}
async function replicateFaqs(faqsList) {
  if (!supabase) return;
  try {
    await supabase.from("faqs").delete().neq("id", "dummy-force-all");
    if (faqsList.length > 0) {
      const { error } = await supabase.from("faqs").insert(faqsList);
      if (error) {
        console.error(`[Supabase Error] failed to sync FAQs:`, error.message);
      } else {
        console.log(`[Supabase Sync] successfully synced ${faqsList.length} FAQs`);
      }
    }
  } catch (err) {
    console.error(`[Supabase Sync Exception] FAQs:`, err.message || err);
  }
}
loadDatabase().then(() => {
  syncFromSupabase().catch((err) => {
    console.error("Async background Supabase sync startup failed:", err);
  });
});
app.post("/api/upload", upload.single("image"), (req, res) => {
  if (!req.file) {
    return res.status(400).json({ error: "No image file provided." });
  }
  const imageUrl = `/uploads/${req.file.filename}`;
  res.status(200).json({ url: imageUrl });
});
app.get("/api/categories", async (req, res) => {
  try {
    const categories = await getCategories();
    res.json(categories);
  } catch (error) {
    console.error("Failed to fetch categories:", error);
    res.status(500).json({ error: error.message });
  }
});
app.post("/api/categories", async (req, res) => {
  try {
    const newCat = await addCategory(req.body);
    replicateUpsert("categories", newCat).catch((err) => console.error(err));
    res.status(201).json(newCat);
  } catch (error) {
    console.error("Failed to add category:", error);
    res.status(500).json({ error: error.message });
  }
});
app.put("/api/categories/:id", async (req, res) => {
  try {
    const { id } = req.params;
    const updated = await updateCategory(id, req.body);
    if (updated) {
      replicateUpsert("categories", updated).catch((err) => console.error(err));
      res.json(updated);
    } else {
      res.status(404).json({ error: "Category not found" });
    }
  } catch (error) {
    console.error("Failed to update category:", error);
    res.status(500).json({ error: error.message });
  }
});
app.delete("/api/categories/:id", async (req, res) => {
  try {
    const { id } = req.params;
    const deleted = await deleteCategory(id);
    if (deleted) {
      replicateDelete("categories", id).catch((err) => console.error(err));
      res.json({ success: true, message: "Category deleted" });
    } else {
      res.status(404).json({ error: "Category not found" });
    }
  } catch (error) {
    console.error("Failed to delete category:", error);
    res.status(500).json({ error: error.message });
  }
});
app.get("/api/products", async (req, res) => {
  try {
    const products = await getProducts();
    res.json(products);
  } catch (error) {
    console.error("Failed to fetch products:", error);
    res.status(500).json({ error: error.message });
  }
});
app.post("/api/products", async (req, res) => {
  try {
    const newProd = await addProduct(req.body);
    replicateUpsert("products", newProd).catch((err) => console.error(err));
    res.status(201).json(newProd);
  } catch (error) {
    console.error("Failed to add product:", error);
    res.status(500).json({ error: error.message });
  }
});
app.put("/api/products/:id", async (req, res) => {
  try {
    const { id } = req.params;
    const updated = await updateProduct(id, req.body);
    if (updated) {
      replicateUpsert("products", updated).catch((err) => console.error(err));
      res.json(updated);
    } else {
      res.status(404).json({ error: "Product not found" });
    }
  } catch (error) {
    console.error("Failed to update product:", error);
    res.status(500).json({ error: error.message });
  }
});
app.delete("/api/products/:id", async (req, res) => {
  try {
    const { id } = req.params;
    const deleted = await deleteProduct(id);
    if (deleted) {
      replicateDelete("products", id).catch((err) => console.error(err));
      res.json({ success: true, message: "Product deleted successfully" });
    } else {
      res.status(404).json({ error: "Product not found" });
    }
  } catch (error) {
    console.error("Failed to delete product:", error);
    res.status(500).json({ error: error.message });
  }
});
app.get("/api/bookings", async (req, res) => {
  try {
    const bookings = await getBookings();
    res.json(bookings);
  } catch (error) {
    console.error("Failed to fetch bookings:", error);
    res.status(500).json({ error: error.message });
  }
});
app.post("/api/bookings", async (req, res) => {
  try {
    const newBooking = await addBooking(req.body);
    replicateUpsert("bookings", newBooking).catch((err) => console.error(err));
    console.log(`[ALERT] NEW APPOINTMENT BOOKING: Type: ${newBooking.consultationType}, Name: ${newBooking.name}, Date: ${newBooking.date} ${newBooking.time}`);
    res.status(201).json(newBooking);
  } catch (error) {
    console.error("Failed to add booking:", error);
    res.status(500).json({ error: error.message });
  }
});
app.put("/api/bookings/:id", async (req, res) => {
  try {
    const { id } = req.params;
    const updated = await updateBooking(id, req.body);
    if (updated) {
      replicateUpsert("bookings", updated).catch((err) => console.error(err));
      res.json(updated);
    } else {
      res.status(404).json({ error: "Booking not found" });
    }
  } catch (error) {
    console.error("Failed to update booking:", error);
    res.status(500).json({ error: error.message });
  }
});
app.get("/api/orders", async (req, res) => {
  try {
    const orders = await getOrders();
    res.json(orders);
  } catch (error) {
    console.error("Failed to fetch orders:", error);
    res.status(500).json({ error: error.message });
  }
});
app.post("/api/orders", async (req, res) => {
  try {
    const newOrder = await addOrder(req.body);
    const items = newOrder.items || [];
    for (const item of items) {
      const prods = await getProducts();
      const existingProduct = prods.find((p) => p.id === item.productId);
      if (existingProduct) {
        const newStock = Math.max(0, existingProduct.stock - item.quantity);
        const updatedProduct = await updateProduct(item.productId, { stock: newStock });
        if (updatedProduct) {
          replicateUpsert("products", updatedProduct).catch((err) => console.error(err));
        }
      }
    }
    replicateUpsert("orders", newOrder).catch((err) => console.error(err));
    console.log(`[ALERT] NEW ORDER SUBMITTED: #${newOrder.orderNumber}, Customer: ${newOrder.customerName}, Total: \u20A6${newOrder.totalAmount}`);
    res.status(201).json(newOrder);
  } catch (error) {
    console.error("Failed to create order:", error);
    res.status(500).json({ error: error.message });
  }
});
app.put("/api/orders/:id", async (req, res) => {
  try {
    const { id } = req.params;
    const updated = await updateOrder(id, req.body);
    if (updated) {
      replicateUpsert("orders", updated).catch((err) => console.error(err));
      res.json(updated);
    } else {
      res.status(404).json({ error: "Order not found" });
    }
  } catch (error) {
    console.error("Failed to update order:", error);
    res.status(500).json({ error: error.message });
  }
});
app.get("/api/faqs", async (req, res) => {
  try {
    const faqs = await getFaqs();
    res.json(faqs);
  } catch (error) {
    console.error("Failed to fetch FAQs:", error);
    res.status(500).json({ error: error.message });
  }
});
app.put("/api/faqs", async (req, res) => {
  try {
    if (Array.isArray(req.body)) {
      const faqs = await setFaqs(req.body);
      replicateFaqs(faqs).catch((err) => console.error(err));
      res.json({ success: true, faqs });
    } else {
      res.status(400).json({ error: "Body must be an array of FAQs" });
    }
  } catch (error) {
    console.error("Failed to update FAQs:", error);
    res.status(500).json({ error: error.message });
  }
});
app.get("/api/settings", async (req, res) => {
  try {
    const settings = await getSettings();
    res.json(settings);
  } catch (error) {
    console.error("Failed to fetch settings:", error);
    res.status(500).json({ error: error.message });
  }
});
app.post("/api/settings", async (req, res) => {
  try {
    await saveSettings(req.body);
    const updatedSettings = await getSettings();
    res.json(updatedSettings);
  } catch (error) {
    console.error("Failed to update settings:", error);
    res.status(500).json({ error: error.message });
  }
});
app.post("/api/gemini/consultation", async (req, res) => {
  try {
    const { messages } = req.body;
    if (!messages || !Array.isArray(messages)) {
      return res.status(400).json({ error: "Messages array is required." });
    }
    const key = process.env.GEMINI_API_KEY;
    if (!key) {
      console.warn("Missing GEMINI_API_KEY env. Falling back to simulated response.");
      return res.json({
        reply: "Welcome to our Nigerian Herbal Wellness assistant! Currently, the system-level Gemini API key has not been specified, so I am running in local consultation mode.\n\nFor general wellness: We highly recommend our **Ew\xE9 Moringa Premium Tea Blend** to elevate your organic vital energy, and our **Ori Luxury Whipped Shea Butter** to naturally restore dry skin complexions. Please let us know if you want to book a wellness appointment!"
      });
    }
    const ai = new import_genai.GoogleGenAI({
      apiKey: key,
      httpOptions: {
        headers: {
          "User-Agent": "aistudio-build"
        }
      }
    });
    const productsList = await getProducts();
    const faqsList = await getFaqs();
    const productsContext = productsList.map((p) => `- ${p.name} (Category: ${p.category}, Price: \u20A6${p.price}): ${p.description}. Ingredients: ${p.ingredients.join(", ")}. Benefits: ${p.benefits.join(". ")}`).join("\n\n");
    const faqsContext = faqsList.map((f) => `Q: ${f.question}
A: ${f.answer}`).join("\n\n");
    const systemInstruction = `You are a warm, traditional, highly experienced Nigerian herbal wellness and holistic lifestyle guide.
Your voice is premium, modern, clean, deeply welcoming, and completely professional.
You offer advice grounded in historical West African herbal therapy, modern food science, and general holistic living (mindfulness, gentle movement, resting patterns, hydration, skin routine).

CORE COMPLIANCE AND SAFETY RULES:
1. YOU ARE STRICTLY FORBIDDEN from offering formal medical diagnoses.
2. DO NOT promise quick cures, miracles, or mention high-risk conditions like treating skin cancer, curing hypertension, kidney failure, diabetes, etc. Instead, suggest general supportive, balancing nourishment traits.
3. ALWAYS add a subtle natural wellness disclaimer where applicable: "Herbal products are intended for general wellness support, and individual results can vary."
4. If a user presents severe acute clinical symptoms (e.g., severe painful breathing, high fever lasting weeks, massive painful skin wounds), gently advise them to seek a primary health physician or clinical examination.
5. RECOMMEND our authentic Nigerian herbal product range actively! Align your organic recommendations to our specific list of products below. Bring alive the premium brand tone.

OUR PRODUCT RANGE:
${productsContext}

PRE-SET FREQUENTLY ASKED QUESTIONS FOR ACCURATE ALIGNMENT:
${faqsContext}

Format your response in neat, highly human-readable markdown paragraphs and bullet points in English. Keep individual answers highly personalized, engaging, and empathetic. Include a subtle touch of warmth (e.g., occasional popular Nigerian greeting particles like "\u1EB8 n l\u1EB9" or "Welcome" with utmost premium luxury refinement). No fake system telemetry tags or robotic noise. Only clear, supportive premium wellness consulting.`;
    const conversationHistory = messages.map((m) => `${m.sender.toUpperCase()}: ${m.text}`).join("\n");
    const response = await ai.models.generateContent({
      model: "gemini-2.0-flash",
      contents: `This is the user text conversation so far:
${conversationHistory}

AI:`,
      config: {
        systemInstruction,
        temperature: 0.75
      }
    });
    const replyText = response.text || "I am here to support your holistic wellness journey. Please tell me more about your daily rhythms, sleep levels, or skincare habits, and I'll suggest a fine organic herbal match.";
    res.json({ reply: replyText });
  } catch (error) {
    console.error("Gemini server-side error path:", error);
    res.status(500).json({ error: "Failed to query the AI consultation module. Please try again." });
  }
});
app.get("/api/diagnostics", async (req, res) => {
  const envVars = {
    DB_HOST: process.env.DB_HOST,
    DB_PORT: process.env.DB_PORT,
    DB_USER: process.env.DB_USER,
    DB_NAME: process.env.DB_NAME,
    hasPassword: !!process.env.DB_PASSWORD,
    NODE_ENV: process.env.NODE_ENV,
    CWD: process.cwd(),
    DIRNAME: _dirname
  };
  let connectionTest = "pending";
  let connectionError = null;
  try {
    const conn = await import_promise2.default.createConnection({
      host: process.env.DB_HOST || "localhost",
      port: parseInt(process.env.DB_PORT || "3306", 10),
      user: process.env.DB_USER || "root",
      password: process.env.DB_PASSWORD || "",
      database: process.env.DB_NAME || "mummy_ayofe"
    });
    await conn.ping();
    await conn.end();
    connectionTest = "success";
  } catch (err) {
    connectionTest = "failed";
    connectionError = {
      message: err.message,
      code: err.code,
      errno: err.errno,
      sqlState: err.sqlState,
      sqlMessage: err.sqlMessage
    };
  }
  res.json({
    env: envVars,
    dbConnection: connectionTest,
    dbErrorDetails: connectionError,
    time: (/* @__PURE__ */ new Date()).toISOString()
  });
});
app.get("/api/setup/status", async (req, res) => {
  const geminiKey = process.env.GEMINI_API_KEY;
  const geminiKeySet = !!geminiKey;
  let geminiKeyFormatValid = false;
  if (geminiKeySet) {
    geminiKeyFormatValid = geminiKey.trim().startsWith("AIzaSy") || geminiKey.trim().length >= 15;
  }
  let dbStatus = "disconnected";
  let dbWritable = false;
  let dbError = "";
  let counts = { products: 0, bookings: 0, orders: 0, faqs: 0 };
  try {
    const products = await getProducts();
    const bookings = await getBookings();
    const orders = await getOrders();
    const faqs = await getFaqs();
    dbStatus = "connected";
    dbWritable = true;
    counts = {
      products: products.length,
      bookings: bookings.length,
      orders: orders.length,
      faqs: faqs.length
    };
  } catch (err) {
    dbStatus = "error";
    dbError = err.message || String(err);
  }
  res.json({
    geminiKeySet,
    geminiKeyFormatValid,
    dbStatus,
    dbPath: "MySQL Connection Pool",
    dbSize: 0,
    dbWritable,
    dbError,
    counts,
    nodeEnv: process.env.NODE_ENV || "development",
    serverTime: (/* @__PURE__ */ new Date()).toISOString(),
    supabaseCredentialsSet: !!supabaseUrl && !!supabaseKey,
    supabaseClientInitialized: !!supabase,
    supabaseStatus,
    supabaseError
  });
});
app.get("/api/settings", async (req, res) => {
  try {
    const settings = await getSettings();
    res.json(settings);
  } catch (error) {
    console.error("Failed to fetch settings:", error);
    res.status(500).json({ error: error.message });
  }
});
app.post("/api/settings", async (req, res) => {
  try {
    const settings = await saveSettings(req.body);
    res.json({ success: true, settings });
  } catch (error) {
    console.error("Failed to save settings:", error);
    res.status(500).json({ error: error.message });
  }
});
app.post("/api/setup/test-gemini", async (req, res) => {
  const key = process.env.GEMINI_API_KEY;
  if (!key) {
    return res.status(400).json({
      success: false,
      error: "GEMINI_API_KEY is not configured in the environment variables."
    });
  }
  try {
    const ai = new import_genai.GoogleGenAI({
      apiKey: key,
      httpOptions: {
        headers: {
          "User-Agent": "aistudio-build"
        }
      }
    });
    const response = await ai.models.generateContent({
      model: "gemini-2.0-flash",
      contents: "Confirm API authorization status. Respond with exactly 'CONNECTION_TEST_OK'"
    });
    const text = response.text?.trim() || "No text received";
    res.json({
      success: true,
      response: text,
      message: "The Gemini API integration completed a full round-trip handshake successfully."
    });
  } catch (error) {
    console.error("Setup diagnostic Gemini error:", error);
    res.status(500).json({
      success: false,
      error: error.message || String(error)
    });
  }
});
async function initServer() {
  if (process.env.NODE_ENV !== "production") {
    const vite = await (0, import_vite.createServer)({
      server: { middlewareMode: true },
      appType: "spa"
    });
    app.use(vite.middlewares);
  } else {
    const distPath = import_path.default.resolve(_dirname);
    app.use(import_express.default.static(distPath));
    app.get("*", (req, res) => {
      const potential = import_path.default.join(distPath, req.path);
      if (import_fs.default.existsSync(potential) && import_fs.default.statSync(potential).isFile()) {
        return res.sendFile(potential);
      }
      res.sendFile(import_path.default.join(distPath, "index.html"));
    });
  }
  const port = Number(PORT) || 3e3;
  app.listen(port, "0.0.0.0", () => {
    console.log(`Nigerian Herbal Wellness backend server active on http://localhost:${port}`);
  });
}
initServer().catch((err) => {
  console.error("Failed to start the Express server setup:", err);
});
//# sourceMappingURL=server.cjs.map
