import { Router, Request, Response, NextFunction } from "express";
import { z } from "zod";
import { prisma } from "../lib/prisma.js";
import { requireAuth, requireRole } from "../middleware/auth.js";
import { AppError } from "../middleware/errorHandler.js";
import { parsePage, paginatedResponse } from "../lib/pagination.js";
import { AuthenticatedRequest } from "../types/index.js";

const router = Router();
const auth = requireAuth as unknown as (r: Request, s: Response, n: NextFunction) => void;
const managerUp = requireRole("owner", "manager") as unknown as (r: Request, s: Response, n: NextFunction) => void;

const CategorySchema = z.object({
  name: z.string().min(1).max(100),
});

router.get("/", auth, async (req: Request, res: Response, next: NextFunction) => {
  try {
    const authReq = req as AuthenticatedRequest;
    const { page, limit, skip } = parsePage(req.query as Record<string, unknown>);
    const where = { vendorId: authReq.auth.vendorId };

    const [data, total] = await Promise.all([
      prisma.category.findMany({ where, skip, take: limit, orderBy: { name: "asc" } }),
      prisma.category.count({ where }),
    ]);

    res.json(paginatedResponse(data, total, { page, limit, skip }));
  } catch (err) {
    next(err);
  }
});

router.get("/:id", auth, async (req: Request, res: Response, next: NextFunction) => {
  try {
    const authReq = req as AuthenticatedRequest;
    const cat = await prisma.category.findFirst({
      where: { id: req.params.id, vendorId: authReq.auth.vendorId },
    });
    if (!cat) throw new AppError(404, "NOT_FOUND", "Category not found");
    res.json(cat);
  } catch (err) {
    next(err);
  }
});

router.post("/", auth, managerUp, async (req: Request, res: Response, next: NextFunction) => {
  try {
    const authReq = req as AuthenticatedRequest;
    const body = CategorySchema.parse(req.body);
    const cat = await prisma.category.create({
      data: { ...body, vendorId: authReq.auth.vendorId },
    });
    res.status(201).json(cat);
  } catch (err) {
    next(err);
  }
});

router.put("/:id", auth, managerUp, async (req: Request, res: Response, next: NextFunction) => {
  try {
    const authReq = req as AuthenticatedRequest;
    const existing = await prisma.category.findFirst({
      where: { id: req.params.id, vendorId: authReq.auth.vendorId },
    });
    if (!existing) throw new AppError(404, "NOT_FOUND", "Category not found");

    const body = CategorySchema.parse(req.body);
    const cat = await prisma.category.update({ where: { id: req.params.id }, data: body });
    res.json(cat);
  } catch (err) {
    next(err);
  }
});

router.delete("/:id", auth, managerUp, async (req: Request, res: Response, next: NextFunction) => {
  try {
    const authReq = req as AuthenticatedRequest;
    const existing = await prisma.category.findFirst({
      where: { id: req.params.id, vendorId: authReq.auth.vendorId },
    });
    if (!existing) throw new AppError(404, "NOT_FOUND", "Category not found");
    await prisma.category.delete({ where: { id: req.params.id } });
    res.status(204).send();
  } catch (err) {
    next(err);
  }
});

export default router;
