/**
 * Helpers for LONGBLOB columns (`users.photo`, `ptw_answers_media.media`).
 * Accepts raw binary buffers (e.g. multer memory uploads), data URLs, or
 * base64 strings, and normalizes them to a Buffer for persistence.
 */

/** True if buffer starts with JPEG/PNG/GIF/WebP/BMP/PDF magic bytes. */
export function hasBinaryFileMagic(buf) {
  if (!buf || buf.length < 4) return false;
  const [b0, b1, b2, b3] = [buf[0], buf[1], buf[2], buf[3]];
  if (b0 === 0xff && b1 === 0xd8 && b2 === 0xff) return true; // JPEG
  if (b0 === 0x89 && b1 === 0x50 && b2 === 0x4e && b3 === 0x47) return true; // PNG
  if (b0 === 0x47 && b1 === 0x49 && b2 === 0x46) return true; // GIF
  if (b0 === 0x25 && b1 === 0x50 && b2 === 0x44 && b3 === 0x46) return true; // %PDF
  if (b0 === 0x42 && b1 === 0x4d) return true; // BMP
  if (
    buf.length >= 12 &&
    b0 === 0x52 &&
    b1 === 0x49 &&
    b2 === 0x46 &&
    b3 === 0x46 &&
    buf[8] === 0x57 &&
    buf[9] === 0x45 &&
    buf[10] === 0x42 &&
    buf[11] === 0x50
  ) {
    return true; // WEBP
  }
  return false;
}

function tryDecodeBase64ToBuffer(str) {
  if (typeof str !== "string" || str.length < 16) return null;
  const cleaned = str.replace(/\s+/g, "").trim();
  if (!/^[A-Za-z0-9+/]+=*$/.test(cleaned)) return null;
  try {
    const out = Buffer.from(cleaned, "base64");
    return out.length ? out : null;
  } catch {
    return null;
  }
}

/**
 * Normalize an incoming value (Buffer | data URL | base64 | raw) to a Buffer
 * suitable for a LONGBLOB column. Returns null/undefined unchanged.
 */
export function normalizeBlobForPersist(value) {
  if (value == null) return value;
  if (Buffer.isBuffer(value)) return value;
  if (typeof value === "string") {
    let t = value.trim();
    if (t.startsWith("data:")) {
      const i = t.indexOf(",");
      t = i >= 0 ? t.slice(i + 1) : t;
    }
    const decoded = tryDecodeBase64ToBuffer(t);
    if (decoded) return decoded;
    return Buffer.from(value, "utf8");
  }
  return value;
}

/** First bytes → MIME for serving LONGBLOB back to clients. */
export function sniffContentType(buf) {
  if (!buf || buf.length < 4) return "application/octet-stream";
  const [b0, b1, b2, b3] = [buf[0], buf[1], buf[2], buf[3]];

  // WebM / Matroska
  if (b0 === 0x1a && b1 === 0x45 && b2 === 0xdf && b3 === 0xa3) {
    return "video/webm";
  }

  // MP4 / MOV (ISO BMFF: ....ftyp)
  if (buf.length >= 12) {
    const boxType = buf.slice(4, 8).toString("ascii");
    if (boxType === "ftyp") return "video/mp4";
  }

  // AVI (RIFF....AVI )
  if (
    b0 === 0x52 &&
    b1 === 0x49 &&
    b2 === 0x46 &&
    b3 === 0x46 &&
    buf.length >= 12 &&
    buf.slice(8, 12).toString("ascii") === "AVI "
  ) {
    return "video/x-msvideo";
  }

  if (b0 === 0xff && b1 === 0xd8 && b2 === 0xff) return "image/jpeg";
  if (b0 === 0x89 && b1 === 0x50 && b2 === 0x4e && b3 === 0x47) return "image/png";
  if (b0 === 0x47 && b1 === 0x49 && b2 === 0x46) return "image/gif";
  if (b0 === 0x25 && b1 === 0x50 && b2 === 0x44 && b3 === 0x46) return "application/pdf";
  if (b0 === 0x42 && b1 === 0x4d) return "image/bmp";
  if (
    buf.length >= 12 &&
    b0 === 0x52 &&
    b1 === 0x49 &&
    b2 === 0x46 &&
    b3 === 0x46 &&
    buf[8] === 0x57 &&
    buf[9] === 0x45 &&
    buf[10] === 0x42 &&
    buf[11] === 0x50
  ) {
    return "image/webp";
  }
  return "application/octet-stream";
}

export function bufferFromDb(raw) {
  if (raw == null) return null;
  return Buffer.isBuffer(raw) ? raw : Buffer.from(raw);
}
