import { Request, Response } from 'express';
import RewardRedemption from '../models/rewardRedemption';
import RewardCatalog from '../models/rewardCatalog';
import User from '../models/users';
import { sendResponse, handleError } from '../utils/apiResponse';
import { createNotification } from '../services/notificationService';

// @desc    Admin approves or fulfills a reward redemption
// @route   POST /api/admin/rewards/redemptions/:id/approve
export const approveRedemption = async (req: Request, res: Response): Promise<void> => {
  try {
    const { id } = req.params;
    const redemption = await RewardRedemption.findById(id).populate('reward').populate('user');
    if (!redemption) return sendResponse(res, 404, 'Redemption request not found');
    if (redemption.status !== 'pending') return sendResponse(res, 400, 'Redemption already processed');

    const reward = redemption.reward as any;
    const user = redemption.user as any;

    // Check again for points and quantity (in case changed since request)
    if (user.total_points < reward.points_required) {
      return sendResponse(res, 400, 'User does not have enough points');
    }
    if (typeof reward.quantity === 'number' && reward.quantity <= 0) {
      return sendResponse(res, 400, 'Reward is out of stock');
    }

    // Increment redeemed_points for user (atomic update)
    await User.findByIdAndUpdate(user._id, { $inc: { redeemed_points: reward.points_required } });

    // Decrement reward quantity if limited
    if (typeof reward.quantity === 'number') {
      reward.quantity -= 1;
      await reward.save();
    }

    // Update redemption status
    redemption.status = 'fulfilled';
    redemption.processedAt = new Date();
    await redemption.save();

    // Notify user (in-app + push)
    await createNotification({
      userId: user._id.toString(),
      title: 'Reward Redeemed!',
      message: `Your reward "${reward.name}" has been redeemed.`,
      type: 'REWARD',
      eventKey: `reward_redeemed_${redemption._id}`,
      meta: {
        rewardId: reward._id.toString(),
        redemptionId: redemption._id.toString(),
        status: 'fulfilled',
      },
    });

    sendResponse(res, 200, 'Reward redemption fulfilled', { redemption });
  } catch (error) {
    handleError(res, error);
  }
};

// @desc    Admin rejects a reward redemption
// @route   POST /api/admin/rewards/redemptions/:id/reject
export const rejectRedemption = async (req: Request, res: Response): Promise<void> => {
  try {
    const { id } = req.params;
    const { adminNote } = req.body;
    const redemption = await RewardRedemption.findById(id);
    if (!redemption) return sendResponse(res, 404, 'Redemption request not found');
    if (redemption.status !== 'pending') return sendResponse(res, 400, 'Redemption already processed');

    redemption.status = 'rejected';
    redemption.processedAt = new Date();
    redemption.adminNote = adminNote;
    await redemption.save();

    // Notify user (in-app + push)
    await createNotification({
      userId: redemption.user.toString(),
      title: 'Reward Redemption Rejected',
      message: `Your reward redemption request was rejected.${adminNote ? ' Reason: ' + adminNote : ''}`,
      type: 'REWARD',
      eventKey: `reward_redeemed_rejected_${redemption._id}`,
      meta: {
        redemptionId: redemption._id.toString(),
        status: 'rejected',
        adminNote,
      },
    });

    sendResponse(res, 200, 'Reward redemption rejected', { redemption });
  } catch (error) {
    handleError(res, error);
  }
};

// @desc    Admin lists all redemptions
// @route   GET /api/admin/rewards/redemptions
export const listRedemptions = async (req: Request, res: Response): Promise<void> => {
  try {
    const redemptions = await RewardRedemption.find()
      .populate('user', 'name email')
      .populate('reward', 'name type points_required')
      .sort({ requestedAt: -1 });
    sendResponse(res, 200, 'Redemptions fetched', { redemptions });
  } catch (error) {
    handleError(res, error);
  }
};
