import { G as createContentManager, bo as getStorageProvider, dM as emitMediaUpdate, c as createError, dN as emitMediaDelete, bN as dbQueryOne } from '../nitro/nitro.mjs';
import { p as parseNullablePositiveInt } from './ids.mjs';
import { g as generateMediaVariants, i as invalidateTransformCache, d as deleteMediaVariants, v as validateFocalPoint, a as isProcessableImage, p as parseFocalPoint } from './media-variants.mjs';
import { a as assertMediaNotInUse } from './media-usage.mjs';

const MEDIA_MUTABLE_FIELDS = ["alt", "caption", "folder", "width", "height", "focalPoint"];
async function getMediaEntryOrThrow(id, notFoundMessage = `Media file with ID ${id} not found`) {
  const media = await createContentManager("media").findOne(id);
  if (!media) {
    throw createError({
      statusCode: 404,
      statusMessage: "Not Found",
      message: notFoundMessage
    });
  }
  return media;
}
async function buildMediaUpdateData(body) {
  if (!body || typeof body !== "object" || Array.isArray(body)) {
    throw createError({
      statusCode: 400,
      statusMessage: "Bad Request",
      message: "Request body must be a valid JSON object"
    });
  }
  const updateData = {};
  const payload = body;
  for (const field of MEDIA_MUTABLE_FIELDS) {
    if (field in payload) {
      updateData[field] = payload[field];
    }
  }
  if (Object.keys(updateData).length === 0) {
    throw createError({
      statusCode: 400,
      statusMessage: "Bad Request",
      message: "No valid fields to update"
    });
  }
  if ("focalPoint" in updateData) {
    try {
      updateData.focalPoint = validateFocalPoint(updateData.focalPoint);
    } catch (err) {
      throw createError({
        statusCode: 400,
        statusMessage: "Bad Request",
        message: err instanceof Error ? err.message : "Invalid focalPoint"
      });
    }
  }
  if ("folder" in updateData) {
    const parsedFolderId = parseNullablePositiveInt(updateData.folder);
    if (!parsedFolderId.valid) {
      throw createError({
        statusCode: 400,
        statusMessage: "Bad Request",
        message: "Invalid folder ID"
      });
    }
    updateData.folder = parsedFolderId.value;
    if (parsedFolderId.value !== null) {
      const folder = await dbQueryOne(`SELECT id FROM media_folders WHERE id = ?`, [
        parsedFolderId.value
      ]);
      if (!folder) {
        throw createError({
          statusCode: 404,
          statusMessage: "Not Found",
          message: `Folder with ID ${parsedFolderId.value} not found`
        });
      }
    }
  }
  return updateData;
}
async function updateMediaById(id, body, actor) {
  const mediaManager = createContentManager("media");
  const existing = await getMediaEntryOrThrow(id);
  const updateData = await buildMediaUpdateData(body);
  const shouldRefreshVariants = shouldRefreshMediaVariants(existing, updateData);
  const existingFormats = shouldRefreshVariants ? parseFormats(existing.formats) : null;
  let nextFormats;
  if (shouldRefreshVariants) {
    const mediaPath = getRequiredStringField(existing.path, "Media file path is invalid");
    const mimeType = getRequiredStringField(existing.mimeType, "Media file MIME type is invalid");
    const storage = getStorageProvider();
    const sourceBuffer = await storage.getFile(mediaPath);
    const focalPoint = toNullableFocalPoint(updateData.focalPoint);
    nextFormats = await generateMediaVariants(sourceBuffer, mediaPath, mimeType, {
      focalPoint,
      variantSuffix: buildVariantRevisionToken()
    });
    updateData.formats = nextFormats;
  }
  try {
    const updated = await mediaManager.update(id, updateData, void 0, { actor });
    if (shouldRefreshVariants) {
      await invalidateTransformCache(id).catch(() => {
      });
      if (existingFormats) {
        await deleteMediaVariants(existingFormats).catch(() => {
        });
      }
    }
    await emitMediaUpdate(id, updated, actor);
    return updated;
  } catch (error) {
    if (shouldRefreshVariants && nextFormats) {
      await deleteMediaVariants(nextFormats).catch(() => {
      });
    }
    throw error;
  }
}
async function deleteMediaEntry(id, media, actor) {
  const mediaPath = media.path;
  if (typeof mediaPath !== "string" || mediaPath.trim() === "") {
    throw createError({
      statusCode: 500,
      statusMessage: "Internal Server Error",
      message: "Media file path is invalid"
    });
  }
  const storage = getStorageProvider();
  try {
    await storage.delete({ path: mediaPath });
  } catch (error) {
    throw createError({
      statusCode: 500,
      statusMessage: "Internal Server Error",
      message: `Failed to delete media file from storage: ${error instanceof Error ? error.message : "Unknown error"}`
    });
  }
  const formats = parseFormats(media.formats);
  await Promise.all([deleteMediaVariants(formats), invalidateTransformCache(id)]);
  await createContentManager("media").delete(id, { actor });
  await emitMediaDelete(id, media, actor);
  return {
    id,
    path: mediaPath
  };
}
function parseFormats(value) {
  if (!value) {
    return null;
  }
  if (typeof value === "string") {
    try {
      return JSON.parse(value);
    } catch {
      return null;
    }
  }
  if (typeof value !== "object") {
    return null;
  }
  const obj = value;
  if (obj.variants && typeof obj.variants === "object") {
    return value;
  }
  return null;
}
function shouldRefreshMediaVariants(media, updateData) {
  if (!("focalPoint" in updateData)) {
    return false;
  }
  const mimeType = typeof media.mimeType === "string" ? media.mimeType : "";
  if (!isProcessableImage(mimeType)) {
    return false;
  }
  return !areFocalPointsEqual(
    toNullableFocalPoint(media.focalPoint),
    toNullableFocalPoint(updateData.focalPoint)
  );
}
function toNullableFocalPoint(value) {
  var _a;
  if (value === null) {
    return null;
  }
  return (_a = parseFocalPoint(value)) != null ? _a : null;
}
function areFocalPointsEqual(a, b) {
  if (a === null || b === null) {
    return a === b;
  }
  return a.x === b.x && a.y === b.y;
}
function getRequiredStringField(value, message) {
  if (typeof value !== "string" || value.trim() === "") {
    throw createError({
      statusCode: 500,
      statusMessage: "Internal Server Error",
      message
    });
  }
  return value;
}
function buildVariantRevisionToken() {
  return `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;
}
async function deleteMediaById(id, notFoundMessage, actor) {
  const media = await getMediaEntryOrThrow(id, notFoundMessage);
  await assertMediaNotInUse(id);
  return deleteMediaEntry(id, media, actor);
}

export { deleteMediaById as d, getMediaEntryOrThrow as g, updateMediaById as u };
//# sourceMappingURL=media-operations.mjs.map
