import { Router, Response } from 'express';
import { authenticate, AuthRequest } from '../middleware/auth';
import { requireRole } from '../middleware/requireRole';
import { validate } from '../middleware/validate';
import { CreateInventoryItemSchema, UpdateInventoryItemSchema } from '@nobel/shared';
import { qstr, qstrDef } from '../lib/query';
import prisma from '../lib/prisma';

const router = Router();
router.use(authenticate);

router.get('/', async (req: AuthRequest, res: Response) => {
  const search = qstr(req, 'search');
  const filter = qstr(req, 'filter');
  const cursor = qstr(req, 'cursor');
  const take = Math.min(parseInt(qstrDef(req, 'limit', '100')) || 100, 200);

  const where = {
    deletedAt: null as null,
    ...(search ? {
      OR: [
        { name: { contains: search, mode: 'insensitive' as const } },
        { sku: { contains: search, mode: 'insensitive' as const } },
        { category: { contains: search, mode: 'insensitive' as const } },
      ],
    } : {}),
  };

  // Inventory tables are small: load all matching rows once so stats and
  // low/out filtering (a column-to-column comparison Prisma can't express)
  // are computed over the full set, then paginate in memory.
  const allItems = await prisma.inventoryItem.findMany({
    where,
    orderBy: { name: 'asc' },
  });

  const stats = {
    total: allItems.length,
    low: allItems.filter((i) => i.stock > 0 && i.stock <= i.reorderLevel).length,
    out: allItems.filter((i) => i.stock <= 0).length,
    value: allItems.reduce((s, i) => s + i.stock * i.cost, 0),
  };

  const filtered =
    filter === 'low'
      ? allItems.filter((i) => i.stock > 0 && i.stock <= i.reorderLevel)
      : filter === 'out'
        ? allItems.filter((i) => i.stock <= 0)
        : allItems;

  const startIdx = cursor ? filtered.findIndex((i) => i.id === cursor) + 1 : 0;
  const page = filtered.slice(startIdx, startIdx + take);
  const hasMore = startIdx + take < filtered.length;

  res.json({
    data: page,
    nextCursor: hasMore ? page[page.length - 1]?.id : null,
    total: filtered.length,
    stats,
  });
});

router.post('/', requireRole('admin'), validate(CreateInventoryItemSchema), async (req: AuthRequest, res: Response) => {
  const item = await prisma.inventoryItem.create({ data: req.body });
  res.status(201).json(item);
});

router.get('/:id', async (req: AuthRequest, res: Response) => {
  const item = await prisma.inventoryItem.findFirst({
    where: { id: req.params.id, deletedAt: null },
  });
  if (!item) { res.status(404).json({ error: 'Item not found' }); return; }
  res.json(item);
});

router.patch('/:id', requireRole('admin'), validate(UpdateInventoryItemSchema), async (req: AuthRequest, res: Response) => {
  const item = await prisma.inventoryItem.update({
    where: { id: req.params.id },
    data: req.body,
  });
  res.json(item);
});

router.delete('/:id', requireRole('admin'), async (req: AuthRequest, res: Response) => {
  await prisma.inventoryItem.update({
    where: { id: req.params.id },
    data: { deletedAt: new Date() },
  });
  res.json({ ok: true });
});

export default router;
