ERROR  Error fetching workout data: [TypeError: api.get is not a function (it is undefined)]
 ERROR  Error fetching workout data: [TypeError: api.get is not a function (it is undefined)]
 ERROR  Error fetching workout data: [TypeError: api.get is not a function (it is undefined)]
 ERROR  Error fetching workout data: [TypeError: api.get is not a function (it is undefined)]
 ERROR  Error fetching workout data: [TypeError: api.get is not a function (it is undefined)]
 ERROR  Error fetching workout data: [TypeError: api.get is not a function (it is undefined)]

// components/WorkoutHeatmap.js

import React, { useState, useEffect, useContext } from 'react';
import {
  View,
  StyleSheet,
  Dimensions,
  TouchableOpacity,
  Text,
  ActivityIndicator,
  Modal,
  ScrollView,
  Alert,
} from 'react-native';
import Svg, { Rect, Text as SvgText, G, Circle } from 'react-native-svg';
import moment from 'moment';
import { useTheme } from 'react-native-paper';
import { Picker } from '@react-native-picker/picker';
import { AuthContext } from '../context/AuthContext';
import useApi from '../services/api'; // Import the custom Axios hook

const { width } = Dimensions.get('window');
const CELL_SIZE = 30;
const CELL_MARGIN = 4;
const NUM_COLUMNS = 7; // Days of the week

const workoutCategories = ['Cardio', 'StrengthTraining', 'Flexibility'];
const muscleGroups = [
  'All',
  'Chest',
  'Shoulders',
  'Back',
  'Arms',
  'Legs',
  'Quads',
  'Hamstrings',
  'Calves',
  'Glutes',
  'Abs',
  'Obliques',
  'Lower Back',
];

const WorkoutHeatmap = () => {
  const theme = useTheme();
  const { user } = useContext(AuthContext);
  const api = useApi(); // Use the custom Axios instance
  const [selectedCategories, setSelectedCategories] = useState(workoutCategories); // Initially all selected
  const [selectedMuscleGroup, setSelectedMuscleGroup] = useState('All');
  const [currentMonth, setCurrentMonth] = useState(moment());
  const [dateMatrix, setDateMatrix] = useState([]);
  const [workoutData, setWorkoutData] = useState({});
  const [loading, setLoading] = useState(true);
  const [tooltipData, setTooltipData] = useState(null); // For displaying details on tap

  useEffect(() => {
    // Generate date matrix for the current month
    const startOfMonth = currentMonth.clone().startOf('month').startOf('week');
    const endOfMonth = currentMonth.clone().endOf('month').endOf('week');
    const matrix = [];
    let currentDate = startOfMonth.clone();

    while (currentDate.isBefore(endOfMonth)) {
      const week = [];
      for (let i = 0; i < 7; i++) {
        week.push(currentDate.clone());
        currentDate.add(1, 'day');
      }
      matrix.push(week);
    }

    setDateMatrix(matrix);
  }, [currentMonth]);

  useEffect(() => {
    // Fetch workout data whenever dependencies change
    const fetchWorkoutData = async () => {
      if (!user) {
        setWorkoutData({});
        setLoading(false);
        return;
      }

      setLoading(true);

      try {
        // Define the API endpoint for fetching workout data
        // The `useApi` hook already sets the baseURL, so use relative path
        const response = await api.get('/workouts', {
          params: {
            userId: user.id,
            month: currentMonth.format('YYYY-MM'),
            categories: selectedCategories.join(','), // Optionally filter by categories
            muscleGroup: selectedMuscleGroup !== 'All' ? selectedMuscleGroup : undefined, // Optional filter
          },
        });

        // Expected response structure:
        // {
        //   Cardio: { '2023-10-01': { duration, calories, heartRate, PR }, ... },
        //   StrengthTraining: { '2023-10-01': { volume, reps, sets, weight, calories, muscleGroup, PR }, ... },
        //   Flexibility: { '2023-10-01': { duration, calories, recoveryLevel, PR }, ... },
        // }

        setWorkoutData(response.data);
      } catch (error) {
        console.error('Error fetching workout data:', error);
        Alert.alert('Error', 'Failed to fetch workout data.');
        setWorkoutData({});
      } finally {
        setLoading(false);
      }
    };

    fetchWorkoutData();
  }, [user, currentMonth, selectedCategories, selectedMuscleGroup, api]);

  // Handler for category selection
  const toggleCategory = (category) => {
    if (selectedCategories.includes(category)) {
      setSelectedCategories(selectedCategories.filter((cat) => cat !== category));
    } else {
      setSelectedCategories([...selectedCategories, category]);
    }
  };

  // Handler for month navigation
  const changeMonth = (direction) => {
    if (direction === 'prev') {
      setCurrentMonth(currentMonth.clone().subtract(1, 'month'));
    } else if (direction === 'next') {
      setCurrentMonth(currentMonth.clone().add(1, 'month'));
    }
  };

  // Function to get color based on category and data
  const getColorForDate = (date, category) => {
    const dateStr = date.format('YYYY-MM-DD');
    const data = workoutData[category]?.[dateStr];

    if (!data) {
      return theme.colors.disabled; // No activity
    }

    switch (category) {
      case 'Cardio':
        if (data.duration <= 20) return '#AEDFF7';
        if (data.duration <= 40) return '#5CB1F6';
        return '#2A6EBB';
      case 'StrengthTraining':
        if (data.volume <= 100) return '#C2FFD8';
        if (data.volume <= 200) return '#6EE7B7';
        return '#118D6E';
      case 'Flexibility':
        if (data.duration <= 20) return '#D7B0E0';
        if (data.duration <= 40) return '#A569BD';
        return '#6A1B9A';
      default:
        return theme.colors.disabled;
    }
  };

  // Function to check if a date has a PR
  const isPR = (dateStr) => {
    for (let category of selectedCategories) {
      if (workoutData[category]?.[dateStr]?.PR) {
        return true;
      }
    }
    return false;
  };

  // Function to filter data based on selected muscle group
  const filterDataByMuscleGroup = (category, dateStr) => {
    if (selectedMuscleGroup === 'All') return true;
    if (category !== 'StrengthTraining') return true; // Only StrengthTraining has muscle groups
    return workoutData[category][dateStr]?.muscleGroup === selectedMuscleGroup;
  };

  // Function to accumulate data for a specific date across selected categories
  const getAggregatedData = (date) => {
    const dateStr = date.format('YYYY-MM-DD');
    const aggregated = [];

    selectedCategories.forEach((category) => {
      if (
        workoutData[category]?.[dateStr] &&
        filterDataByMuscleGroup(category, dateStr)
      ) {
        aggregated.push({ category, data: workoutData[category][dateStr] });
      }
    });

    return aggregated;
  };

  // Helper function to get category color for tooltip indicators
  const getCategoryColor = (category) => {
    switch (category) {
      case 'Cardio':
        return '#5CB1F6';
      case 'StrengthTraining':
        return '#6EE7B7';
      case 'Flexibility':
        return '#A569BD';
      default:
        return theme.colors.primary;
    }
  };

  // Helper function to format metrics text based on category
  const getMetricsText = (entry) => {
    switch (entry.category) {
      case 'Cardio':
        return `Duration: ${entry.data.duration}m, Calories: ${entry.data.calories}`;
      case 'StrengthTraining':
        return `Volume: ${entry.data.volume}, Reps: ${entry.data.reps}, Sets: ${entry.data.sets}, Weight: ${entry.data.weight}kg, Calories: ${entry.data.calories}`;
      case 'Flexibility':
        return `Duration: ${entry.data.duration}m, Calories: ${entry.data.calories}`;
      default:
        return '';
    }
  };

  return (
    <View style={styles.container}>
      {/* Month Navigation */}
      <View style={styles.monthNavigation}>
        <TouchableOpacity
          onPress={() => changeMonth('prev')}
          accessibilityLabel="Navigate to previous month"
          accessibilityRole="button"
        >
          <Text style={[styles.navButton, { color: theme.colors.primary }]}>←</Text>
        </TouchableOpacity>
        <Text style={[styles.monthLabel, { color: theme.colors.text }]}>
          {currentMonth.format('MMMM YYYY')}
        </Text>
        <TouchableOpacity
          onPress={() => changeMonth('next')}
          accessibilityLabel="Navigate to next month"
          accessibilityRole="button"
        >
          <Text style={[styles.navButton, { color: theme.colors.primary }]}>→</Text>
        </TouchableOpacity>
      </View>

      {/* Category Toggle Buttons */}
      <View style={styles.categoryContainer}>
        {workoutCategories.map((category) => (
          <TouchableOpacity
            key={category}
            style={[
              styles.categoryButton,
              {
                backgroundColor: selectedCategories.includes(category)
                  ? theme.colors.primary
                  : theme.colors.disabled,
              },
            ]}
            onPress={() => toggleCategory(category)}
            accessibilityLabel={`Toggle ${category}`}
            accessibilityRole="button"
          >
            <Text style={styles.categoryButtonText}>{category}</Text>
          </TouchableOpacity>
        ))}
      </View>

      {/* Muscle Group Picker */}
      {selectedCategories.includes('StrengthTraining') && (
        <View style={styles.pickerContainer}>
          <Text style={[styles.pickerLabel, { color: theme.colors.text }]}>
            Muscle Group:
          </Text>
          <Picker
            selectedValue={selectedMuscleGroup}
            style={[styles.picker, { color: theme.colors.text }]}
            onValueChange={(itemValue) => setSelectedMuscleGroup(itemValue)}
            mode="dropdown"
          >
            {muscleGroups.map((group) => (
              <Picker.Item label={group} value={group} key={group} />
            ))}
          </Picker>
        </View>
      )}

      {/* Loading Indicator */}
      {loading ? (
        <ActivityIndicator size="large" color={theme.colors.primary} style={{ marginTop: 20 }} />
      ) : (
        <ScrollView
          horizontal={false}
          contentContainerStyle={styles.heatmapContainer}
        >
          {/* Calendar Heatmap */}
          <Svg
            width={width - 40}
            height={(CELL_SIZE + CELL_MARGIN) * dateMatrix.length + 40}
            style={styles.heatmap}
          >
            {dateMatrix.map((week, weekIndex) =>
              week.map((date, dayIndex) => {
                const x = dayIndex * (CELL_SIZE + CELL_MARGIN);
                const y = weekIndex * (CELL_SIZE + CELL_MARGIN);
                const isCurrentMonth = date.month() === currentMonth.month();
                const aggregatedData = getAggregatedData(date);
                const dateStr = date.format('YYYY-MM-DD');
                const hasPR = isPR(dateStr);
                const hasData = aggregatedData.length > 0;

                // Calculate color based on multiple categories
                let fillColor = theme.colors.disabled;
                if (hasData) {
                  // Prioritize Cardio > StrengthTraining > Flexibility
                  if (
                    selectedCategories.includes('Cardio') &&
                    workoutData.Cardio?.[dateStr] &&
                    filterDataByMuscleGroup('Cardio', dateStr)
                  ) {
                    fillColor = getColorForDate(date, 'Cardio');
                  } else if (
                    selectedCategories.includes('StrengthTraining') &&
                    workoutData.StrengthTraining?.[dateStr] &&
                    filterDataByMuscleGroup('StrengthTraining', dateStr)
                  ) {
                    fillColor = getColorForDate(date, 'StrengthTraining');
                  } else if (
                    selectedCategories.includes('Flexibility') &&
                    workoutData.Flexibility?.[dateStr]
                  ) {
                    fillColor = getColorForDate(date, 'Flexibility');
                  }
                }

                return (
                  <G key={dateStr}>
                    <TouchableOpacity
                      onPress={() => {
                        const data = getAggregatedData(date);
                        setTooltipData({
                          date: date.format('MMMM Do YYYY'),
                          data,
                        });
                      }}
                      accessible={true}
                      accessibilityLabel={`Workout on ${date.format('MMMM Do YYYY')}`}
                      accessibilityRole="button"
                    >
                      <Rect
                        x={x}
                        y={y}
                        width={CELL_SIZE}
                        height={CELL_SIZE}
                        fill={isCurrentMonth ? fillColor : theme.colors.disabled}
                        rx={4}
                        ry={4}
                      />
                      <SvgText
                        x={x + CELL_SIZE / 2}
                        y={y + CELL_SIZE / 2 + 4}
                        fontSize={10}
                        fill={theme.colors.text}
                        textAnchor="middle"
                      >
                        {date.date()}
                      </SvgText>
                      {hasPR && (
                        <Circle
                          cx={x + CELL_SIZE - 6}
                          cy={y + 6}
                          r={4}
                          fill="gold"
                        />
                      )}
                    </TouchableOpacity>
                  </G>
                );
              })
            )}
          </Svg>
        </ScrollView>
      )}

      {/* Tooltip for Detailed Information */}
      <Modal
        visible={tooltipData !== null}
        transparent={true}
        animationType="fade"
        onRequestClose={() => setTooltipData(null)}
      >
        {tooltipData && (
          <TouchableOpacity
            style={styles.modalOverlay}
            activeOpacity={1}
            onPressOut={() => setTooltipData(null)}
            accessible={false}
          >
            <View style={[styles.tooltip, { backgroundColor: theme.colors.surface }]}>
              <Text style={[styles.tooltipTitle, { color: theme.colors.text }]}>
                {tooltipData.date}
              </Text>
              <ScrollView>
                {tooltipData.data.map((entry, index) => (
                  <View key={index} style={styles.tooltipEntry}>
                    <View
                      style={[
                        styles.colorIndicator,
                        { backgroundColor: getCategoryColor(entry.category) },
                      ]}
                    />
                    <Text style={[styles.tooltipText, { color: theme.colors.text }]}>
                      {entry.category}: {getMetricsText(entry)}
                      {entry.data.PR && (
                        <Text style={styles.prText}> ★ PR</Text>
                      )}
                    </Text>
                  </View>
                ))}
              </ScrollView>
              <TouchableOpacity
                onPress={() => setTooltipData(null)}
                style={styles.closeButton}
                accessibilityLabel="Close Details"
                accessibilityRole="button"
              >
                <Text
                  style={[
                    styles.closeButtonText,
                    { color: theme.colors.primary },
                  ]}
                >
                  Close
                </Text>
              </TouchableOpacity>
            </View>
          </TouchableOpacity>
        )}
      </Modal>
    </View>
  );
};

/**
 * Helper function to get category colors for tooltip indicators
 */
const getCategoryColor = (category) => {
  switch (category) {
    case 'Cardio':
      return '#5CB1F6';
    case 'StrengthTraining':
      return '#6EE7B7';
    case 'Flexibility':
      return '#A569BD';
    default:
      return '#000';
  }
};

/**
 * Helper function to format metrics text based on category
 */
const getMetricsText = (entry) => {
  switch (entry.category) {
    case 'Cardio':
      return `Duration: ${entry.data.duration}m, Calories: ${entry.data.calories}`;
    case 'StrengthTraining':
      return `Volume: ${entry.data.volume}, Reps: ${entry.data.reps}, Sets: ${entry.data.sets}, Weight: ${entry.data.weight}kg, Calories: ${entry.data.calories}`;
    case 'Flexibility':
      return `Duration: ${entry.data.duration}m, Calories: ${entry.data.calories}`;
    default:
      return '';
  }
};

const styles = StyleSheet.create({
  container: {
    marginVertical: 20,
    alignItems: 'center',
  },
  monthNavigation: {
    flexDirection: 'row',
    alignItems: 'center',
    marginBottom: 10,
  },
  navButton: {
    fontSize: 24,
    marginHorizontal: 20,
  },
  monthLabel: {
    fontSize: 18,
    fontWeight: 'bold',
  },
  categoryContainer: {
    flexDirection: 'row',
    marginBottom: 10,
    justifyContent: 'center',
  },
  categoryButton: {
    paddingVertical: 6,
    paddingHorizontal: 12,
    borderRadius: 20,
    marginHorizontal: 5,
  },
  categoryButtonText: {
    color: '#fff',
    fontSize: 14,
  },
  pickerContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    marginBottom: 10,
  },
  pickerLabel: {
    marginRight: 10,
    fontSize: 16,
  },
  picker: {
    height: 50,
    width: 150,
  },
  heatmapContainer: {
    alignItems: 'center',
  },
  heatmap: {
    overflow: 'visible',
  },
  tooltip: {
    width: '80%',
    maxHeight: '80%',
    padding: 20,
    borderRadius: 8,
    elevation: 5,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.25,
    shadowRadius: 3.84,
  },
  tooltipTitle: {
    fontSize: 16,
    fontWeight: 'bold',
    marginBottom: 10,
    textAlign: 'center',
  },
  tooltipEntry: {
    flexDirection: 'row',
    alignItems: 'center',
    marginBottom: 10,
  },
  colorIndicator: {
    width: 12,
    height: 12,
    borderRadius: 6,
    marginRight: 8,
  },
  tooltipText: {
    fontSize: 14,
    flex: 1,
    flexWrap: 'wrap',
  },
  prText: {
    color: 'gold',
    fontWeight: 'bold',
  },
  closeButton: {
    marginTop: 10,
    alignSelf: 'flex-end',
  },
  closeButtonText: {
    fontSize: 14,
    fontWeight: 'bold',
  },
  modalOverlay: {
    flex: 1,
    backgroundColor: 'rgba(0,0,0,0.3)',
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  noDataText: {
    marginTop: 20,
    fontSize: 16,
    color: 'gray',
  },
});

export default WorkoutHeatmap;

// context/AuthContext.js

import React, { createContext, useState, useEffect } from 'react';
import * as SecureStore from 'expo-secure-store';
import { Alert } from 'react-native';
import jwtDecode from 'jwt-decode'; // Ensure correct import
import useApi from '../services/api'; // Import the custom Axios hook

export const AuthContext = createContext();

/**
 * AuthProvider Component
 * Provides authentication context to the application.
 */
export const AuthProvider = ({ children }) => {
  const [authToken, setAuthToken] = useState(null);
  const [user, setUser] = useState(null); // Manage user object
  const [loading, setLoading] = useState(true); // Loading state to manage asynchronous operations

  const SIGNIN_KEY = 'authToken';

  const api = useApi(); // Use the custom Axios instance

  /**
   * Function to handle user sign-in
   * @param {String} token - JWT token received from the backend
   */
  const signIn = async (token) => {
    try {
      if (token && token.split('.').length === 3) { // Basic JWT structure validation
        setAuthToken(token);
        await SecureStore.setItemAsync(SIGNIN_KEY, token);
        console.log('Token stored successfully:', token); // Debugging

        // Decode the token to extract user information
        const decoded = jwtDecode(token);
        console.log('Decoded Token:', decoded); // Verify decoded data

        // Adjust according to your token payload
        setUser({
          id: decoded.userId || decoded.id, // Adjust based on your token's structure
          name: decoded.name || null,
          email: decoded.email || null,
        });
      } else {
        throw new Error('Invalid JWT token');
      }
    } catch (error) {
      console.error('Error during sign-in:', error);
      Alert.alert('Authentication Error', error.message || 'Failed to authenticate.');
    }
  };

  /**
   * Function to handle user sign-out
   */
  const signOut = async () => {
    try {
      setAuthToken(null);
      setUser(null);
      await SecureStore.deleteItemAsync(SIGNIN_KEY);
      console.log('Token removed successfully.');

      // Optionally, navigate to the login screen or reset navigation stack
    } catch (error) {
      console.error('Error during sign-out:', error);
      Alert.alert('Error', 'Failed to log out.');
    }
  };

  /**
   * Function to load the token from SecureStore on app start
   */
  const loadToken = async () => {
    try {
      const token = await SecureStore.getItemAsync(SIGNIN_KEY);
      if (token && token.split('.').length === 3) { // Basic JWT structure validation
        setAuthToken(token);
        console.log('Token loaded from SecureStore:', token); // Debugging

        // Decode the token to extract user information
        const decoded = jwtDecode(token);
        console.log('Decoded Token:', decoded); // Verify decoded data

        setUser({
          id: decoded.userId || decoded.id, // Adjust based on your token's structure
          name: decoded.name || null,
          email: decoded.email || null,
        });
      } else if (token) {
        console.warn('Stored token is invalid. Clearing it.');
        await SecureStore.deleteItemAsync(SIGNIN_KEY);
      } else {
        console.log('No token found.');
      }
    } catch (e) {
      console.log('Failed to load token:', e);
      Alert.alert('Loading Error', 'Failed to load authentication token.');
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    loadToken();
  }, []);

  return (
    <AuthContext.Provider value={{ authToken, user, loading, signIn, signOut }}>
      {!loading && children}
    </AuthContext.Provider>
  );
};