import fs from 'node:fs';
import path from 'node:path';
import crypto from 'node:crypto';
import multer from 'multer';

const UPLOAD_ROOT = path.resolve(process.cwd(), 'uploads');
const MAX_FILE_SIZE_BYTES = 20 * 1024 * 1024; // 20MB, matching the Figma upload box's stated limit

// DWG has no standard mimetype, so allowed types are checked by extension too.
const ALLOWED_EXTENSIONS = new Set(['.pdf', '.dwg', '.xls', '.xlsx']);

// Returns a multer instance that saves into uploads/<subdir>/, named with a
// random prefix so two uploads with the same original filename never collide.
export function createUploader(subdir: string) {
  const destination = path.join(UPLOAD_ROOT, subdir);
  fs.mkdirSync(destination, { recursive: true });

  const storage = multer.diskStorage({
    destination,
    filename: (_req, file, cb) => {
      const ext = path.extname(file.originalname);
      cb(null, `${crypto.randomUUID()}${ext}`);
    },
  });

  return multer({
    storage,
    limits: { fileSize: MAX_FILE_SIZE_BYTES },
    fileFilter: (_req, file, cb) => {
      const ext = path.extname(file.originalname).toLowerCase();
      if (!ALLOWED_EXTENSIONS.has(ext)) {
        const error = Object.assign(new Error('Only PDF, DWG, XLS and XLSX files are allowed'), {
          type: 'file.invalid.type',
        });
        cb(error);
        return;
      }
      cb(null, true);
    },
  });
}

export { UPLOAD_ROOT };

// ── Images (organization logo, profile photos): held in memory, then stored in S3 ──
// (src/utils/storage.ts). Project documents above stay on local disk.

export const MAX_IMAGE_BYTES = 5 * 1024 * 1024;

const IMAGE_TYPES: Record<string, string> = {
  '.jpg': 'image/jpeg',
  '.jpeg': 'image/jpeg',
  '.png': 'image/png',
  '.webp': 'image/webp',
  '.svg': 'image/svg+xml',
};

/** One image in the `file` field: JPG, PNG, WebP or SVG, up to 5 MB. */
export const imageUpload = multer({
  storage: multer.memoryStorage(),
  limits: { fileSize: MAX_IMAGE_BYTES, files: 1 },
  fileFilter: (_req, file, cb) => {
    const ext = path.extname(file.originalname).toLowerCase();
    if (!(ext in IMAGE_TYPES) || IMAGE_TYPES[ext] !== file.mimetype.replace('image/jpg', 'image/jpeg')) {
      cb(Object.assign(new Error('Only JPG, PNG, WebP and SVG images are allowed'), { type: 'file.invalid.type' }));
      return;
    }
    cb(null, true);
  },
}).single('file');

/** The content type to store an image with (from its extension, not the client's header). */
export const imageContentType = (originalName: string) =>
  IMAGE_TYPES[path.extname(originalName).toLowerCase()] ?? 'application/octet-stream';

/** A fresh, collision-free S3 key under `prefix`, keeping the file's extension. */
export const objectKey = (prefix: string, originalName: string) =>
  `${prefix}/${crypto.randomUUID()}${path.extname(originalName).toLowerCase()}`;
