const express = require("express");
const router = express.Router();
const auth = require("../middleware/auth");
const { getCacheMiddleware, invalidateCacheByPattern } = require("../middleware/cache");
const gamificationService = require("../services/gamificationService");
const User = require("../models/User");
const logger = require("../utils/logger");

/**
 * @route   GET /api/leaderboard/global
 * @desc    Get global leaderboard (all time)
 * @access  Public
 * @query   limit (default 100), offset (default 0)
 */
router.get("/global", getCacheMiddleware(300), async (req, res) => {
  try {
    const limit = Math.min(parseInt(req.query.limit) || 100, 500);
    const offset = parseInt(req.query.offset) || 0;

    logger.info("Fetching global leaderboard", { limit, offset });

    const leaderboard = await gamificationService.getGlobalLeaderboard(limit, offset);

    res.json({
      success: true,
      count: leaderboard.length,
      limit,
      offset,
      data: leaderboard
    });
  } catch (error) {
    logger.error("Error fetching global leaderboard", error);
    res.status(500).json({
      success: false,
      msg: "Server error fetching global leaderboard",
      error: error.message
    });
  }
});

/**
 * @route   GET /api/leaderboard/weekly
 * @desc    Get weekly leaderboard
 * @access  Public
 * @query   limit (default 100), offset (default 0)
 */
router.get("/weekly", getCacheMiddleware(300), async (req, res) => {
  try {
    const limit = Math.min(parseInt(req.query.limit) || 100, 500);
    const offset = parseInt(req.query.offset) || 0;

    logger.info("Fetching weekly leaderboard", { limit, offset });

    const leaderboard = await gamificationService.getWeeklyLeaderboard(limit, offset);

    res.json({
      success: true,
      count: leaderboard.length,
      limit,
      offset,
      timeframe: "week",
      data: leaderboard
    });
  } catch (error) {
    logger.error("Error fetching weekly leaderboard", error);
    res.status(500).json({
      success: false,
      msg: "Server error fetching weekly leaderboard",
      error: error.message
    });
  }
});

/**
 * @route   GET /api/leaderboard/monthly
 * @desc    Get monthly leaderboard
 * @access  Public
 * @query   limit (default 100), offset (default 0)
 */
router.get("/monthly", getCacheMiddleware(300), async (req, res) => {
  try {
    const limit = Math.min(parseInt(req.query.limit) || 100, 500);
    const offset = parseInt(req.query.offset) || 0;

    logger.info("Fetching monthly leaderboard", { limit, offset });

    const leaderboard = await gamificationService.getMonthlyLeaderboard(limit, offset);

    res.json({
      success: true,
      count: leaderboard.length,
      limit,
      offset,
      timeframe: "month",
      data: leaderboard
    });
  } catch (error) {
    logger.error("Error fetching monthly leaderboard", error);
    res.status(500).json({
      success: false,
      msg: "Server error fetching monthly leaderboard",
      error: error.message
    });
  }
});

/**
 * @route   GET /api/leaderboard/friends
 * @desc    Get friends leaderboard (requires auth)
 * @access  Private
 * @query   limit (default 100), offset (default 0)
 */
router.get("/friends", auth, getCacheMiddleware(300), async (req, res) => {
  try {
    const limit = Math.min(parseInt(req.query.limit) || 100, 500);
    const offset = parseInt(req.query.offset) || 0;
    const userId = req.user.id;

    logger.info("Fetching friends leaderboard", { userId, limit, offset });

    const leaderboard = await gamificationService.getFriendsLeaderboard(userId, limit, offset);

    res.json({
      success: true,
      count: leaderboard.length,
      limit,
      offset,
      data: leaderboard
    });
  } catch (error) {
    logger.error("Error fetching friends leaderboard", error);
    res.status(500).json({
      success: false,
      msg: "Server error fetching friends leaderboard",
      error: error.message
    });
  }
});

/**
 * @route   GET /api/leaderboard/user/:userId
 * @desc    Get user's rank and position in leaderboard
 * @access  Public
 */
router.get("/user/:userId", getCacheMiddleware(300), async (req, res) => {
  try {
    const { userId } = req.params;
    const timeframe = req.query.timeframe || "all"; // all, week, month

    logger.info("Fetching user leaderboard position", { userId, timeframe });

    const userPosition = await gamificationService.getUserLeaderboardPosition(userId, timeframe);

    if (!userPosition) {
      return res.status(404).json({
        success: false,
        msg: "User not found or has no points"
      });
    }

    res.json({
      success: true,
      data: userPosition
    });
  } catch (error) {
    logger.error("Error fetching user leaderboard position", error);
    res.status(500).json({
      success: false,
      msg: "Server error fetching user position",
      error: error.message
    });
  }
});

/**
 * @route   GET /api/leaderboard/stats
 * @desc    Get leaderboard statistics
 * @access  Public
 */
router.get("/stats", getCacheMiddleware(300), async (req, res) => {
  try {
    logger.info("Fetching leaderboard statistics");

    const stats = await gamificationService.getLeaderboardStats();

    res.json({
      success: true,
      data: stats
    });
  } catch (error) {
    logger.error("Error fetching leaderboard statistics", error);
    res.status(500).json({
      success: false,
      msg: "Server error fetching leaderboard statistics",
      error: error.message
    });
  }
});

module.exports = router;
