const { Router } = require("express");
const prisma = require("../prisma");
const { requireAuth } = require("../middleware/auth");
const { requirePosRead, requirePosWrite } = require("../middleware/perms");
const { auditFromReq } = require("../lib/audit");
const { notDeleted } = require("../lib/softDelete");
const { requireActiveBranch } = require("../middleware/branch");

const router = Router();

function normalizeOptionalString(input) {
  if (input === undefined) return undefined;
  if (input === null || input === "") return null;
  const s = String(input).trim();
  return s || null;
}

function prismaConflict(err, res) {
  if (err.code === "P2002") {
    return res.status(409).json({ error: "Customer name already exists" });
  }
  return null;
}

const OPTIONAL_FIELDS = ["email", "phone", "country", "city", "zipCode"];

function buildOptionalData(body) {
  const data = {};
  for (const k of OPTIONAL_FIELDS) {
    if (body[k] !== undefined) data[k] = normalizeOptionalString(body[k]);
  }
  return data;
}

router.get("/", requireAuth, requireActiveBranch, requirePosRead, async (req, res, next) => {
  try {
    const page = Math.max(1, parseInt(req.query.page) || 1);
    const limit = Math.min(100, Math.max(1, parseInt(req.query.limit) || 25));
    const skip = (page - 1) * limit;
    const search = (req.query.search || "").trim();

    const where = { ...notDeleted, branchId: req.activeBranchId };
    if (search) {
      where.OR = [
        { name: { contains: search, mode: "insensitive" } },
        { email: { contains: search, mode: "insensitive" } },
        { phone: { contains: search, mode: "insensitive" } },
      ];
    }

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

    return res.json({
      data: rows,
      pagination: { page, limit, total, totalPages: Math.ceil(total / limit) },
    });
  } catch (err) {
    return next(err);
  }
});

router.get("/:id", requireAuth, requireActiveBranch, requirePosRead, async (req, res, next) => {
  try {
    const row = await prisma.customer.findFirst({
      where: { id: req.params.id, ...notDeleted, branchId: req.activeBranchId },
    });
    if (!row) return res.status(404).json({ error: "Not found" });
    return res.json(row);
  } catch (err) {
    return next(err);
  }
});

router.post("/", requireAuth, requireActiveBranch, requirePosWrite, async (req, res, next) => {
  try {
    const body = req.body || {};
    const { name, sortOrder, isActive } = body;
    if (!name || !String(name).trim()) return res.status(400).json({ error: "Missing name" });

    const data = {
      name: String(name).trim(),
      sortOrder: Number.isFinite(Number(sortOrder)) ? Number(sortOrder) : 0,
      isActive: typeof isActive === "boolean" ? isActive : true,
      branchId: req.activeBranchId,
      ...buildOptionalData(body),
    };
    const customer = await prisma.customer.create({ data });
    auditFromReq(req, { action: "create", entityType: "Customer", entityId: customer.id, summary: customer.name });
    return res.status(201).json(customer);
  } catch (err) {
    const r = prismaConflict(err, res);
    if (r) return r;
    return next(err);
  }
});

router.patch("/:id", requireAuth, requireActiveBranch, requirePosWrite, async (req, res, next) => {
  try {
    const { id } = req.params;
    const existing = await prisma.customer.findFirst({ where: { id, ...notDeleted, branchId: req.activeBranchId } });
    if (!existing) return res.status(404).json({ error: "Not found" });

    const body = req.body || {};
    const { name, sortOrder, isActive } = body;
    if (name !== undefined && !String(name).trim()) {
      return res.status(400).json({ error: "Name cannot be empty" });
    }

    const data = {};
    if (name !== undefined) data.name = String(name).trim();
    for (const k of OPTIONAL_FIELDS) {
      if (body[k] !== undefined) data[k] = normalizeOptionalString(body[k]);
    }
    if (sortOrder !== undefined) {
      data.sortOrder = Number.isFinite(Number(sortOrder)) ? Number(sortOrder) : 0;
    }
    if (isActive !== undefined) data.isActive = Boolean(isActive);

    const customer = await prisma.customer.update({ where: { id }, data });
    return res.json(customer);
  } catch (err) {
    const r = prismaConflict(err, res);
    if (r) return r;
    return next(err);
  }
});

router.delete("/:id", requireAuth, requireActiveBranch, requirePosWrite, async (req, res, next) => {
  try {
    const { id } = req.params;
    const row = await prisma.customer.findFirst({ where: { id, ...notDeleted, branchId: req.activeBranchId } });
    if (!row) return res.status(404).json({ error: "Not found" });
    await prisma.customer.update({ where: { id }, data: { deletedAt: new Date() } });
    auditFromReq(req, { action: "delete", entityType: "Customer", entityId: id, summary: row.name });
    return res.json({ ok: true });
  } catch (err) {
    return next(err);
  }
});

module.exports = router;

