const { Router } = require("express");
const prisma = require("../prisma");
const { requireAuth } = require("../middleware/auth");
const { requireInventoryRead, requireInventoryWrite } = require("../middleware/perms");
const { requireActiveBranch, branchWhere } = require("../middleware/branch");

const router = Router();
router.use(requireAuth, requireActiveBranch);

function optionsArrayFromBody(options) {
  if (Array.isArray(options) && options.length) {
    return options
      .map((o) => (typeof o === "string" ? o.trim() : String(o).trim()))
      .filter(Boolean);
  }
  if (typeof options === "string" && options.trim()) {
    try {
      const p = JSON.parse(options);
      if (Array.isArray(p)) {
        return p
          .map((o) => (typeof o === "string" ? o.trim() : String(o).trim()))
          .filter(Boolean);
      }
    } catch {
      return [options.trim()];
    }
  }
  return null;
}

function mapVariationRow(v) {
  const optList = Array.isArray(v.options)
    ? v.options.map((o) => String(o).trim()).filter(Boolean)
    : [];
  return {
    ...v,
    optionCount: optList.length,
  };
}

router.get("/", requireInventoryRead, 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 = branchWhere(req);
    if (search) {
      where.OR = [
        { name: { contains: search, mode: "insensitive" } },
      ];
    }

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

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

router.get("/:id", requireInventoryRead, async (req, res, next) => {
  try {
    const row = await prisma.variation.findFirst({ where: branchWhere(req, { id: req.params.id }) });
    if (!row) return res.status(404).json({ error: "Not found" });
    return res.json(mapVariationRow(row));
  } catch (err) {
    return next(err);
  }
});

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

    const optionsJson = optionsArrayFromBody(options);
    const variation = await prisma.variation.create({
      data: {
        name: String(name).trim(),
        sortOrder: Number.isFinite(Number(sortOrder)) ? Number(sortOrder) : 0,
        isActive: typeof isActive === "boolean" ? isActive : true,
        branchId: req.activeBranchId,
        ...(optionsJson && optionsJson.length ? { options: optionsJson } : {}),
      },
    });
    return res.status(201).json(mapVariationRow(variation));
  } catch (err) {
    return next(err);
  }
});

router.patch("/:id", requireInventoryWrite, async (req, res, next) => {
  try {
    const { id } = req.params;
    const existing = await prisma.variation.findFirst({ where: branchWhere(req, { id }) });
    if (!existing) return res.status(404).json({ error: "Not found" });

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

    let nextOptions;
    if (options !== undefined) {
      const parsed = optionsArrayFromBody(options);
      nextOptions = parsed && parsed.length ? parsed : null;
    }

    const data = {};
    if (name !== undefined) data.name = String(name).trim();
    if (sortOrder !== undefined) {
      data.sortOrder = Number.isFinite(Number(sortOrder)) ? Number(sortOrder) : 0;
    }
    if (isActive !== undefined) data.isActive = Boolean(isActive);
    if (nextOptions !== undefined) data.options = nextOptions;

    const variation = await prisma.variation.update({ where: { id }, data });
    return res.json(mapVariationRow(variation));
  } catch (err) {
    return next(err);
  }
});

router.delete("/:id", requireInventoryWrite, async (req, res, next) => {
  try {
    const { id } = req.params;
    const row = await prisma.variation.findFirst({ where: branchWhere(req, { id }) });
    if (!row) return res.status(404).json({ error: "Not found" });
    await prisma.variation.delete({ where: { id } });
    return res.json({ ok: true });
  } catch (err) {
    return next(err);
  }
});

module.exports = router;
