/**
 * /admin/media/* (mounted at /admin — PLANNING.md §4b). Every route requires a
 * valid access token; both roles manage media (only user management is
 * superadmin-only, §14 Q4). `/media/order` is declared before `/media/:id` so
 * "order" is never captured as an id.
 */
import { randomBytes } from 'node:crypto';
import { Router, type RequestHandler } from 'express';
import multer from 'multer';
import { AppError } from '../../lib/AppError';
import { asyncHandler } from '../../lib/asyncHandler';
import { authenticate } from '../../middleware/authenticate';
import { tmpDir } from './storage.service';
import * as media from './media.controller';

const MAX_UPLOAD_BYTES = 25 * 1024 * 1024;

const upload = multer({
  storage: multer.diskStorage({
    destination: (_req, _file, cb) => cb(null, tmpDir()),
    filename: (_req, _file, cb) => cb(null, randomBytes(16).toString('hex')),
  }),
  limits: { fileSize: MAX_UPLOAD_BYTES, files: 1 },
  fileFilter: (_req, file, cb) => {
    if (file.mimetype.startsWith('image/')) cb(null, true);
    else cb(new AppError(422, 'Only image uploads are accepted', { expose: true }));
  },
});

/** Wrap multer so its errors become AppErrors (errorHandler stays the one formatter). */
const uploadSingle: RequestHandler = (req, res, next) => {
  upload.single('file')(req, res, (err: unknown) => {
    if (!err) return next();
    if (err instanceof multer.MulterError) {
      if (err.code === 'LIMIT_FILE_SIZE') {
        return next(new AppError(413, 'File exceeds the 25MB limit', { expose: true }));
      }
      return next(new AppError(400, `Upload error: ${err.message}`, { expose: true }));
    }
    return next(err);
  });
};

export const mediaAdminRouter = Router();

mediaAdminRouter.use(authenticate);

mediaAdminRouter.get('/media/categories', asyncHandler(media.getCategories));
mediaAdminRouter.get('/media', asyncHandler(media.listImages));
mediaAdminRouter.post('/media', uploadSingle, asyncHandler(media.uploadImage));
mediaAdminRouter.patch('/media/order', asyncHandler(media.reorder));
mediaAdminRouter.patch('/media/:id/visibility', asyncHandler(media.setVisibility));
mediaAdminRouter.patch('/media/:id', asyncHandler(media.updateImage));
mediaAdminRouter.delete('/media/:id', asyncHandler(media.deleteImage));
