import { Router } from "express";
import { db } from "@workspace/db";
import {
  supplyOrdersTable,
  supplyOrderItemsTable,
  suppliersTable,
  factoriesTable,
  productsTable,
} from "@workspace/db";
import { eq, sql } from "drizzle-orm";

const router = Router();

async function formatOrder(o: typeof supplyOrdersTable.$inferSelect) {
  const [supplier] = await db.select().from(suppliersTable).where(eq(suppliersTable.id, o.supplierId));
  const [factory] = await db.select().from(factoriesTable).where(eq(factoriesTable.id, o.factoryId));
  const items = await db.select().from(supplyOrderItemsTable).where(eq(supplyOrderItemsTable.orderId, o.id));
  const formattedItems = await Promise.all(
    items.map(async (item) => {
      const [product] = await db.select().from(productsTable).where(eq(productsTable.id, item.productId));
      return {
        id: item.id,
        productId: item.productId,
        productName: product?.name ?? "",
        unit: product?.unit ?? "",
        quantity: Number(item.quantity),
        unitPrice: Number(item.unitPrice),
        total: Number(item.total),
      };
    })
  );
  return {
    id: o.id,
    supplierId: o.supplierId,
    supplierName: supplier?.name ?? "",
    factoryId: o.factoryId,
    factoryName: factory?.name ?? "",
    date: o.date,
    documentNo: o.documentNo,
    totalAmount: Number(o.totalAmount),
    notes: o.notes ?? null,
    items: formattedItems,
    createdAt: o.createdAt.toISOString(),
  };
}

router.get("/", async (req, res) => {
  const { supplierId, factoryId, from, to } = req.query as Record<string, string>;
  let rows = await db.select().from(supplyOrdersTable).orderBy(sql`${supplyOrdersTable.date} desc, ${supplyOrdersTable.id} desc`);
  if (supplierId) rows = rows.filter((r) => r.supplierId === parseInt(supplierId));
  if (factoryId) rows = rows.filter((r) => r.factoryId === parseInt(factoryId));
  if (from) rows = rows.filter((r) => r.date >= from);
  if (to) rows = rows.filter((r) => r.date <= to);
  const result = await Promise.all(rows.map(formatOrder));
  res.json(result);
});

router.post("/", async (req, res) => {
  const { supplierId, factoryId, date, documentNo, notes, items } = req.body;
  if (!supplierId || !factoryId || !date || !documentNo || !items?.length) {
    return res.status(400).json({ error: "Missing required fields" });
  }
  const totalAmount = items.reduce((sum: number, item: { quantity: number; unitPrice: number }) => {
    return sum + item.quantity * item.unitPrice;
  }, 0);
  const [order] = await db
    .insert(supplyOrdersTable)
    .values({
      supplierId: parseInt(supplierId),
      factoryId: parseInt(factoryId),
      date,
      documentNo,
      totalAmount: String(totalAmount),
      notes,
    })
    .returning();
  // Insert items
  for (const item of items) {
    const total = item.quantity * item.unitPrice;
    await db.insert(supplyOrderItemsTable).values({
      orderId: order.id,
      productId: parseInt(item.productId),
      quantity: String(item.quantity),
      unitPrice: String(item.unitPrice),
      total: String(total),
    });
  }
  res.status(201).json(await formatOrder(order));
});

router.get("/:id", async (req, res) => {
  const id = parseInt(req.params.id);
  const [o] = await db.select().from(supplyOrdersTable).where(eq(supplyOrdersTable.id, id));
  if (!o) return res.status(404).json({ error: "Not found" });
  res.json(await formatOrder(o));
});

router.delete("/:id", async (req, res) => {
  const id = parseInt(req.params.id);
  await db.delete(supplyOrderItemsTable).where(eq(supplyOrderItemsTable.orderId, id));
  await db.delete(supplyOrdersTable).where(eq(supplyOrdersTable.id, id));
  res.status(204).end();
});

export default router;
