"use server";

import { auth } from "@/auth";
import { db } from "@/lib/db";
import { hasPermission } from "@/lib/permissions";
import { revalidatePath } from "next/cache";
import { z } from "zod";

const schema = z.object({
  // A category NAME — picked from the existing list or typed to create a new one.
  categoryName: z.string().trim().min(1, "Category is required"),
  text: z.string().trim().min(1, "Clause text is required"),
  isDefault: z.boolean().default(false),
});

type Result = { ok: true } | { error: string };

async function guard(): Promise<{ ok: true } | { error: string }> {
  const session = await auth();
  if (!session?.user || !hasPermission(session.user.role, "manage_terms")) {
    return { error: "Forbidden" };
  }
  return { ok: true };
}

function parse(formData: FormData) {
  return schema.safeParse({
    categoryName: formData.get("categoryName"),
    text: formData.get("text"),
    isDefault: formData.get("isDefault") === "on" || formData.get("isDefault") === "true",
  });
}

// Find a category by name (case-insensitive), creating it (appended to the end)
// if it doesn't exist — this is how new categories are added "along with clauses".
async function ensureCategory(name: string): Promise<string> {
  const existing = await db.termsCategory.findFirst({
    where: { name: { equals: name, mode: "insensitive" } },
    select: { id: true },
  });
  if (existing) return existing.id;
  const max = await db.termsCategory.aggregate({ _max: { sortOrder: true } });
  const created = await db.termsCategory.create({
    data: { name, sortOrder: (max._max.sortOrder ?? 0) + 1 },
  });
  return created.id;
}

export async function createTerm(formData: FormData): Promise<Result> {
  const g = await guard();
  if ("error" in g) return g;

  const parsed = parse(formData);
  if (!parsed.success) return { error: parsed.error.errors[0].message };

  const categoryId = await ensureCategory(parsed.data.categoryName);
  await db.termsCondition.create({
    data: { categoryId, text: parsed.data.text, isDefault: parsed.data.isDefault },
  });
  revalidatePath("/admin/terms");
  return { ok: true };
}

export async function updateTerm(id: string, formData: FormData): Promise<Result> {
  const g = await guard();
  if ("error" in g) return g;

  const parsed = parse(formData);
  if (!parsed.success) return { error: parsed.error.errors[0].message };

  const categoryId = await ensureCategory(parsed.data.categoryName);
  await db.termsCondition.update({
    where: { id },
    data: { categoryId, text: parsed.data.text, isDefault: parsed.data.isDefault },
  });
  revalidatePath("/admin/terms");
  return { ok: true };
}

export async function toggleTermActive(id: string): Promise<Result> {
  const g = await guard();
  if ("error" in g) return g;

  const term = await db.termsCondition.findUnique({ where: { id }, select: { isActive: true } });
  if (!term) return { error: "Not found" };
  await db.termsCondition.update({ where: { id }, data: { isActive: !term.isActive } });
  revalidatePath("/admin/terms");
  return { ok: true };
}

export async function deleteTerm(id: string): Promise<Result> {
  const g = await guard();
  if ("error" in g) return g;

  // Safe to delete: POs keep their T&C as a JSON snapshot, so no PO references this row.
  await db.termsCondition.delete({ where: { id } });
  revalidatePath("/admin/terms");
  return { ok: true };
}
