import { TRPCError } from "@trpc/server";
import type {
  Storageindex,
  StorageindexId,
} from "~/schemas/public/Storageindex";
import type { UsersId } from "~/schemas/public/Users";
import {
  addUserStorageJunc,
  deleteFile,
  deleteUserStorageJunc,
} from "~/server/services/storage.service";
import type { Querier } from "~/server/db";
import { jsonArrayFrom } from "kysely/helpers/postgres";

export const getAllHandler = async ({ db }: { db: Querier }) => {
  return await db.selectFrom("storageindex").selectAll().execute();
};

export const getFromIdHandler = async ({
  db,
  storage_id,
}: {
  db: Querier;
  storage_id: StorageindexId;
}) => {
  return await db
    .selectFrom("storageindex")
    .selectAll()
    .where("id", "=", storage_id)
    .executeTakeFirst();
};

export const getUserStorageHandler = async ({
  db,
  userId,
}: {
  db: Querier;
  userId: UsersId;
}): Promise<Storageindex[]> => {
  try {
    return await db
      .selectFrom("storageindex")
      .selectAll("storageindex")
      .rightJoin("users_storage", "users_storage.storageid", "storageindex.id")
      .where("users_storage.userid", "=", userId)
      .orderBy("created_at", "desc")
      .execute();
  } catch {
    throw new TRPCError({
      code: "INTERNAL_SERVER_ERROR",
      message: "Error while getting user storage",
    });
  }
};

export const addUserStorageHandler = async ({
  db,
  userId,
  storageId,
}: {
  db: Querier;
  userId: UsersId;
  storageId: StorageindexId;
}) => {
  try {
    await addUserStorageJunc({
      db,
      userId,
      storageId,
    });

    return "ok";
  } catch (e) {
    throw new TRPCError({
      code: "INTERNAL_SERVER_ERROR",
      message: "Error while adding user storage: " + (e as Error).message,
    });
  }
};

export const deleteUserStorageHandler = async ({
  db,
  userId,
  storageId,
}: {
  db: Querier;
  userId: UsersId;
  storageId: StorageindexId;
}) => {
  try {
    const file = await db
      .selectFrom("users_storage")
      .selectAll()
      .where("userid", "=", userId)
      .where("storageid", "=", storageId)
      .executeTakeFirst();
    if (!file) {
      return "no file";
    }

    await deleteFile({
      db,
      fileId: file.storageid,
      cb: async (fileId) => {
        await db.transaction().execute(async (trx) => {
          await deleteUserStorageJunc({
            db: trx,
            userId,
            storageId: fileId,
          });

          await trx
            .deleteFrom("storageindex")
            .where("id", "=", fileId)
            .execute();
        });
      },
    });
    return "ok";
  } catch {
    throw new TRPCError({
      code: "INTERNAL_SERVER_ERROR",
      message: "Error while deleting user storage",
    });
  }
};

// export const deleteAllUserStorageHandler = async ({
//   db,
//   userId,
// }: {
//   db: Querier;
//   userId: UsersId;
// }) => {
//   try {
//     const files = await db
//       .selectFrom("users_storage")
//       .select("storageid")
//       .where("userid", "=", userId)
//       .execute();

//     if (!files || files.length === 0) {
//       return "no files";
//     }
//     await deleteFiles({
//       db,
//       refs: files,
//       cb: async (fileIds) => {
//         const ids = fileIds.map((file) => file.storageid);
//         await db.transaction().execute(async (trx) => {
//           await trx
//             .deleteFrom("users_storage")
//             .where("userid", "=", userId)
//             .where("storageid", "in", ids)
//             .execute();
//           await trx.deleteFrom("storageindex").where("id", "in", ids).execute();
//         });
//       },
//     });
//     return "ok";
//   } catch {
//     throw new TRPCError({
//       code: "INTERNAL_SERVER_ERROR",
//       message: "Error while deleting user storage",
//     });
//   }
// };

export const getMultipleWithRelations = async ({
  db,
  ids,
}: {
  db: Querier;
  ids: StorageindexId[];
}) => {
  return await db
    .selectFrom("storageindex")
    .selectAll("storageindex")
    .select((eb) => [
      jsonArrayFrom(
        eb
          .selectFrom("users_storage")
          .leftJoin("users", "users.id", "users_storage.userid")
          .select(["users.username"])
          .whereRef("users_storage.storageid", "=", "storageindex.id")
          .selectAll("users_storage"),
      ).as("users_storages"),
    ])
    .where("id", "in", ids)
    .execute();
};
