import type { FastifyInstance } from "fastify";
import { z } from "zod";
import { requireSession } from "../../lib/auth.js";
import { prisma } from "../../lib/prisma.js";
import { getSessionProfile } from "../../lib/session.js";
import { readBinaryFile } from "../../lib/storage.js";

const fileIdParamSchema = z.object({
  fileId: z.string().uuid(),
});

const fileQuerySchema = z.object({
  download: z
    .string()
    .optional()
    .transform((value) => value === "1" || value === "true"),
});

function sanitizeContentDispositionFileName(fileName: string) {
  return fileName.replace(/["\\\r\n]+/g, "_");
}

export async function registerFileRoutes(app: FastifyInstance) {
  app.get("/:fileId/content", async (request, reply) => {
    const session = await requireSession(request, reply);
    const profile = await getSessionProfile(session);
    const { fileId } = fileIdParamSchema.parse(request.params);
    const query = fileQuerySchema.parse(request.query);

    if (!profile) {
      throw reply.unauthorized("Session is no longer valid");
    }

    const [file] = await prisma.$queryRaw<
      Array<{
        id: string;
        law_firm_id: string;
        storage_provider: string;
        object_key: string;
        mime_type: string;
        original_file_name: string;
      }>
    >`
      SELECT id, law_firm_id, storage_provider, object_key, mime_type, original_file_name
      FROM files
      WHERE id = ${fileId}
        AND law_firm_id = ${profile.lawFirm.id}
      LIMIT 1
    `;

    if (!file) {
      throw reply.notFound("File not found");
    }

    const bytes = await readBinaryFile({
      storageProvider: file.storage_provider,
      objectKey: file.object_key,
    });
    const disposition = query.download ? "attachment" : "inline";
    const fileName = sanitizeContentDispositionFileName(file.original_file_name);

    reply.header("Content-Type", file.mime_type || "application/octet-stream");
    reply.header("Content-Length", bytes.length);
    reply.header("Content-Disposition", `${disposition}; filename="${fileName}"`);

    return reply.send(bytes);
  });
}
