export interface ClientFileValidationOptions {
  maxSizeBytes?: number;
  allowedExtensions?: string[];
  allowedMimeTypes?: string[];
}

export interface ClientFileValidationResult {
  ok: boolean;
  errors: string[];
}

function normalizeExtension(extension: string) {
  return extension.toLowerCase().replace(/^\./, "");
}

export function formatBytes(bytes: number) {
  if (!Number.isFinite(bytes) || bytes <= 0) {
    return "0 B";
  }

  const units = ["B", "KB", "MB", "GB", "TB"];
  const exponent = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1);
  const value = bytes / 1024 ** exponent;

  return `${value.toFixed(value >= 10 || exponent === 0 ? 0 : 1)} ${units[exponent]}`;
}

export function validateClientFile(file: File, options: ClientFileValidationOptions = {}): ClientFileValidationResult {
  const errors: string[] = [];
  const {
    maxSizeBytes,
    allowedExtensions = [],
    allowedMimeTypes = []
  } = options;

  if (maxSizeBytes && file.size > maxSizeBytes) {
    errors.push(`File exceeds size limit (${formatBytes(maxSizeBytes)} max).`);
  }

  if (allowedExtensions.length > 0) {
    const extension = file.name.includes(".")
      ? normalizeExtension(file.name.split(".").pop() ?? "")
      : "";

    const extensionAllowed = allowedExtensions
      .map(normalizeExtension)
      .includes(extension);

    if (!extensionAllowed) {
      errors.push(
        `Unsupported file extension.${allowedExtensions.length > 0 ? ` Allowed: ${allowedExtensions.join(", ")}` : ""}`
      );
    }
  }

  if (allowedMimeTypes.length > 0 && file.type) {
    const mimeAllowed = allowedMimeTypes.includes(file.type);
    if (!mimeAllowed) {
      errors.push(
        `Unsupported file type.${allowedMimeTypes.length > 0 ? ` Allowed: ${allowedMimeTypes.join(", ")}` : ""}`
      );
    }
  }

  return {
    ok: errors.length === 0,
    errors
  };
}
