import { NextResponse } from "next/server";
import { createHash } from "node:crypto";
import { revalidatePath } from "next/cache";
import { and, eq, isNull } from "drizzle-orm";
import { db } from "@/db";
import { menuItemSbisLinks, menuItems, sbisCatalogItems } from "@/db/schema";
import { adminAuthorized } from "@/lib/admin-auth";
import { recordAudit } from "@/lib/audit";

const PULL_FIELDS = ["name", "description", "imageUrl"] as const;
type PullField = (typeof PULL_FIELDS)[number];

function fail(error: string, status = 400) { return NextResponse.json({ error }, { status }); }

/** Manual pull of editorial fields from the last validated SBIS snapshot (§6.3). */
export async function POST(request: Request) {
  if (!(await adminAuthorized(request, true))) return fail("Unauthorized", 401);
  if (!db) return fail("Database is not configured", 503);
  const body = await request.json() as { menuItemId?: unknown; fields?: unknown };
  const menuItemId = Number(body.menuItemId);
  const fields = Array.isArray(body.fields) ? [...new Set(body.fields.filter((field): field is PullField => PULL_FIELDS.includes(field as PullField)))] : [];
  if (!Number.isInteger(menuItemId) || !fields.length) return fail("Укажите карточку и хотя бы одно поле (name, description, imageUrl)");
  try {
    const [row] = await db.select({ link: menuItemSbisLinks, sbis: sbisCatalogItems })
      .from(menuItemSbisLinks)
      .innerJoin(sbisCatalogItems, eq(sbisCatalogItems.sbisId, menuItemSbisLinks.sbisId))
      .where(and(eq(menuItemSbisLinks.menuItemId, menuItemId), isNull(menuItemSbisLinks.unlinkedAt)))
      .limit(1);
    if (!row) return fail("У карточки нет активной связи СБИС", 409);
    if (!row.sbis.inCurrentPrice) return fail("Позиция отсутствует в актуальном прайсе СБИС", 409);
    const pulledAt = new Date();
    const patch: Partial<typeof menuItems.$inferInsert> = { updatedAt: pulledAt };
    for (const field of fields) {
      if (field === "name") patch.name = row.sbis.name;
      else if (field === "description") patch.description = row.sbis.description ?? null;
      else patch.imageUrl = row.sbis.imageUrl ?? null;
    }
    const sbisFieldsHash = createHash("sha256").update(JSON.stringify({ name: row.sbis.name, description: row.sbis.description ?? null, imageUrl: row.sbis.imageUrl ?? null })).digest("hex");
    await db.transaction(async (tx) => {
      await tx.update(menuItems).set(patch).where(eq(menuItems.id, menuItemId));
      await tx.update(menuItemSbisLinks).set({ lastPullAt: pulledAt, lastResult: `pull:${fields.join(",")}`, sbisFieldsHash }).where(eq(menuItemSbisLinks.id, row.link.id));
    });
    await recordAudit("sbis_pull", { entityType: "menu_item", entityId: menuItemId, details: { sbis_id: row.sbis.sbisId, fields } });
    revalidatePath("/menu");
    return NextResponse.json({ ok: true, fields });
  } catch (error) {
    return fail(error instanceof Error ? error.message : "Не удалось выполнить pull из СБИС", 503);
  }
}
