import "server-only";

import path from "node:path";

import { getMediaProcessingConfig } from "@/lib/server/media-config";
import { MediaProcessingError } from "@/lib/server/media-errors";

const DEFAULT_ALLOWED_EXTENSIONS = [
  ".mp4",
  ".mov",
  ".m4v",
  ".webm",
  ".mkv",
  ".avi",
  ".wmv",
  ".flv"
];

const DEFAULT_ALLOWED_MIME_TYPES = [
  "video/mp4",
  "video/quicktime",
  "video/x-m4v",
  "video/webm",
  "video/x-matroska",
  "video/x-msvideo",
  "video/x-ms-wmv",
  "video/x-flv"
];

export interface MediaFileValidationOptions {
  allowedExtensions?: string[];
  allowedMimeTypes?: string[];
  maxUploadSizeBytes?: number;
}

function ensureDotPrefix(extension: string) {
  return extension.startsWith(".") ? extension.toLowerCase() : `.${extension.toLowerCase()}`;
}

export function sanitizeBaseName(fileName: string) {
  const extension = path.extname(fileName);
  const rawBaseName = path.basename(fileName, extension);
  const safeName = rawBaseName.replace(/[^a-zA-Z0-9-_]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
  return safeName || "media";
}

export function validateVideoUploadFile(
  file: File,
  options: MediaFileValidationOptions = {}
) {
  const config = getMediaProcessingConfig();
  const allowedExtensions = (options.allowedExtensions || DEFAULT_ALLOWED_EXTENSIONS).map(ensureDotPrefix);
  const allowedMimeTypes = options.allowedMimeTypes || DEFAULT_ALLOWED_MIME_TYPES;
  const maxUploadSizeBytes = options.maxUploadSizeBytes || config.maxUploadSizeBytes;

  if (file.size <= 0) {
    throw new MediaProcessingError({
      message: "Uploaded file is empty.",
      code: "invalid_file",
      statusCode: 400
    });
  }

  if (file.size > maxUploadSizeBytes) {
    throw new MediaProcessingError({
      message: `File exceeds max size of ${String(maxUploadSizeBytes)} bytes.`,
      code: "invalid_file",
      statusCode: 413
    });
  }

  const extension = path.extname(file.name).toLowerCase();
  if (!allowedExtensions.includes(extension)) {
    throw new MediaProcessingError({
      message: `Unsupported file extension '${extension}'.`,
      code: "invalid_file",
      statusCode: 400
    });
  }

  if (file.type && !allowedMimeTypes.includes(file.type)) {
    throw new MediaProcessingError({
      message: `Unsupported file MIME type '${file.type}'.`,
      code: "invalid_file",
      statusCode: 400
    });
  }

  return {
    extension,
    baseName: sanitizeBaseName(file.name)
  };
}

export function validateOptionalTimeRange(
  startSeconds: number | null | undefined,
  endSeconds: number | null | undefined
) {
  if (startSeconds == null && endSeconds == null) {
    return;
  }

  if (startSeconds == null || endSeconds == null) {
    throw new MediaProcessingError({
      message: "Both start and end times are required when providing a range.",
      code: "invalid_input",
      statusCode: 400
    });
  }

  if (!Number.isFinite(startSeconds) || !Number.isFinite(endSeconds)) {
    throw new MediaProcessingError({
      message: "Invalid time range values.",
      code: "invalid_input",
      statusCode: 400
    });
  }

  if (startSeconds < 0 || endSeconds < 0 || endSeconds <= startSeconds) {
    throw new MediaProcessingError({
      message: "Invalid time range; ensure end is greater than start.",
      code: "invalid_input",
      statusCode: 400
    });
  }
}
