src/api/v2/projects/projectfiles/projectfiles.routes.tsmodified
import express from "express";
import {singleUpload} from "../../../../middleware/storage";
import {
  validateBiggestFileRequest,
  validateFileUploadRequest,
  validateGetFileRequest,
} from "./projectfiles.validator";
import {
  getFiles,
  getFile,
  getBiggestFile,
  uploadFile,
} from "./projectfiles.controller";
import { hasRolesOrProjectAccess } from "../../../../middleware/authorisation";
import { Authorities } from "../../../auth/authorities.types";

const router = express.Router({ mergeParams: true });

/**
 * @swagger
 * /api/v2/projects/{projectId}/files:
 *   get:
 *     summary: List all files for a project
 *     tags: [Files]
 *     description: Returns metadata for all files uploaded to the specified project, ordered by most recently inserted first.
 *     parameters:
 *       - in: path
 *         name: projectId
 *         required: true
 *         schema:
 *           type: string
 *           format: uuid
 *         description: The project ID
 *     responses:
 *       200:
 *         description: List of project files
 *         content:
 *           application/json:
 *             schema:
 *               type: array
 *               items:
 *                 type: object
 *                 properties:
 *                   fileReferenceId:
 *                     type: string
 *                     format: uuid
 *                   fileName:
 *                     type: string
 *                   fileExtension:
 *                     type: string
 *                   xyzDisplayName:
 *                     type: string
 *                   fileSizeBytes:
 *                     type: number
 *                   fileHash:
 *                     type: string
 *                     description: SHA-256 hash of the file content
 *                   createdBy:
 *                     type: string
 *                   insertedOn:
 *                     type: string
 *                     format: date-time
 *                   lastModifiedBy:
 *                     type: string
 *                   lastModifiedOn:
 *                     type: string
 *                     format: date-time
 *       400:
 *         description: Bad request
 *       401:
 *         description: Unauthorized
 *       403:
 *         description: Forbidden
 *       500:
 *         description: Server error
 */
router.get(
  "/",
  hasRolesOrProjectAccess([], [Authorities.IMAGE_VIEW]),
  getFiles,
);

/**
 * @swagger
 * /api/v2/projects/{projectId}/files/biggest:
 *   get:
 *     summary: Get the largest file in a project
 *     tags: [Files]
 *     description: Returns the full metadata for the largest non-soft-deleted file (by FileSizeBytes) in the specified project. Returns 200 with a null body when the project has no files, and 404 when the project does not exist.
 *     parameters:
 *       - in: path
 *         name: projectId
 *         required: true
 *         schema:
 *           type: string
 *           format: uuid
 *         description: The project ID
 *     responses:
 *       200:
 *         description: The largest file's metadata, or null when the project has no files
 *         content:
 *           application/json:
 *             schema:
 *               nullable: true
 *               type: object
 *               properties:
 *                 fileReferenceId:
 *                   type: string
 *                   format: uuid
 *                 fileName:
 *                   type: string
 *                 fileExtension:
 *                   type: string
 *                 xyzDisplayName:
 *                   type: string
 *                 fileSizeBytes:
 *                   type: number
 *                 fileHash:
 *                   type: string
 *                   description: SHA-256 hash of the file content
 *                 createdBy:
 *                   type: string
 *                 insertedOn:
 *                   type: string
 *                   format: date-time
 *                 lastModifiedBy:
 *                   type: string
 *                 lastModifiedOn:
 *                   type: string
 *                   format: date-time
 *       400:
 *         description: Bad request
 *       401:
 *         description: Unauthorized
 *       403:
 *         description: Forbidden
 *       404:
 *         description: Project not found
 *       500:
 *         description: Server error
 */
router.get(
  "/biggest",
  validateBiggestFileRequest,
  hasRolesOrProjectAccess([], [Authorities.IMAGE_VIEW]),
  getBiggestFile,
);

/**
 * @swagger
 * /api/v2/projects/{projectId}/files/{fileReferenceId}:
 *   get:
 *     summary: Get details of a specific project file
 *     tags: [Files]
 *     description: Returns file details and a signed blob download URL for the specified file reference.
 *     parameters:
 *       - in: path
 *         name: projectId
 *         required: true
 *         schema:
 *           type: string
 *           format: uuid
 *         description: The project ID
 *       - in: path
 *         name: fileReferenceId
 *         required: true
 *         schema:
 *           type: string
 *           format: uuid
 *         description: The file reference ID returned from the upload endpoint
 *     responses:
 *       200:
 *         description: File details retrieved successfully
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 fileReferenceId:
 *                   type: string
 *                   format: uuid
 *                 fileName:
 *                   type: string
 *                 fileExtension:
 *                   type: string
 *                 xyzDisplayName:
 *                   type: string
 *                 fileSizeBytes:
 *                   type: number
 *                 fileHash:
 *                   type: string
 *                   description: SHA-256 hash of the file content
 *                 createdBy:
 *                   type: string
 *                 insertedOn:
 *                   type: string
 *                   format: date-time
 *                 lastModifiedBy:
 *                   type: string
 *                 lastModifiedOn:
 *                   type: string
 *                   format: date-time
 *                 downloadUrl:
 *                   type: string
 *                   description: Signed blob download URL
 *       400:
 *         description: Bad request
 *       401:
 *         description: Unauthorized
 *       403:
 *         description: Forbidden
 *       404:
 *         description: File not found
 *       500:
 *         description: Server error
 */
router.get(
  "/:fileReferenceId",
  validateGetFileRequest,
  hasRolesOrProjectAccess([], [Authorities.IMAGE_VIEW]),
  getFile,
);

/**
 * @swagger
 * /api/v2/projects/{projectId}/files:
 *   post:
 *     summary: Upload a file to a project
 *     tags: [Files]
 *     description: Uploads any file type (image, video, document, etc.) to Azure Blob Storage and records it in the database. Supports chunked upload for large files. On the first chunk (chunkIndex=0) a fileReferenceId is returned and must be supplied for subsequent chunks.
 *     parameters:
 *       - in: path
 *         name: projectId
 *         required: true
 *         schema:
 *           type: string
 *           format: uuid
 *         description: The project ID
 *     requestBody:
 *       required: true
 *       content:
 *         multipart/form-data:
 *           schema:
 *             type: object
 *             required:
 *               - file
 *               - fileName
 *               - xyzDisplayName
 *               - chunkIndex
 *               - totalChunks
 *             properties:
 *               file:
 *                 type: string
 *                 format: binary
 *                 description: The file chunk to upload
 *               fileName:
 *                 type: string
 *                 description: Original file name including extension
 *               xyzDisplayName:
 *                 type: string
 *                 description: Display name shown in the XYZ platform
 *               chunkIndex:
 *                 type: string
 *                 description: Zero-based index of the current chunk
 *               totalChunks:
 *                 type: string
 *                 description: Total number of chunks for this upload
 *               fileReferenceId:
 *                 type: string
 *                 format: uuid
 *                 description: Required for chunks after the first (returned from the first chunk response)
 *     responses:
 *       200:
 *         description: Chunk uploaded successfully (more chunks expected)
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 fileReferenceId:
 *                   type: string
 *                   format: uuid
 *                 message:
 *                   type: string
 *       201:
 *         description: File upload complete
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 fileReferenceId:
 *                   type: string
 *                   format: uuid
 *                 message:
 *                   type: string
 *       400:
 *         description: Bad request
 *       401:
 *         description: Unauthorized
 *       403:
 *         description: Forbidden
 *       500:
 *         description: Server error
 */
router.post(
  "/",
  ...singleUpload("file"),
  validateFileUploadRequest,
  hasRolesOrProjectAccess([], [Authorities.IMAGE_UPLOAD]),
  uploadFile,
);

export default router;