"use server";

// Server action for the release size rules.
//
// Re-checks the session like every other action here: Server Actions are
// reachable by direct POST, not only through the form on the page, so the
// layout's admin guard governs rendering and nothing more.

import { auth } from "@/auth";
import { db } from "@/db/client";
import { releaseSizeRules } from "@/db/schema";
import { eq, sql } from "drizzle-orm";
import { revalidatePath } from "next/cache";

const QUALITIES = ["sd", "720p", "1080p", "4k"] as const;
type Quality = (typeof QUALITIES)[number];

/**
 * Read one rate off the form.
 *
 * A blank or unparseable field is rejected rather than coerced. Number("") is
 * 0, and a silent 0 here is not a small mistake -- a floor of 0 accepts every
 * fake and a ceiling of 0 rejects everything ever offered.
 */
function rate(formData: FormData, name: string, { optional = false } = {}) {
  const raw = String(formData.get(name) ?? "").trim();
  if (raw === "") {
    if (optional) return null;
    throw new Error(`${name} is required`);
  }
  const value = Number(raw);
  if (!Number.isFinite(value) || value <= 0) {
    throw new Error(`${name} must be a positive number`);
  }
  // numeric(6,1): four digits before the point, one after.
  if (value > 9999) throw new Error(`${name} is implausibly large`);
  return Math.round(value * 10) / 10;
}

export async function saveSizeRulesAction(formData: FormData) {
  const session = await auth();
  if (!session?.user?.isAdmin) throw new Error("Unauthorized");

  for (const quality of QUALITIES) {
    const min = rate(formData, `${quality}-min`);
    const max = rate(formData, `${quality}-max`);
    const atmosMax = rate(formData, `${quality}-atmos`, { optional: true });
    const timelessMax = rate(formData, `${quality}-timeless`, { optional: true });

    // Checked per band rather than trusted: an inverted pair silently rejects
    // every release of that quality, and the symptom -- nothing is ever
    // grabbed -- looks nothing like the cause.
    if (min !== null && max !== null && min >= max) {
      throw new Error(`${quality}: the minimum must be below the maximum`);
    }
    if (atmosMax !== null && max !== null && atmosMax < max) {
      throw new Error(
        `${quality}: the Atmos allowance cannot be below the ordinary maximum — ` +
          "it is an allowance, not a second ceiling",
      );
    }

    if (timelessMax !== null && max !== null && timelessMax < max) {
      throw new Error(
        `${quality}: the timeless allowance cannot be below the ordinary maximum`,
      );
    }

    await db
      .update(releaseSizeRules)
      .set({
        minMbPerMinute: String(min),
        maxMbPerMinute: String(max),
        atmosMaxMbPerMinute: atmosMax === null ? null : String(atmosMax),
        timelessMaxMbPerMinute: timelessMax === null ? null : String(timelessMax),
        updatedAt: sql`now()`,
      })
      .where(eq(releaseSizeRules.quality, quality));
  }

  revalidatePath("/admin/policy/sizes");
}
