/* Seeds demo catalogue, homepage, pages, navigation, shipping and (clearly labelled) demo orders.
   Run: npm run db:seed        Re-running is safe: it clears catalogue/content tables first.
   Does NOT create admin accounts — use `npm run admin:create`. */
import "dotenv/config";
import { PrismaClient, type Prisma, type SaleMode } from "@prisma/client";
import { PrismaMariaDb } from "@prisma/adapter-mariadb";
import { randomBytes } from "crypto";
import catalog from "./demo-catalog.json";

const url = new URL(process.env.DATABASE_URL!);
const db = new PrismaClient({
  adapter: new PrismaMariaDb({
    host: url.hostname, port: Number(url.port || 3306), user: decodeURIComponent(url.username),
    password: url.password ? decodeURIComponent(url.password) : undefined, database: url.pathname.slice(1),
    connectionLimit: 3, allowPublicKeyRetrieval: true,
  }),
});

const day = (n: number) => { const d = new Date(); d.setHours(12, 0, 0, 0); d.setDate(d.getDate() + n); return d; };
const slug = (s: string) => s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
const img = (p: string, colour: string, n = 1) => `/demo/${p}-${slug(colour)}-${n}.jpg`;

type CatProduct = (typeof catalog.products)[number] & { sizes?: string[]; stock?: number; batch?: Record<string, unknown> & { committed?: number }; featured?: boolean };

async function wipe() {
  // Order matters for foreign keys.
  await db.orderEvent.deleteMany(); await db.payment.deleteMany(); await db.orderItem.deleteMany(); await db.order.deleteMany();
  await db.cartItem.deleteMany(); await db.cart.deleteMany(); await db.wishlistItem.deleteMany();
  await db.collectionProduct.deleteMany(); await db.collection.deleteMany();
  await db.productImage.deleteMany(); await db.productVariant.deleteMany(); await db.preorderBatch.deleteMany(); await db.product.deleteMany(); await db.category.deleteMany();
  await db.homepageSection.deleteMany(); await db.homepageRevision.deleteMany(); await db.page.deleteMany(); await db.faqItem.deleteMany(); await db.menuItem.deleteMany();
  await db.editorialPost.deleteMany(); await db.shippingZone.deleteMany(); await db.discountCode.deleteMany();
}

async function main() {
  await wipe();

  const cats: Record<string, string> = {};
  for (const [i, c] of catalog.categories.entries()) {
    const row = await db.category.create({ data: { slug: c.slug, name: c.name, description: c.description, imageUrl: c.image, hoverUrl: c.hover, sortOrder: i } });
    cats[c.slug] = row.id;
  }

  const products: Record<string, { id: string; variants: { id: string; mode: SaleMode; batchId: string | null; price: number; label: string; sku: string; color: string | null }[]; image: string; name: string; category: string }> = {};
  for (const [pi, raw] of (catalog.products as CatProduct[]).entries()) {
    const p = raw;
    const product = await db.product.create({
      data: {
        slug: p.slug, sku: p.sku, name: p.name, shortDescription: p.short, description: p.description,
        materials: p.materials, care: p.care, specs: p.specs.map(([label, value]) => ({ label, value })),
        sizeGuide: p.sizes ? "Measure your bust, waist and hips and compare with the chart. Between sizes? Choose the larger size for a relaxed fit.\n\n| Size | Bust | Waist | Hip |\n|---|---|---|---|\n| S | 84–88 cm | 66–70 cm | 90–94 cm |\n| M | 89–93 cm | 71–75 cm | 95–99 cm |\n| L | 94–99 cm | 76–81 cm | 100–105 cm |\n| XL | 100–106 cm | 82–88 cm | 106–112 cm |" : null,
        basePrice: p.price, categoryId: cats[p.category], status: "PUBLISHED", featured: !!p.featured, sortOrder: pi,
        seoTitle: `${p.name} | Veloura`, seoDesc: p.short,
      },
    });
    let batchId: string | null = null;
    if (p.mode === "PRE_ORDER" && p.batch) {
      const b = p.batch as { code: string; capacity: number; committed?: number; openDays: number; closeDays: number; dispatchFromDays: number; dispatchToDays: number; payment: "FULL_ONLY" | "DEPOSIT_OPTIONAL" | "DEPOSIT_REQUIRED"; depositType: "PERCENT" | "FIXED"; deposit: number };
      const batch = await db.preorderBatch.create({
        data: {
          productId: product.id, code: b.code, capacity: b.capacity, committedQty: b.committed ?? 0,
          opensAt: day(b.openDays), closesAt: day(b.closeDays), dispatchFrom: day(b.dispatchFromDays), dispatchTo: day(b.dispatchToDays),
          deliveryNote: "Delivery inside Dhaka usually takes 1–2 days after dispatch, outside Dhaka 2–4 days.",
          paymentOption: b.payment, depositType: b.depositType, depositValue: b.deposit, balanceDueDays: 3,
        },
      });
      batchId = batch.id;
    }
    const sizes = p.sizes ?? [null];
    const vs: (typeof products)[string]["variants"] = [];
    let vi = 0;
    for (const [colour, hex] of p.colours as [string, unknown][]) {
      for (const size of sizes) {
        const sku = `${p.sku}-${slug(colour).slice(0, 4).toUpperCase()}${size ? `-${size}` : ""}`;
        const v = await db.productVariant.create({
          data: {
            productId: product.id, sku, color: colour, colorHex: typeof hex === "string" && hex.startsWith("#") ? hex : hex === "gold" ? "#C9A55C" : hex === "silver" ? "#C9CDD2" : Array.isArray(hex) ? (hex[0] as string) : null,
            size, mode: p.mode as SaleMode, stockQty: p.mode === "READY_STOCK" ? (p.stock ?? 0) : 0, batchId, sortOrder: vi++,
          },
        });
        vs.push({ id: v.id, mode: v.mode, batchId, price: p.price, label: [colour, size].filter(Boolean).join(" / "), sku, color: colour });
      }
      await db.productImage.createMany({
        data: [1, 2].map((n, k) => ({ productId: product.id, color: colour, url: img(p.slug, colour, n), alt: `${p.name} in ${colour.toLowerCase()}${n === 2 ? ", detail" : ""}`, sortOrder: (p.colours.findIndex((c) => c[0] === colour)) * 10 + k })),
      });
    }
    products[p.slug] = { id: product.id, variants: vs, image: img(p.slug, (p.colours[0] as [string, unknown])[0]), name: p.name, category: p.category };
  }

  const P = (s: string) => products[s].id;
  const preorderSlugs = (catalog.products as CatProduct[]).filter((p) => p.mode === "PRE_ORDER").map((p) => p.slug);

  await db.collection.create({
    data: {
      slug: "winter-pre-order", title: "The winter pre-order", intro: "Pieces made in this season's batches. Reserve with a deposit, pay the balance before dispatch.", imageUrl: "/demo/scene-dresses.jpg",
      products: { create: preorderSlugs.map((s, i) => ({ productId: P(s), sortOrder: i })) },
    },
  });
  await db.collection.create({
    data: {
      slug: "evening-edit", title: "The evening edit", intro: "A clutch, a wrap dress and the jewellery to go with them.", imageUrl: "/demo/scene-accessories.jpg",
      products: { create: ["evening-box-clutch", "evening-wrap-dress", "pleated-slip-dress", "pearl-drop-earrings", "minimal-chain-necklace"].map((s, i) => ({ productId: P(s), sortOrder: i })) },
    },
  });
  await db.collection.create({
    data: {
      slug: "ready-to-ship", title: "Ready to ship", intro: "In stock now and dispatched within two working days.",
      products: { create: (catalog.products as CatProduct[]).filter((p) => p.mode === "READY_STOCK").map((p, i) => ({ productId: P(p.slug), sortOrder: i })) },
    },
  });

  // Related products: same category
  for (const p of catalog.products) {
    const rel = catalog.products.filter((o) => o.category === p.category && o.slug !== p.slug).slice(0, 4).map((o) => P(o.slug));
    await db.product.update({ where: { id: P(p.slug) }, data: { relatedIds: rel } });
  }

  // ───────── shipping & discounts (editable demo values) ─────────
  await db.shippingZone.createMany({
    data: [
      { name: "Inside Dhaka", districts: ["Dhaka"], fee: 80, freeOver: 6000, etaText: "1–2 days after dispatch", sortOrder: 0 },
      { name: "Dhaka suburbs", districts: ["Gazipur", "Narayanganj", "Savar", "Keraniganj"], fee: 120, freeOver: 6000, etaText: "2–3 days after dispatch", sortOrder: 1 },
      { name: "Outside Dhaka", districts: ["*"], fee: 150, freeOver: 8000, etaText: "2–4 days after dispatch", sortOrder: 2 },
    ],
  });
  await db.discountCode.create({ data: { code: "WELCOME10", type: "PERCENT", value: 10, minSubtotal: 2000, usageLimit: 200 } });

  // ───────── homepage (reference section order) ─────────
  const sections: { type: Prisma.HomepageSectionCreateInput["type"]; label: string; data: Prisma.InputJsonValue }[] = [
    { type: "CATEGORY_FEATURE", label: "Bags feature", data: { title: "Bags", href: "/collections/bags", panels: [
      { image: img("everyday-shoulder-bag", "Cocoa"), hoverImage: img("everyday-shoulder-bag", "Cocoa", 2), alt: "Everyday Shoulder Bag in cocoa", href: "/products/everyday-shoulder-bag" },
      { image: img("structured-mini-tote", "Sand"), hoverImage: img("structured-mini-tote", "Espresso"), alt: "Structured Mini Tote in sand", href: "/products/structured-mini-tote" },
      { image: img("weekend-crossbody", "Caramel"), hoverImage: img("weekend-crossbody", "Olive"), alt: "Weekend Crossbody in caramel", href: "/products/weekend-crossbody" },
      { image: img("evening-box-clutch", "Black"), hoverImage: img("evening-box-clutch", "Champagne"), alt: "Evening Box Clutch in black", href: "/products/evening-box-clutch" },
    ] } },
    { type: "CATEGORY_FEATURE", label: "Dresses feature", data: { title: "Dresses", href: "/collections/dresses", panels: [
      { image: img("evening-wrap-dress", "Emerald"), hoverImage: img("evening-wrap-dress", "Wine"), alt: "Evening Wrap Dress in emerald", href: "/products/evening-wrap-dress" },
      { image: img("everyday-midi-dress", "Rosewood"), hoverImage: img("everyday-midi-dress", "Sage"), alt: "Everyday Midi Dress in rosewood", href: "/products/everyday-midi-dress" },
      { image: img("tiered-cotton-maxi", "Mustard"), hoverImage: img("tiered-cotton-maxi", "White"), alt: "Tiered Cotton Maxi in mustard", href: "/products/tiered-cotton-maxi" },
      { image: img("relaxed-shirt-dress", "Sky"), hoverImage: img("relaxed-shirt-dress", "Ecru"), alt: "Relaxed Shirt Dress in sky", href: "/products/relaxed-shirt-dress" },
    ] } },
    { type: "EDITORIAL_TRIPTYCH", label: "Pre-order introduction", data: {
      large: "/demo/scene-story.jpg", smallA: img("crescent-hobo-bag", "Chestnut"), smallB: img("linen-day-dress", "Oat"),
      title: "Made in batches", body: "Most Veloura pieces are made to order in small batches. You reserve a place with a deposit or full payment, we produce once the batch closes, and every product page shows the batch size, closing date and estimated dispatch window before you pay.",
      ctaLabel: "Shop now", ctaHref: "/shop" } },
    { type: "PRODUCT_STORIES", label: "Product stories", data: { title: "This season's batches", stories: [
      { productId: P("structured-mini-tote"), caption: "Batch of 40", body: "An upright tote that holds its shape on a firm base. Carry it by the twin handles or clip on the long strap.", ctaLabel: "Shop bags", ctaHref: "/collections/bags" },
      { productId: P("evening-wrap-dress"), caption: "Batch of 50", body: "A true wrap in fluid satin. The wrap adjusts to your fit and the skirt falls to mid-calf with a soft front split.", ctaLabel: "Shop dresses", ctaHref: "/collections/dresses" },
      { productId: P("pearl-drop-earrings"), caption: "Batch of 60", body: "A single glass pearl on a fine bar. Light enough to wear all evening.", ctaLabel: "Shop accessories", ctaHref: "/collections/accessories" },
    ] } },
    { type: "CATEGORY_INDEX", label: "Category index", data: { items: [
      { label: "Bags", href: "/collections/bags", image: img("everyday-shoulder-bag", "Ivory") },
      { label: "Dresses", href: "/collections/dresses", image: img("everyday-midi-dress", "Sage") },
      { label: "Accessories", href: "/collections/accessories", image: img("silk-feel-printed-scarf", "Navy") },
      { label: "Pre-order", href: "/collections/winter-pre-order", image: img("structured-mini-tote", "Espresso") },
      { label: "Ready to ship", href: "/collections/ready-to-ship", image: img("weekend-crossbody", "Olive") },
      { label: "Evening edit", href: "/collections/evening-edit", image: img("evening-box-clutch", "Champagne") },
    ] } },
    { type: "LIMITED_DROP", label: "Winter batch", data: {
      title: "The winter batch", lead: "Each piece here is produced once, in a fixed quantity. When a batch is fully reserved, it closes.",
      body: "Places are reserved in the order payments are verified. You'll see the remaining places, closing date and estimated dispatch window on every product page.",
      ctaLabel: "Read the pre-order guide", ctaHref: "/pre-order-guide",
      productIds: ["structured-mini-tote", "crescent-hobo-bag", "evening-box-clutch", "everyday-midi-dress", "evening-wrap-dress", "linen-day-dress"].map(P),
      footnote: "New batches are announced to the newsletter first." } },
    { type: "ENQUIRY_MARQUEE", label: "Styling enquiry", data: {
      title: "Ask before you order", body: "Not sure about a size, a colour or how two pieces go together? Send us a message with what you're looking for and we'll reply with measurements, extra photos or a suggestion.",
      ctaLabel: "Send an enquiry", ctaHref: "/contact",
      images: ["everyday-shoulder-bag:Black", "evening-wrap-dress:Wine", "minimal-chain-necklace:Gold", "tiered-cotton-maxi:White", "weekend-crossbody:Olive", "pleated-slip-dress:Midnight", "everyday-hoop-earrings:Silver"].map((s) => { const [p, c] = s.split(":"); return { image: img(p, c), alt: "" }; }) } },
    { type: "BRAND_STORY", label: "About", data: {
      title: "About Veloura", lead: "Bags, accessories and dresses, made in small batches for pre-order.",
      body: "Producing to order means we make what has been reserved rather than guessing quantities. It keeps prices fair and leaves less unsold stock. A few pieces are also kept in stock and ship within two working days.",
      image: "/demo/scene-bags.jpg", ctaLabel: "Our approach", ctaHref: "/about" } },
    { type: "GIFTING", label: "How pre-order works", data: {
      title: "How pre-order works", body: "Choose your piece, pay the deposit or the full amount by bKash, Nagad or bank transfer, and we confirm your place once the payment is verified. We'll message you when your batch arrives and when the balance is due.",
      ctaLabel: "Read the pre-order guide", ctaHref: "/pre-order-guide", image: "/demo/scene-gifting.jpg" } },
    { type: "FOOTER_GALLERY", label: "Image strip", data: { images: ["/demo/scene-dresses.jpg", img("everyday-hoop-earrings", "Gold"), "/demo/scene-accessories.jpg", img("woven-bucket-bag", "Natural"), "/demo/scene-bags.jpg", img("silk-feel-printed-scarf", "Terracotta")].map((image) => ({ image, alt: "" })) } },
    { type: "NEWSLETTER", label: "Drop sign-up", data: { title: "Be the first to know when the next batch opens.", buttonLabel: "Get notified" } },
  ];
  for (const [i, s] of sections.entries()) {
    await db.homepageSection.create({ data: { type: s.type, label: s.label, sortOrder: i, draftData: s.data, publishedData: s.data } });
  }
  const live = await db.homepageSection.findMany({ orderBy: { sortOrder: "asc" } });
  await db.homepageRevision.create({ data: { note: "Initial seed", snapshot: live.map((r) => ({ id: r.id, type: r.type, label: r.label, sortOrder: r.sortOrder, visible: r.visible, publishAt: null, unpublishAt: null, data: r.publishedData })) as Prisma.InputJsonValue } });

  // ───────── pages ─────────
  const pages = [
    { slug: "about", title: "About Veloura", intro: "Bags, accessories and dresses made in small pre-order batches.", body: "## How we work\n\nMost pieces are produced to order. A batch opens for a fixed number of places, closes on a set date, and goes into production once it closes. That way we make what has been reserved.\n\n## Ready to ship\n\nSome pieces are kept in stock. They're marked Ready to ship and leave the studio within two working days.\n\n## Talk to us\n\nQuestions about sizing, colours or an order? [Send us a message](/contact)." },
    { slug: "pre-order-guide", title: "Pre-order guide", intro: "What happens between reserving a piece and receiving it.", body: "## 1. Reserve\n\nEach pre-order product belongs to a batch with a fixed number of places. Product pages show how many places remain, when the batch closes and the estimated dispatch window.\n\n## 2. Pay the deposit or in full\n\nDepending on the batch you can pay a deposit now and the balance later, or pay in full. Pay by bKash, Nagad or bank transfer and submit your transaction ID on the order page.\n\n## 3. We verify your payment\n\nYour place is held for 24 hours after ordering. Once our team verifies the payment, your place is confirmed. If no payment is submitted in that time, the place is released.\n\n## 4. Production and arrival\n\nWe'll update your order as it moves through sourcing or production and arrives at our studio. Dispatch dates are estimates and can move; we'll message you if your batch is delayed.\n\n## 5. Balance and dispatch\n\nIf you paid a deposit, the balance is due before dispatch. Your order page shows the due date and amount.\n\n## Mixed bags\n\nIf your bag has ready-to-ship and pre-order items, you choose at checkout whether to ship everything together when the pre-order arrives, or in two parcels for an extra delivery fee.\n\n## Cancelling\n\nYou can cancel for a full refund until the batch closes. After it closes, deposits are refundable only if we can't fulfil your order or the dispatch window slips by more than 21 days." },
    { slug: "shipping-and-returns", title: "Shipping & returns", intro: "Delivery across Bangladesh.", body: "## Delivery fees\n\nFees depend on your district and are shown at checkout before you pay.\n\n## Dispatch\n\nReady-to-ship items leave within two working days of payment verification or order confirmation. Pre-order items are dispatched in their batch's estimated window.\n\n## Returns\n\nContact us within 3 days of delivery if an item arrives damaged or isn't what you ordered. Items must be unused with tags attached. Earrings can't be returned for hygiene reasons unless faulty.\n\n## Refunds\n\nApproved refunds are sent to the original bKash, Nagad or bank account." },
    { slug: "privacy-policy", title: "Privacy policy", intro: "How we handle your information.", body: "## What we collect\n\nYour name, phone number, email address and delivery address when you order, and your email if you subscribe to the newsletter.\n\n## How we use it\n\nTo process and deliver your orders, contact you about them, and send newsletters if you subscribed.\n\n## Sharing\n\nWe share delivery details with our courier partners only to deliver your order. We don't sell your data.\n\n## Your choices\n\nYou can unsubscribe at any time or ask us to delete your account by [contacting us](/contact).\n\n*Replace this template with a policy reviewed for your business before launch.*" },
    { slug: "terms", title: "Terms of service", intro: "The terms that apply when you shop with us.", body: "## Orders\n\nAn order is confirmed when we verify your payment, or for cash on delivery when we confirm it by phone.\n\n## Pre-orders\n\nEstimated dispatch windows are estimates, not guarantees. Pre-order terms shown at checkout form part of your order.\n\n## Prices\n\nPrices are in Bangladeshi Taka and include applicable taxes. Delivery fees are shown at checkout.\n\n*Replace this template with terms reviewed for your business before launch.*" },
  ];
  for (const p of pages) await db.page.create({ data: { ...p, system: true, seoTitle: `${p.title} | Veloura`, seoDesc: p.intro } });

  const faqs = [
    ["Pre-order", "What does pre-order mean?", "The piece is produced or sourced after its batch closes. You reserve a place now and we dispatch in the estimated window shown on the product page."],
    ["Pre-order", "When do I pay the balance?", "If you paid a deposit, the balance is due a few days before the batch's dispatch window. Your order page shows the exact amount and due date."],
    ["Pre-order", "What if my batch is delayed?", "We'll message you with a new estimate. If the dispatch window slips by more than 21 days you can cancel for a full refund."],
    ["Payment", "How do I pay?", "By bKash, Nagad or bank transfer. After ordering, send the amount shown and submit the transaction ID on your order page. Ready-to-ship orders may also be paid on delivery."],
    ["Payment", "Why is my payment 'awaiting verification'?", "Our team checks every manual transfer against the transaction ID. This usually happens within a few hours during working days."],
    ["Delivery", "How long does delivery take?", "Inside Dhaka usually 1–2 days after dispatch, outside Dhaka 2–4 days."],
    ["Delivery", "Can I track my order?", "Yes. Use the link in your order confirmation or the Track order page with your order number and phone number."],
  ];
  for (const [i, [group, question, answer]] of faqs.entries()) await db.faqItem.create({ data: { group, question, answer, sortOrder: i } });

  const menus: [Prisma.MenuItemCreateManyInput["location"], string, string][] = [
    ["HEADER", "Shop", "/shop"], ["HEADER", "Bags", "/collections/bags"], ["HEADER", "Dresses", "/collections/dresses"], ["HEADER", "Accessories", "/collections/accessories"], ["HEADER", "Pre-order", "/collections/winter-pre-order"], ["HEADER", "Journal", "/journal"], ["HEADER", "About", "/about"],
    ["FOOTER_SHOP", "Bags", "/collections/bags"], ["FOOTER_SHOP", "Dresses", "/collections/dresses"], ["FOOTER_SHOP", "Accessories", "/collections/accessories"], ["FOOTER_SHOP", "Pre-order", "/collections/winter-pre-order"], ["FOOTER_SHOP", "Ready to ship", "/collections/ready-to-ship"],
    ["FOOTER_INFO", "About", "/about"], ["FOOTER_INFO", "Journal", "/journal"], ["FOOTER_INFO", "Pre-order guide", "/pre-order-guide"], ["FOOTER_INFO", "FAQ", "/faq"],
    ["FOOTER_CONTACT", "Contact", "/contact"], ["FOOTER_CONTACT", "Track order", "/track"], ["FOOTER_CONTACT", "Shipping & returns", "/shipping-and-returns"], ["FOOTER_CONTACT", "Privacy", "/privacy-policy"], ["FOOTER_CONTACT", "Terms", "/terms"],
  ];
  await db.menuItem.createMany({ data: menus.map(([location, label, href], i) => ({ location, label, href, sortOrder: i })) });

  await db.editorialPost.create({ data: {
    slug: "one-bag-three-ways", title: "One bag, three ways", status: "PUBLISHED", publishedAt: day(-6), coverUrl: "/demo/scene-bags.jpg",
    excerpt: "The Structured Mini Tote by hand, on the shoulder and across the body.",
    body: "## By hand\n\nThe twin handles keep the tote upright. Pair it with the Relaxed Shirt Dress for a working day.\n\n## On the shoulder\n\nClip the strap to its shortest length.\n\n## Across the body\n\nLet the strap out fully for errands and travel.",
    gallery: [img("structured-mini-tote", "Sand"), img("structured-mini-tote", "Espresso"), img("structured-mini-tote", "Sand", 2)],
    productIds: [P("structured-mini-tote"), P("relaxed-shirt-dress")] } });
  await db.editorialPost.create({ data: {
    slug: "dressing-for-evening", title: "Dressing for evening", status: "PUBLISHED", publishedAt: day(-2), coverUrl: "/demo/scene-dresses.jpg",
    excerpt: "Satin, a box clutch and one pair of earrings.",
    body: "## Start with the dress\n\nThe Evening Wrap Dress adjusts to your fit.\n\n## Keep accessories quiet\n\nA box clutch and pearl drops are enough.",
    gallery: [img("evening-wrap-dress", "Emerald"), img("evening-box-clutch", "Black"), img("pearl-drop-earrings", "Gold")],
    productIds: [P("evening-wrap-dress"), P("evening-box-clutch"), P("pearl-drop-earrings")] } });

  // Register the demo art in the media library so it can be picked in the admin.
  const { readdirSync, statSync } = await import("fs");
  await db.media.deleteMany({ where: { folder: "demo" } });
  const { fileURLToPath } = await import("url");
  const demoDir = fileURLToPath(new URL("../public/demo/", import.meta.url));
  for (const f of readdirSync(demoDir).filter((x) => x.endsWith(".jpg"))) {
    await db.media.create({ data: { url: `/demo/${f}`, storageKey: `demo/${f}`, filename: f, mime: "image/jpeg", size: statSync(demoDir + f).size, width: f.startsWith("scene-") ? null : 1000, height: f.startsWith("scene-") ? null : 1193, folder: "demo", alt: "" } });
  }

  await db.setting.upsert({ where: { key: "store" }, create: { key: "store", value: {} }, update: {} });

  // ───────── demo orders, clearly prefixed DEMO- so dashboards can label them ─────────
  if (process.env.SEED_DEMO_ORDERS !== "false") {
    const names = ["Nusrat J.", "Tasnim A.", "Farhana R.", "Sadia K.", "Mithila H.", "Raisa M.", "Anika T.", "Lamia S.", "Jannat F.", "Sumaiya B."];
    const slugsAll = Object.keys(products).filter((s) => !["linen-day-dress", "leaf-charm-bracelet"].includes(s));
    let seed = 7; const rnd = () => (seed = (seed * 9301 + 49297) % 233280) / 233280;
    for (let i = 0; i < 28; i++) {
      const created = day(-Math.floor(rnd() * 55) - 1);
      const lines = Array.from({ length: 1 + Math.floor(rnd() * 2) }, () => {
        const p = products[slugsAll[Math.floor(rnd() * slugsAll.length)]]; const v = p.variants[Math.floor(rnd() * p.variants.length)];
        return { p, v, qty: 1 };
      });
      const subtotal = lines.reduce((s, l) => s + l.v.price * l.qty, 0);
      const shippingFee = 80; const total = subtotal + shippingFee;
      const hasPre = lines.some((l) => l.v.mode === "PRE_ORDER");
      const plan = hasPre ? (rnd() < 0.6 ? "DEPOSIT" : "FULL") : rnd() < 0.5 ? "COD" : "FULL";
      const dueNow = plan === "COD" ? 0 : plan === "FULL" ? total : Math.round(subtotal * 0.3) + shippingFee;
      const r = rnd();
      const cancelled = r < 0.1;
      const fulfillment = cancelled ? "CANCELLED" : r < 0.3 ? "PENDING_CONFIRMATION" : r < 0.5 ? "CONFIRMED" : r < 0.65 ? "SOURCING" : r < 0.8 ? "SHIPPED" : "DELIVERED";
      const paidSteps: { kind: "DEPOSIT" | "FULL" | "BALANCE" | "COD_COLLECTION"; amount: number }[] = [];
      if (!cancelled && fulfillment !== "PENDING_CONFIRMATION") {
        if (plan === "FULL") paidSteps.push({ kind: "FULL", amount: total });
        if (plan === "DEPOSIT") { paidSteps.push({ kind: "DEPOSIT", amount: dueNow }); if (["SHIPPED", "DELIVERED"].includes(fulfillment)) paidSteps.push({ kind: "BALANCE", amount: total - dueNow }); }
        if (plan === "COD" && fulfillment === "DELIVERED") paidSteps.push({ kind: "COD_COLLECTION", amount: total });
      }
      const amountPaid = paidSteps.reduce((s, x) => s + x.amount, 0);
      const paymentStatus = amountPaid >= total ? "PAID" : amountPaid > 0 ? "PARTIALLY_PAID" : "UNPAID";
      const n = names[i % names.length];
      await db.order.create({ data: {
        number: `DEMO-${String(1001 + i)}`, trackingToken: randomBytes(18).toString("base64url"), customerName: n, phone: `0170000${String(1000 + i).slice(-4)}`, email: `demo${i}@example.invalid`,
        address: "House 1, Road 1", district: "Dhaka", area: "Dhanmondi", shippingZoneName: "Inside Dhaka",
        subtotal, shippingFee, total, dueNow, paymentPlan: plan, paymentMethod: plan === "COD" ? "COD" : rnd() < 0.6 ? "BKASH" : "NAGAD",
        paymentStatus, amountPaid, fulfillmentStatus: fulfillment as never, hasPreorder: hasPre, termsAcceptedAt: hasPre ? created : null,
        createdAt: created, cancelledAt: cancelled ? created : null, cancelReason: cancelled ? "Demo: customer changed their mind" : null,
        items: { create: lines.map((l) => ({ productId: l.p.id, variantId: l.v.id, categorySlug: l.p.category, productName: l.p.name, variantLabel: l.v.label, sku: l.v.sku, imageUrl: l.p.image, unitPrice: l.v.price, qty: l.qty, lineTotal: l.v.price * l.qty, mode: l.v.mode, batchId: l.v.batchId, depositPerUnit: plan === "DEPOSIT" && l.v.mode === "PRE_ORDER" ? Math.round(l.v.price * 0.3) : 0, capacityState: cancelled ? "RELEASED" : paidSteps.length || plan === "COD" ? "COMMITTED" : "HELD" })) },
        payments: { create: paidSteps.map((s, k) => ({ kind: s.kind, method: plan === "COD" ? "COD" : "BKASH", amount: s.amount, status: "VERIFIED", reference: `DEMO${i}${k}`, verifiedAt: new Date(created.getTime() + (k + 1) * 86400000), createdAt: created })) },
        events: { create: [{ type: "SYSTEM", message: "Demo order created by the seed script.", createdAt: created }] },
      } });
      for (const l of lines) if (l.v.mode === "PRE_ORDER" && l.v.batchId && !cancelled) {
        const committed = paidSteps.length > 0 || plan === "COD";
        await db.preorderBatch.update({ where: { id: l.v.batchId }, data: committed ? { committedQty: { increment: l.qty } } : { heldQty: { increment: l.qty } } });
      }
    }
  }

  console.log(`Seeded ${catalog.products.length} products, ${sections.length} homepage sections, ${pages.length} pages.`);
}

main().then(() => db.$disconnect()).catch(async (e) => { console.error(e); await db.$disconnect(); process.exit(1); });
