import { GraphQLError } from "graphql";
import { builder } from "../builder";
import { CommentType } from "../types/index";
import { comments, users } from "../../db/schema/index";
import { eq, and, desc } from "drizzle-orm";
import { awardPoints, checkAchievements } from "../../lib/gamification";
import { requireOwnerOrAdmin } from "../../lib/acl";

builder.queryField("commentsForVideo", (t) =>
  t.field({
    type: [CommentType],
    args: {
      videoId: t.arg.string({ required: true }),
    },
    resolve: async (_root, args, ctx) => {
      const commentList = await ctx.db
        .select()
        .from(comments)
        .where(and(eq(comments.collection, "videos"), eq(comments.item_id, args.videoId)))
        .orderBy(desc(comments.date_created));

      return Promise.all(
        commentList.map(async (c: any) => {
          const user = await ctx.db
            .select({
              id: users.id,
              first_name: users.first_name,
              last_name: users.last_name,
              artist_name: users.artist_name,
              avatar: users.avatar,
            })
            .from(users)
            .where(eq(users.id, c.user_id))
            .limit(1);
          return { ...c, user: user[0] || null };
        }),
      );
    },
  }),
);

builder.mutationField("createCommentForVideo", (t) =>
  t.field({
    type: CommentType,
    args: {
      videoId: t.arg.string({ required: true }),
      comment: t.arg.string({ required: true }),
    },
    resolve: async (_root, args, ctx) => {
      if (!ctx.currentUser) throw new GraphQLError("Unauthorized");

      const newComment = await ctx.db
        .insert(comments)
        .values({
          collection: "videos",
          item_id: args.videoId,
          comment: args.comment,
          user_id: ctx.currentUser.id,
        })
        .returning();

      // Gamification
      await awardPoints(ctx.db, ctx.currentUser.id, "COMMENT_CREATE");
      await checkAchievements(ctx.db, ctx.currentUser.id, "social");

      const user = await ctx.db
        .select({
          id: users.id,
          first_name: users.first_name,
          last_name: users.last_name,
          artist_name: users.artist_name,
          avatar: users.avatar,
        })
        .from(users)
        .where(eq(users.id, ctx.currentUser.id))
        .limit(1);

      return { ...newComment[0], user: user[0] || null };
    },
  }),
);

builder.mutationField("deleteComment", (t) =>
  t.field({
    type: "Boolean",
    args: {
      id: t.arg.int({ required: true }),
    },
    resolve: async (_root, args, ctx) => {
      const comment = await ctx.db.select().from(comments).where(eq(comments.id, args.id)).limit(1);
      if (!comment[0]) throw new GraphQLError("Comment not found");
      requireOwnerOrAdmin(ctx, comment[0].user_id);
      await ctx.db.delete(comments).where(eq(comments.id, args.id));
      return true;
    },
  }),
);
