import { NextResponse } from "next/server";
import { eq, and, isNull } from "drizzle-orm";
import { db } from "@/db";
import { menuCategories, menuItemSbisLinks, menuItemVariants, menuItems, sbisCatalogItems } from "@/db/schema";
import { getBotCatalog } from "@/lib/bot-api";
import { adminAuthorized } from "@/lib/admin-auth";
import { recordAudit } from "@/lib/audit";

function fail(message: string, status = 400) { return NextResponse.json({ error: message }, { status }); }
function slugify(value: string) { return value.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}\-]+/gu, "-").replace(/^-+|-+$/g, "").slice(0, 70) || "category"; }
function categoryNumber(value: string) { let hash = 0; for (const char of value) hash = (hash * 31 + char.codePointAt(0)!) % 89999; return 90000 + hash; }
function flatten(catalog: Awaited<ReturnType<typeof getBotCatalog>>) { return catalog.categories.flatMap((category) => category.items.map((item) => ({ ...item, categoryId: String(category.id), categoryName: category.name }))); }

export async function GET(request: Request) {
  if (!(await adminAuthorized(request))) return fail("Unauthorized", 401); if (!db) return fail("Database is not configured", 503);
  try { const catalog = await getBotCatalog(); for (const item of flatten(catalog)) await db.insert(sbisCatalogItems).values({ sbisId: String(item.sbis_id), categoryId: item.categoryId, categoryName: item.categoryName, name: item.name, priceKopecks: Math.round(item.price * 100), stockLeft: item.stock_left ?? null, available: item.available !== false, unavailableText: item.unavailable_text ?? null, variantOf: item.variant_of }).onConflictDoUpdate({ target: sbisCatalogItems.sbisId, set: { categoryId: item.categoryId, categoryName: item.categoryName, name: item.name, priceKopecks: Math.round(item.price * 100), stockLeft: item.stock_left ?? null, available: item.available !== false, unavailableText: item.unavailable_text ?? null, variantOf: item.variant_of, updatedAt: new Date() } }); return NextResponse.json(catalog); }
  catch (error) { return fail(error instanceof Error ? error.message : "Каталог СБИС недоступен", 503); }
}

export async function POST(request: Request) {
  if (!(await adminAuthorized(request, true))) return fail("Unauthorized", 401); if (!db) return fail("Database is not configured", 503);
  try {
    const body = await request.json() as { sbisIds?: unknown[] }; const normalizeId = (id: unknown) => typeof id === "number" ? String(Math.trunc(id)) : typeof id === "string" ? id : null; const ids = new Set((body.sbisIds || []).map(normalizeId).filter((id): id is string => Boolean(id))); if (!ids.size) return fail("Выберите позиции каталога");
    // Bot ids are numeric (contract §3); the site stores them as text keys.
    const catalog = flatten(await getBotCatalog()).filter((item) => ids.has(String(item.sbis_id))).map((item) => ({ ...item, sbisId: String(item.sbis_id), available: item.available !== false }));
    for (const item of catalog) {
      const categorySlug = slugify(item.categoryName); let [category] = await db.select().from(menuCategories).where(eq(menuCategories.slug, categorySlug)).limit(1);
      if (!category) { [category] = await db.insert(menuCategories).values({ slug: categorySlug, name: item.categoryName, yandexCategoryId: categoryNumber(item.categoryId || item.categoryName) }).onConflictDoNothing().returning(); if (!category) [category] = await db.select().from(menuCategories).where(eq(menuCategories.slug, categorySlug)).limit(1); }
      if (!category) continue;
      const [existingLink] = await db.select({ itemId: menuItemSbisLinks.menuItemId }).from(menuItemSbisLinks).where(and(eq(menuItemSbisLinks.sbisId, item.sbisId), isNull(menuItemSbisLinks.unlinkedAt))).limit(1);
      if (existingLink) { await db.update(menuItems).set({ isAvailable: item.available, updatedAt: new Date() }).where(eq(menuItems.id, existingLink.itemId)); const [variant] = await db.select().from(menuItemVariants).where(eq(menuItemVariants.itemId, existingLink.itemId)).limit(1); if (variant) await db.update(menuItemVariants).set({ priceKopecks: Math.round(item.price * 100), isAvailable: item.available, updatedAt: new Date() }).where(eq(menuItemVariants.id, variant.id)); continue; }
      const slug = `${slugify(item.name)}-${item.sbisId.replace(/[^a-zA-Z0-9]+/g, "").slice(-12) || Date.now()}`;
      const [created] = await db.insert(menuItems).values({ slug, categoryId: category.id, name: item.name, source: "sbis", sourceExternalId: null, isAvailable: item.available, showOnWebsite: false, publishToYandex: false }).returning();
      await db.insert(menuItemVariants).values({ itemId: created.id, label: "1 порция", priceKopecks: Math.round(item.price * 100), yandexOfferId: `sbis-${item.sbisId}`, isAvailable: item.available });
      await db.insert(menuItemSbisLinks).values({ menuItemId: created.id, sbisId: item.sbisId, linkedBy: "admin-catalog-import" });
    }
    await recordAudit("sbis_catalog_import", { details: { requested: ids.size, imported: catalog.length } });
    return NextResponse.json({ ok: true, imported: catalog.length });
  } catch (error) { return fail(error instanceof Error ? error.message : "Не удалось импортировать позиции", 503); }
}
