// backend/controllers/workoutsController.js

const Workout = require('../models/Workout'); // Ensure the Workout model is correctly defined
const moment = require('moment');

/**
 * Get workouts for a user based on query parameters.
 */
exports.getUserWorkouts = async (req, res) => {
  try {
    const { month, categories, muscleGroup } = req.query;

    // 1. Derive userId from authenticated user
    const userId = req.user.id;

    // 2. Validate and parse the month parameter
    if (!month) {
      return res.status(400).json({ message: 'month query parameter is required.' });
    }

    const parsedMonth = moment(month, 'YYYY-MM', true);
    if (!parsedMonth.isValid()) {
      return res.status(400).json({ message: 'Invalid month format. Use YYYY-MM.' });
    }

    // 3. Define default categories
    const defaultCategories = ['Cardio', 'StrengthTraining', 'Flexibility'];
    let selectedCategories = defaultCategories;

    // 4. Filter by categories if provided
    if (categories) {
      selectedCategories = categories.split(',').map((cat) => cat.trim());
      // Validate selectedCategories against defaultCategories
      const validCategories = selectedCategories.filter((cat) => defaultCategories.includes(cat));
      if (validCategories.length === 0) {
        return res.status(400).json({ message: 'No valid categories provided.' });
      }
      selectedCategories = validCategories;
    }

    // 5. Build the query object
    const query = {
      user: userId,
      date: {
        $gte: parsedMonth.clone().startOf('month').toDate(),
        $lte: parsedMonth.clone().endOf('month').toDate(),
      },
      category: { $in: selectedCategories },
    };

    // 6. Further filter by muscle group if provided and category is StrengthTraining
    if (muscleGroup && muscleGroup !== 'All') {
      // Fetch workouts that are either StrengthTraining with the specified muscleGroup or not StrengthTraining
      query.$or = [
        { category: 'StrengthTraining', muscleGroup: muscleGroup },
        { category: { $ne: 'StrengthTraining' } },
      ];
    }

    // 7. Fetch workouts from the database
    const workouts = await Workout.find(query)
      .populate('user', '-password') // Exclude password and populate if needed
      .lean(); // Returns plain JavaScript objects

    // 8. Structure data as per frontend expectations
    const structuredData = {};

    workouts.forEach((workout) => {
      const dateStr = moment(workout.date).format('YYYY-MM-DD');
      if (!structuredData[workout.category]) {
        structuredData[workout.category] = {};
      }
      structuredData[workout.category][dateStr] = workout;
    });

    res.json(structuredData);
  } catch (error) {
    console.error('Error fetching workouts:', error);
    res.status(500).json({ message: 'Server Error' });
  }
};

// backend/middleware/authMiddleware.js

const jwt = require('jsonwebtoken');
const dotenv = require('dotenv');
const mongoose = require('mongoose');
const User = require('../models/User'); // Ensure the User model exists and is correctly defined
const { promisify } = require('util');

// Load environment variables from .env file
dotenv.config();

// Promisify jwt.verify for cleaner async/await usage
const verifyToken = promisify(jwt.verify);

/**
 * Authentication middleware to verify JWT tokens.
 * Attaches authenticated user information to req.user upon successful verification.
 */
const authMiddleware = async (req, res, next) => {
  try {
    // 1. Retrieve the Authorization header
    const authHeader = req.header('Authorization');

    if (!authHeader) {
      console.warn('No Authorization header provided.');
      return res.status(401).json({ message: 'No token, authorization denied' });
    }

    // 2. Validate the format of the Authorization header ("Bearer <token>")
    const parts = authHeader.split(' ');
    if (parts.length !== 2 || parts[0] !== 'Bearer') {
      console.warn('Invalid Authorization header format.');
      return res.status(401).json({ message: 'Token is not valid' });
    }

    const token = parts[1];

    if (!token) {
      console.warn('No token found in Authorization header.');
      return res.status(401).json({ message: 'No token, authorization denied' });
    }

    // 3. Verify the JWT token
    let decoded;
    try {
      decoded = await verifyToken(token, process.env.JWT_SECRET);
    } catch (err) {
      console.error('Token verification failed:', err.message);
      return res.status(401).json({ message: 'Token is not valid' });
    }

    // 4. Ensure the decoded token contains the necessary user information
    if (!decoded || !decoded.userId) {
      console.warn('Decoded token does not contain userId.');
      return res.status(401).json({ message: 'Token is not valid' });
    }

    // 5. Validate the format of userId
    if (!mongoose.Types.ObjectId.isValid(decoded.userId)) {
      console.warn('Invalid userId format in token.');
      return res.status(401).json({ message: 'Token is not valid' });
    }

    // 6. Fetch the user from the database to ensure they still exist
    const user = await User.findById(decoded.userId).select('-password'); // Exclude sensitive fields

    if (!user) {
      console.warn('User not found for userId:', decoded.userId);
      return res.status(401).json({ message: 'User does not exist' });
    }

    // 7. Attach user information to the request object
    req.user = {
      id: user._id.toString(), // Ensuring 'id' is a string
      name: user.name,
      email: user.email,
      // Add other user properties as needed, e.g., roles, permissions
    };

    console.log(`Token verified. Authenticated user: ${req.user.email} (${req.user.id})`);

    // 8. Proceed to the next middleware or route handler
    next();
  } catch (error) {
    console.error('Authentication Middleware Error:', error);
    res.status(500).json({ message: 'Server Error during authentication' });
  }
};

module.exports = authMiddleware;

Error fetching workouts: TypeError: Cannot read properties of undefined (reading 'toString')
    at exports.getUserWorkouts (D:\apps\Fitness-app\backend\controllers\workoutsController.js:14:32)
    at Layer.handle [as handle_request] (D:\apps\Fitness-app\backend\node_modules\express\lib\router\layer.js:95:5)
    at next (D:\apps\Fitness-app\backend\node_modules\express\lib\router\route.js:149:13)
    at authMiddleware (D:\apps\Fitness-app\backend\middleware\authMiddleware.js:30:9)
    at Layer.handle [as handle_request] (D:\apps\Fitness-app\backend\node_modules\express\lib\router\layer.js:95:5)
    at next (D:\apps\Fitness-app\backend\node_modules\express\lib\router\route.js:149:13)
    at Route.dispatch (D:\apps\Fitness-app\backend\node_modules\express\lib\router\route.js:119:3)
    at Layer.handle [as handle_request] (D:\apps\Fitness-app\backend\node_modules\express\lib\router\layer.js:95:5)
    at D:\apps\Fitness-app\backend\node_modules\express\lib\router\index.js:284:15
    at Function.process_params (D:\apps\Fitness-app\backend\node_modules\express\lib\router\index.js:346:12)
::ffff:10.0.0.218 - - [08/Oct/2024:18:35:46 +0000] "GET /api/workouts?userId=66ff4c3d7a99bdf2f7ac6024&month=2024-10&categories=Cardio,StrengthTraining,Flexibility HTTP/1.1" 500 26 "-" "okhttp/4.9.2"