const multer = require('multer');
const path = require('path');
const { v4: uuidv4 } = require('uuid');
const config = require('../config');

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, config.contentDir);
  },
  filename: (req, file, cb) => {
    // busboy decodes the Content-Disposition filename header as latin1 by
    // default. Modern clients send raw UTF-8 bytes for non-ASCII filenames
    // (e.g. browsers + curl on UTF-8 locales send "Begrussungsscreens.jpg"
    // with c3 bc for u-umlaut). Reading those bytes as latin1 produces the
    // string "A-tilde + quarter-mark" which JS then re-encodes as 4 UTF-8
    // bytes on the way to the DB - classic double-encoding mojibake.
    //
    // The `defParamCharset: 'utf8'` option below only takes effect for
    // RFC 5987 encoded `filename*=...` params, which most clients don't send.
    // For the plain `filename="..."` case, re-decode here to recover the
    // original UTF-8 byte sequence. Mutating originalname here propagates to
    // every downstream consumer (route handlers reading req.file.originalname).
    if (file.originalname) {
      file.originalname = Buffer.from(file.originalname, 'latin1').toString('utf8');
    }
    // Deliberately NOT path.extname(file.originalname): the extension decides how a
    // browser interprets the file, and these are served from the dashboard's own origin,
    // so a caller must not choose it. multer picks the name before any bytes exist, so we
    // land on a neutral `.part` and lib/upload-sniff.finalizeUpload() renames it to a
    // content-derived extension once the bytes are on disk.
    cb(null, `${uuidv4()}.part`);
  }
});

const fileFilter = (req, file, cb) => {
  const allowedTypes = [
    'video/mp4', 'video/webm', 'video/avi', 'video/mkv', 'video/mov',
    'video/x-msvideo', 'video/quicktime', 'video/x-matroska',
    'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/bmp'
  ];
  if (allowedTypes.includes(file.mimetype) || file.mimetype.startsWith('video/') || file.mimetype.startsWith('image/')) {
    cb(null, true);
  } else {
    cb(new Error('Only video and image files are allowed'), false);
  }
};

// `defParamCharset: 'utf8'` only takes effect for RFC 5987 encoded
// `filename*=utf-8''...` params. Most real clients (browsers, curl, programmatic
// HTTP) send the plain `filename="..."` form, where busboy still reads the bytes
// as latin1 regardless of this option. The actual UTF-8 recovery happens in the
// storage.filename callback above via Buffer.from(name,'latin1').toString('utf8').
// Kept here as defense-in-depth for the rare RFC 5987 case.
const upload = multer({
  storage,
  fileFilter,
  limits: { fileSize: config.maxFileSize },
  defParamCharset: 'utf8'
});

// #216: dedicated uploader for WebVTT subtitle files. The main `fileFilter` only allows
// video/image, so subtitles need their own instance. Written into the same content dir
// (served at /uploads/content/<file>) with a .vtt name; capped small — subtitles are tiny.
const subtitleStorage = multer.diskStorage({
  destination: (req, file, cb) => cb(null, config.contentDir),
  filename: (req, file, cb) => cb(null, `${uuidv4()}.vtt`),
});
const subtitleUpload = multer({
  storage: subtitleStorage,
  limits: { fileSize: 2 * 1024 * 1024 }, // 2MB — generous for a subtitle track
  fileFilter: (req, file, cb) => {
    // Browsers send .vtt as text/vtt; some send text/plain or application/octet-stream.
    // Gate on the extension (authoritative here) plus those benign text mimetypes.
    const okExt = /\.vtt$/i.test(file.originalname || '');
    const okMime = ['text/vtt', 'text/plain', 'application/octet-stream'].includes(file.mimetype);
    if (okExt && okMime) return cb(null, true);
    cb(new Error('Only .vtt subtitle files are allowed'), false);
  },
});
upload.subtitleUpload = subtitleUpload;

module.exports = upload;
