/**
 * @copyright 2026 NHCarrigan
 * @license Naomi's Public License
 * @author Naomi Carrigan
 */

import { FastifyPluginAsync } from "fastify";
import { CreateLikeDto, LikeResponse, LikedItemDto, AuditAction, AuditCategory } from "@library/shared-types";
import { LikeService } from "../../services/like.service";
import { AuditService } from "../../services/audit.service";
import { bannedGuard } from "../../middleware/banned-guard";

const likesRoutes: FastifyPluginAsync = async (app) => {
  const likeService = new LikeService();

  /**
   * Toggle like on an item (authenticated users).
   */
  app.post<{ Body: CreateLikeDto; Reply: LikeResponse }>(
    "/toggle",
    {
      preValidation: [app.authenticate, bannedGuard],
      preHandler: [app.csrfProtection],
    },
    async (request) => {
      const userId = request.user.id;
      const { entityType, entityId } = request.body;
      const result = await likeService.toggleLike(userId, entityType, entityId, request);
      return result;
    }
  );

  /**
   * Get like count for an item (public route).
   */
  app.get<{
    Querystring: { entityType: string; entityId: string };
  }>(
    "/count",
    async (request, reply) => {
      const { entityType, entityId } = request.query;

      // Validate entityType
      const validTypes = ['book', 'game', 'show', 'manga', 'music', 'art'];
      if (!validTypes.includes(entityType)) {
        reply.code(400);
        return { error: "Invalid entity type" };
      }

      if (!entityId) {
        reply.code(400);
        return { error: "Entity ID is required" };
      }

      const count = await likeService.getLikeCount(entityType as any, entityId);
      return { count };
    }
  );

  /**
   * Check if current user has liked an item (authenticated users).
   */
  app.get<{
    Querystring: { entityType: string; entityId: string };
  }>(
    "/status",
    {
      preValidation: [app.authenticate],
    },
    async (request, reply) => {
      const userId = request.user.id;
      const { entityType, entityId } = request.query;

      // Validate entityType
      const validTypes = ['book', 'game', 'show', 'manga', 'music', 'art'];
      if (!validTypes.includes(entityType)) {
        reply.code(400);
        return { error: "Invalid entity type" };
      }

      if (!entityId) {
        reply.code(400);
        return { error: "Entity ID is required" };
      }

      const liked = await likeService.getUserLikeStatus(userId, entityType as any, entityId);
      return { liked };
    }
  );

  /**
   * Get all items liked by the current user (authenticated users).
   */
  app.get<{
    Querystring: { entityType?: string };
  }>(
    "/user",
    {
      preValidation: [app.authenticate],
    },
    async (request, reply) => {
      const userId = request.user.id;
      const { entityType } = request.query;

      // Validate entityType if provided
      if (entityType) {
        const validTypes = ['book', 'game', 'show', 'manga', 'music', 'art'];
        if (!validTypes.includes(entityType)) {
          reply.code(400);
          return { error: "Invalid entity type" };
        }
      }

      const likedItems = await likeService.getUserLikedItems(userId, entityType as any);
      return likedItems;
    }
  );

  /**
   * Get bulk like statuses for multiple items (authenticated users).
   * Useful for efficiently loading like status for lists.
   */
  app.post<{
    Body: { items: Array<{ entityType: string; entityId: string }> };
  }>(
    "/bulk-status",
    {
      preValidation: [app.authenticate],
    },
    async (request, reply) => {
      const userId = request.user.id;
      const { items } = request.body;

      if (!items || !Array.isArray(items)) {
        reply.code(400);
        return { error: "Items array is required" };
      }

      if (items.length > 100) {
        reply.code(400);
        return { error: "Maximum 100 items allowed per request" };
      }

      const validTypes = ['book', 'game', 'show', 'manga', 'music', 'art'];
      const results = await Promise.all(
        items.map(async (item) => {
          if (!validTypes.includes(item.entityType)) {
            return {
              entityType: item.entityType,
              entityId: item.entityId,
              liked: false,
              count: 0,
            };
          }

          const [liked, count] = await Promise.all([
            likeService.getUserLikeStatus(userId, item.entityType as any, item.entityId),
            likeService.getLikeCount(item.entityType as any, item.entityId),
          ]);

          return {
            entityType: item.entityType,
            entityId: item.entityId,
            liked,
            count,
          };
        })
      );

      return results;
    }
  );
};

export default likesRoutes;