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 ownerOnly = requireRole("owner") as unknown as (r: Request, s: Response, n: NextFunction) => void;

const VendorSchema = z.object({
  name: z.string().min(1).max(100),
  businessNum: z.string().max(50).optional(),
  taxSettings: z.record(z.unknown()).optional(),
});

// GET /api/v1/vendors — list (owner sees their own vendor)
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 [data, total] = await Promise.all([
      prisma.vendor.findMany({
        where: { id: authReq.auth.vendorId },
        skip,
        take: limit,
        orderBy: { createdAt: "desc" },
      }),
      prisma.vendor.count({ where: { id: authReq.auth.vendorId } }),
    ]);

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

// GET /api/v1/vendors/:id
router.get("/:id", auth, async (req: Request, res: Response, next: NextFunction) => {
  try {
    const authReq = req as AuthenticatedRequest;
    const vendor = await prisma.vendor.findFirst({
      where: { id: req.params.id, ...(authReq.auth.roleName !== "owner" ? { id: authReq.auth.vendorId } : {}) },
    });
    if (!vendor) throw new AppError(404, "NOT_FOUND", "Vendor not found");
    res.json(vendor);
  } catch (err) {
    next(err);
  }
});

// POST /api/v1/vendors
router.post("/", auth, ownerOnly, async (req: Request, res: Response, next: NextFunction) => {
  try {
    const body = VendorSchema.parse(req.body);
    const vendor = await prisma.vendor.create({
      data: {
        ...body,
        taxSettings: body.taxSettings ? JSON.stringify(body.taxSettings) : null,
      },
    });
    res.status(201).json(vendor);
  } catch (err) {
    next(err);
  }
});

// PUT /api/v1/vendors/:id
router.put("/:id", auth, ownerOnly, async (req: Request, res: Response, next: NextFunction) => {
  try {
    const authReq = req as AuthenticatedRequest;
    if (req.params.id !== authReq.auth.vendorId) {
      throw new AppError(403, "FORBIDDEN", "Cannot modify another vendor");
    }
    const body = VendorSchema.parse(req.body);
    const vendor = await prisma.vendor.update({
      where: { id: req.params.id },
      data: {
        ...body,
        taxSettings: body.taxSettings ? JSON.stringify(body.taxSettings) : undefined,
      },
    });
    res.json(vendor);
  } catch (err) {
    next(err);
  }
});

export default router;
