const express = require("express");
const Reward = require("../models/Reward");
const auth = require("../middleware/auth");
const { asyncHandler } = require("../middleware/errorHandler");
const {
  createRewardValidation,
  rewardIdValidation,
} = require("../middleware/validators/rewardValidator");
const { paginate, buildPaginatedResponse } = require("../middleware/pagination");
const { getCacheMiddleware, invalidateCacheByPattern } = require("../middleware/cache");

const router = express.Router();

// Get all rewards (with pagination)
router.get(
  "/",
  paginate,
  getCacheMiddleware(600), // Cache for 10 minutes
  asyncHandler(async (req, res) => {
    const { page, limit } = req.pagination;

    const result = await Reward.getAllPaginated(page, limit);
    res.json(buildPaginatedResponse(result.rewards, result.pagination.totalCount, page, limit));
  }),
);

// Create a reward
router.post(
  "/",
  auth,
  createRewardValidation,
  asyncHandler(async (req, res) => {
    const { name, description, cost, isPremium } = req.body;

    const reward = await Reward.create({
      name,
      description,
      cost,
      isPremium,
    });

    // Invalidate rewards cache
    invalidateCacheByPattern('/api/rewards');

    res.json(reward);
  }),
);

// Redeem a reward
router.post(
  "/redeem/:id",
  auth,
  rewardIdValidation,
  asyncHandler(async (req, res) => {
    const rewardId = req.params.id;
    const userId = req.user.id;

    try {
      const result = await Reward.redeemReward(userId, rewardId);
      
      res.json({
        msg: "Reward redeemed successfully",
        pointsDeducted: result.pointsDeducted,
        newBalance: result.newBalance,
        redemption: result.redemption
      });
    } catch (error) {
      if (error.message === "Reward not found") {
        return res.status(404).json({ msg: "Reward not found" });
      }
      if (error.message === "Reward is not available") {
        return res.status(400).json({ msg: "Reward is not available" });
      }
      if (error.message === "User not found") {
        return res.status(404).json({ msg: "User not found" });
      }
      if (error.message === "Not enough points") {
        return res.status(400).json({ msg: "Not enough points" });
      }
      if (error.message === "Premium reward not available") {
        return res.status(403).json({ msg: "Premium reward not available" });
      }
      throw error;
    }
  }),
);

// Get reward by ID
router.get(
  "/:id",
  rewardIdValidation,
  asyncHandler(async (req, res) => {
    const reward = await Reward.findById(req.params.id);
    if (!reward) {
      return res.status(404).json({ msg: "Reward not found" });
    }
    res.json(reward);
  })
);

// Update reward
router.put(
  "/:id",
  auth,
  rewardIdValidation,
  createRewardValidation,
  asyncHandler(async (req, res) => {
    const { name, description, cost, isPremium, isActive } = req.body;
    
    const reward = await Reward.findById(req.params.id);
    if (!reward) {
      return res.status(404).json({ msg: "Reward not found" });
    }

    const updateData = { name, description, cost, isPremium };
    if (isActive !== undefined) {
      updateData.isActive = isActive;
    }

    const updatedReward = await Reward.update(req.params.id, updateData);
    res.json(updatedReward);
  })
);

// Delete reward
router.delete(
  "/:id",
  auth,
  rewardIdValidation,
  asyncHandler(async (req, res) => {
    const reward = await Reward.findById(req.params.id);
    if (!reward) {
      return res.status(404).json({ msg: "Reward not found" });
    }

    await Reward.delete(req.params.id);
    res.json({ msg: "Reward deleted successfully" });
  })
);

// Get active rewards only
router.get(
  "/active/list",
  asyncHandler(async (req, res) => {
    const rewards = await Reward.getActiveRewards();
    res.json(rewards);
  })
);

// Get premium rewards
router.get(
  "/premium/list",
  asyncHandler(async (req, res) => {
    const rewards = await Reward.getPremiumRewards();
    res.json(rewards);
  })
);

// Get regular rewards
router.get(
  "/regular/list",
  asyncHandler(async (req, res) => {
    const rewards = await Reward.getRegularRewards();
    res.json(rewards);
  })
);

// Get rewards by cost range
router.get(
  "/cost-range/:min/:max",
  asyncHandler(async (req, res) => {
    const { min, max } = req.params;
    const rewards = await Reward.findByCostRange(parseInt(min), parseInt(max));
    res.json(rewards);
  })
);

// Get user's redemption history
router.get(
  "/redemptions/user/:userId",
  auth,
  asyncHandler(async (req, res) => {
    const { userId } = req.params;
    const { limit = 20 } = req.query;
    
    // Only allow users to see their own redemption history
    if (userId !== req.user.id) {
      return res.status(403).json({ msg: "Access denied" });
    }

    const redemptions = await Reward.getUserRedemptions(userId, parseInt(limit));
    res.json(redemptions);
  })
);

// Get reward statistics
router.get(
  "/stats/:id",
  rewardIdValidation,
  asyncHandler(async (req, res) => {
    const stats = await Reward.getRewardStats(req.params.id);
    res.json(stats);
  })
);

// Get catalog statistics
router.get(
  "/catalog/stats",
  auth,
  asyncHandler(async (req, res) => {
    const stats = await Reward.getCatalogStats();
    res.json(stats);
  })
);

// Search rewards
router.get(
  "/search/:term",
  asyncHandler(async (req, res) => {
    const { term } = req.params;
    const { limit = 20 } = req.query;
    
    const rewards = await Reward.searchRewards(term, { limit: parseInt(limit) });
    res.json(rewards);
  })
);

// Toggle reward active status
router.patch(
  "/:id/toggle",
  auth,
  rewardIdValidation,
  asyncHandler(async (req, res) => {
    const updatedReward = await Reward.toggleActiveStatus(req.params.id);
    res.json(updatedReward);
  })
);

// Bulk create rewards (admin only)
router.post(
  "/bulk",
  auth,
  asyncHandler(async (req, res) => {
    const { rewards } = req.body;
    
    if (!Array.isArray(rewards) || rewards.length === 0) {
      return res.status(400).json({ msg: "Invalid rewards array" });
    }

    const result = await Reward.bulkCreate(rewards);
    res.json({
      msg: `Created ${result.length} rewards`,
      rewards: result
    });
  })
);

module.exports = router;