export const WARNING_LIMIT_BYTES = 4_294_967_296;
export const CRITICAL_LIMIT_BYTES = 4_831_838_208;
export const HARD_LIMIT_BYTES = 5_368_709_120;
export const CAPACITY_COUNTED_FILE_KINDS = [
  "reference",
  "generated",
  "export",
  "derived",
  "sticker_original",
  "sticker_thumbnail",
] as const;
export const CAPACITY_EXCLUDED_STORAGE = [
  "read_only_assets",
  "application_files",
  "database",
  "logs",
  "audit",
  "browser_cache",
  "user_downloads",
] as const;

export type CapacityNoticeLevel = "normal" | "warning" | "critical";
export type StorageStatus = "active" | "full" | "unavailable";
export type StorageAction =
  | "project_json_write"
  | "binary_write"
  | "ai_call"
  | "latest_export_write"
  | "read"
  | "download"
  | "client_only_download"
  | "permanent_delete"
  | "explicit_cleanup";
export type StorageActionDecision = "allow" | "reject_capacity" | "reject_unavailable" | "reject_uncommitted";

export function classifyCapacity(managedContentBytes: number, activeReservationBytes: number) {
  if (!Number.isSafeInteger(managedContentBytes) || managedContentBytes < 0) throw new Error("managed_content_bytes_invalid");
  if (!Number.isSafeInteger(activeReservationBytes) || activeReservationBytes < 0) throw new Error("active_reservation_bytes_invalid");
  const capacity_notice_level: CapacityNoticeLevel = managedContentBytes < WARNING_LIMIT_BYTES
    ? "normal"
    : managedContentBytes < CRITICAL_LIMIT_BYTES
      ? "warning"
      : "critical";
  const storage_status: StorageStatus = managedContentBytes + activeReservationBytes >= HARD_LIMIT_BYTES
    ? "full"
    : "active";
  return { capacity_notice_level, storage_status };
}

export function decideStorageAction(
  status: StorageStatus,
  sqliteWritable: boolean,
  action: StorageAction,
): StorageActionDecision {
  if (status === "unavailable") {
    if (action === "read" || action === "download" || action === "client_only_download") return "allow";
    if (action === "permanent_delete" || action === "explicit_cleanup") {
      return sqliteWritable ? "allow" : "reject_uncommitted";
    }
    return "reject_unavailable";
  }
  if (status === "full" && (action === "binary_write" || action === "ai_call" || action === "latest_export_write")) {
    return "reject_capacity";
  }
  return "allow";
}

export function storageCapacityErrorDetails(input: {
  activeReservationBytes: number;
  managedContentBytes: number;
  projectedWriteBytes: number;
}) {
  const { capacity_notice_level, storage_status } = classifyCapacity(
    input.managedContentBytes,
    input.activeReservationBytes,
  );
  return {
    capacity_status: storage_status === "full" ? "full" as const : capacity_notice_level,
    remaining_bytes: Math.max(0, HARD_LIMIT_BYTES - input.managedContentBytes - input.activeReservationBytes),
  };
}
