import { TRPCError } from "@trpc/server";
import z from "zod";
import type { NewUsersStorage } from "~/schemas/public/UsersStorage";
import {
	adminProcedure,
	createTRPCRouter,
	protectedProcedure,
} from "~/server/api/trpc";
import {
	addUserStorage,
	deleteUserStorageEntry,
	getAllWithFromAdmin,
	getMultipleWithRelations,
	purgeFileFromUserStorages,
	retrieveUserFiles,
} from "~/server/controllers/storage.controller";
import { db } from "~/server/db";
import {
	deleteFile,
	editFile,
	getFileInfo,
} from "~/server/services/storage.service";
import { zUserId } from "~/server/utils/zod_types";

export const storageRouter = createTRPCRouter({
	getFileInfos: protectedProcedure
		.input(z.object({ storageId: z.string() }))
		.query(async ({ input }) => {
			return (await getFileInfo(input.storageId)) || undefined;
		}),
	deleteFile: protectedProcedure
		.input(z.object({ storageId: z.string() }))
		.mutation(async ({ input }) => {
			const deletion = await deleteFile(input.storageId);
			if (!deletion.success) {
				throw new TRPCError({
					code: "INTERNAL_SERVER_ERROR",
					message: deletion.error,
				});
			}
			await purgeFileFromUserStorages({
				...input,
			});
		}),
	deleteUserStorageEntry: protectedProcedure
		.input(z.object({ storageId: z.string(), userId: zUserId }))
		.mutation(async ({ input }) => {
			return await deleteUserStorageEntry(input);
		}),
	deleteFilesFromUserStorage: adminProcedure
		.input(z.object({ storageIds: z.string().array() }))
		.mutation(async ({ input }) => {
			for (const storageId of input.storageIds) {
				await purgeFileFromUserStorages({ storageId });
			}
			return "ok";
		}),
	retrieveUserFileData: protectedProcedure
		.input(z.object({ userId: zUserId }))
		.query(async ({ input }) => {
			return await retrieveUserFiles(input);
		}),
	getStorageAccessDetails: adminProcedure
		.input(z.object({ storageIds: z.string().array() }))
		.query(async ({ input }) => {
			return await getMultipleWithRelations({
				db,
				ids: input.storageIds,
			});
		}),
	addUserStorageEntry: protectedProcedure
		.input(z.custom<NewUsersStorage>())
		.mutation(async ({ input }) => {
			return await addUserStorage(input);
		}),

	getAll: protectedProcedure.query(async () => {
		return await getAllWithFromAdmin();
	}),

	renameFile: adminProcedure
		.input(z.object({ fileId: z.string(), name: z.string() }))
		.mutation(async ({ input }) => {
			return await editFile(input.fileId, input.name);
		}),
});
