/**
 * داده نمونه دیتابیس: ۸ برند فرضی، ۱۳ دسته، ۳۰ محصول با تنوع‌ها و نظرات،
 * روش‌های ارسال، کدهای تخفیف، بنرها، تنظیمات و یک کاربر نمونه با ۳ سفارش.
 * اجرا: npm run db:seed (داده‌های قبلی کاتالوگ و سفارش‌ها پاک و دوباره ساخته می‌شوند)
 */
import "dotenv/config";
import { PrismaPg } from "@prisma/adapter-pg";
import { PrismaClient } from "../src/generated/prisma/client";
import { brands, categories, skinTypes } from "../src/data/taxonomy";
import { products, reviews } from "../src/data/products";
import { banners, shippingSettings } from "../src/data/content";
import { sampleOrders } from "../src/data/orders";
import { randomBytes, scrypt as scryptCb } from "node:crypto";

import { buildSearchText } from "../src/lib/search-text";

/** همان قالب رمز src/server/auth/password.ts */
function hashPassword(pw: string) {
  const salt = randomBytes(16);
  return new Promise<string>((res, rej) =>
    scryptCb(pw.normalize("NFKC"), salt, 64, { N: 16384, r: 8, p: 1, maxmem: 64 * 1024 * 1024 }, (err, key) =>
      err ? rej(err) : res(["scrypt", 16384, 8, 1, salt.toString("base64url"), key.toString("base64url")].join("$")),
    ),
  );
}


const db = new PrismaClient({ adapter: new PrismaPg({ connectionString: process.env.DATABASE_URL! }) });

async function main() {
  // پاک‌سازی به ترتیب وابستگی
  await db.$transaction([
    db.payment.deleteMany(),
    db.orderStatusHistory.deleteMany(),
    db.orderItem.deleteMany(),
    db.order.deleteMany(),
    db.cartItem.deleteMany(),
    db.cart.deleteMany(),
    db.wishlistItem.deleteMany(),
    db.review.deleteMany(),
    db.productImage.deleteMany(),
    db.productVariant.deleteMany(),
    db.product.deleteMany(),
    db.category.updateMany({ data: { parentId: null } }),
    db.category.deleteMany(),
    db.brand.deleteMany(),
    db.skinType.deleteMany(),
    db.shippingMethod.deleteMany(),
    db.discountCode.deleteMany(),
    db.banner.deleteMany(),
  ]);

  await db.brand.createMany({ data: brands });
  await db.skinType.createMany({ data: skinTypes });
  // اول دسته‌های والد، بعد فرزندان
  await db.category.createMany({ data: categories.filter((c) => !c.parentId).map((c, i) => ({ ...c, sortOrder: i })) });
  await db.category.createMany({ data: categories.filter((c) => c.parentId).map((c, i) => ({ ...c, parentId: c.parentId!, sortOrder: i })) });

  const brandById = new Map(brands.map((b) => [b.id, b]));
  const catById = new Map(categories.map((c) => [c.id, c]));

  for (const p of products) {
    const cat = catById.get(p.categoryId)!;
    const parent = cat.parentId ? catById.get(cat.parentId) : undefined;
    await db.product.create({
      data: {
        id: p.id,
        slug: p.slug,
        name: p.name,
        brandId: p.brandId,
        categoryId: p.categoryId,
        skinTypes: { connect: p.skinTypeIds.map((id) => ({ id })) },
        summary: p.summary,
        description: p.description,
        howToUse: p.howToUse,
        ingredients: p.ingredients,
        ircCode: p.ircCode,
        madeIn: p.madeIn,
        shape: p.shape,
        tone: p.tone,
        tags: p.tags,
        minPrice: Math.min(...p.variants.map((v) => v.price)),
        ratingAvg: p.rating,
        reviewCount: p.reviewCount,
        soldCount: p.soldCount,
        searchText: buildSearchText({ name: p.name, summary: p.summary, brand: brandById.get(p.brandId)!, categories: [cat.name, parent?.name ?? ""] }),
        createdAt: new Date(p.createdAt),
        variants: { create: p.variants.map((v, i) => ({ ...v, sortOrder: i })) },
      },
    });
  }
  // شمارنده شناسه محصول را بعد از درج دستی شناسه‌ها تنظیم می‌کنیم
  await db.$executeRawUnsafe(`SELECT setval(pg_get_serial_sequence('"Product"', 'id'), (SELECT MAX(id) FROM "Product"))`);

  await db.review.createMany({
    data: reviews.map((r) => ({
      productId: r.productId,
      authorName: r.author,
      rating: r.rating,
      title: r.title,
      body: r.body,
      skinTypeId: r.skinTypeId,
      verifiedPurchase: r.verifiedPurchase,
      status: "APPROVED" as const,
      createdAt: new Date(r.createdAt),
    })),
  });

  await db.shippingMethod.createMany({ data: shippingSettings.methods.map((m, i) => ({ ...m, tehranOnly: !!m.tehranOnly, sortOrder: i })) });
  await db.setting.upsert({
    where: { key: "freeShippingThreshold" },
    create: { key: "freeShippingThreshold", value: shippingSettings.freeShippingThreshold },
    update: { value: shippingSettings.freeShippingThreshold },
  });
  await db.discountCode.createMany({
    data: [
      { code: "ZAHORA10", label: "۱۰٪ تخفیف (حداکثر ۳۰۰ هزار تومان)", type: "PERCENT", value: 10, minSubtotal: 500_000, maxAmount: 300_000 },
      { code: "WELCOME", label: "۱۵۰ هزار تومان تخفیف خرید اول", type: "FIXED", value: 150_000, minSubtotal: 1_000_000 },
    ],
  });
  await db.banner.createMany({ data: banners.map(({ id: _id, ...b }, i) => ({ ...b, sortOrder: i })) });

  // کاربر و سفارش‌های نمونه (برای صفحه پیگیری و پروفایل)
  // کاربر نمونه = مدیر عامل محیط توسعه؛ رمز ورود پنل از SEED_OWNER_PASSWORD در .env (در کد هیچ رمزی نیست)
  const ownerPassword = process.env.SEED_OWNER_PASSWORD;
  const ownerAuth = ownerPassword ? { passwordHash: await hashPassword(ownerPassword) } : {};
  const user = await db.user.upsert({
    where: { phone: "09120000000" },
    create: { phone: "09120000000", name: "کاربر نمونه", role: "OWNER", ...ownerAuth },
    update: { role: "OWNER", ...ownerAuth },
  });
  // ↑ فقط برای تست محلی: کاربر نمونه مدیر است. در production با npm run admin:grant مدیر تعیین کنید.
  const variants = new Map(products.flatMap((p) => p.variants.map((v) => [v.id, { p, v }] as const)));
  const statusMap = { pending_payment: "PENDING_PAYMENT", paid: "PAID", processing: "PROCESSING", shipped: "SHIPPED", delivered: "DELIVERED", canceled: "CANCELED" } as const;
  const methodByName = new Map(shippingSettings.methods.map((m) => [m.name, m.id]));
  for (const o of sampleOrders) {
    const subtotal = o.items.reduce((s, i) => s + i.price * i.qty, 0);
    await db.order.create({
      data: {
        code: o.code,
        userId: user.id,
        status: statusMap[o.status],
        receiver: "کاربر نمونه",
        phone: o.phone,
        province: "تهران",
        city: "تهران",
        addressLine: "خیابان نمونه، پلاک ۱",
        postalCode: "1234567890",
        shippingMethodId: methodByName.get(o.shippingMethod)!,
        shippingCost: o.shippingCost,
        subtotal,
        discount: o.discount,
        total: subtotal - o.discount + o.shippingCost,
        trackingCode: o.trackingCode,
        createdAt: new Date(o.createdAt),
        items: {
          create: o.items.map((i) => {
            const { p, v } = variants.get(i.variantId)!;
            return { variantId: v.id, productName: p.name, variantLabel: [v.colorName, v.size].filter(Boolean).join(" · "), price: i.price, qty: i.qty };
          }),
        },
        history: { create: o.history.map((h) => ({ status: statusMap[h.status], createdAt: new Date(h.at) })) },
      },
    });
  }

  const counts = await Promise.all([db.product.count(), db.productVariant.count(), db.review.count(), db.order.count()]);
  console.log(`✓ seed: ${counts[0]} محصول، ${counts[1]} تنوع، ${counts[2]} نظر، ${counts[3]} سفارش`);
}

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