const express = require('express');
const passport = require('passport');
const bodyParser = require('body-parser');
const services = require('../services/file/');
const { isValidPath, createErrorResponse } = require('../services/file');
const { logger } = require('../utils/logger');

const router = express.Router();

// JSON body parser that ONLY parses application/json content-type
// This prevents errors when binary data is sent or no body is present
const jsonParser = bodyParser.json({
  limit: '1mb',
  type: (req) => {
    const contentType = req.headers['content-type'] || '';
    return contentType.includes('application/json');
  },
});

router.get('/download', (req, res) => {
  services.downloadFile(req, res);
});

// POST /api/file/presign - Generate presigned URLs for multiple assets
router.post('/presign', jsonParser, async (req, res) => {
  const log = req.log || logger;
  const { urls } = req.body || {};

  if (!Array.isArray(urls) || urls.length === 0) {
    return res.status(400).json(createErrorResponse('urls array required', 'MISSING_URLS'));
  }

  if (urls.length > 50) {
    return res.status(400).json(createErrorResponse('Maximum 50 URLs per request', 'TOO_MANY_URLS'));
  }

  // Validate that all URLs are non-empty strings
  const invalidUrls = urls.filter(
    (url) => typeof url !== 'string' || !url.trim(),
  );
  if (invalidUrls.length > 0) {
    return res.status(400).json(createErrorResponse('All URLs must be non-empty strings', 'INVALID_URL_FORMAT'));
  }

  // Validate paths for security (no traversal, no protocols)
  const unsafeUrls = urls.filter((url) => !isValidPath(url));
  if (unsafeUrls.length > 0) {
    log.warn({ unsafeUrls }, 'Presign request with invalid paths rejected');
    return res.status(400).json(createErrorResponse('Invalid file paths detected', 'INVALID_PATH', {
      invalidPaths: unsafeUrls,
    }));
  }

  try {
    const presignedUrls = await services.generatePresignedUrls(urls);
    res.json({ presignedUrls });
  } catch (error) {
    log.error({ err: error, urlCount: urls.length }, 'Failed to generate presigned URLs');
    res.status(500).json(createErrorResponse('Failed to generate presigned URLs', 'PRESIGN_ERROR'));
  }
});

router.post(
  '/upload/:table/:field',
  passport.authenticate('jwt', { session: false }),
  (req, res) => {
    const fileName = `${req.params.table}/${req.params.field}`;

    services.uploadFile(fileName, req, res);
  },
);

router.post(
  '/upload-sessions/init',
  passport.authenticate('jwt', { session: false }),
  jsonParser,
  (req, res) => {
    services.initUploadSession(req, res);
  },
);

router.get(
  '/upload-sessions/:sessionId',
  passport.authenticate('jwt', { session: false }),
  (req, res) => {
    services.getUploadSession(req, res);
  },
);

// Chunk upload - NO body parser, raw stream is read directly by uploadChunk
router.put(
  '/upload-sessions/:sessionId/chunks/:chunkIndex',
  passport.authenticate('jwt', { session: false }),
  (req, res) => {
    services.uploadChunk(req, res);
  },
);

// Finalize - NO body parser needed, only uses req.params.sessionId
router.post(
  '/upload-sessions/:sessionId/finalize',
  passport.authenticate('jwt', { session: false }),
  (req, res) => {
    services.finalizeUploadSession(req, res);
  },
);

module.exports = router;
