// SPDX-FileCopyrightText: © 2025 Nøkken.io <nokken.io@proton.me>
// SPDX-License-Identifier: AGPL-3.0
//
//  calendar_screen.dart
//  Monthly calendar view with medication schedule visualization and mood tracking
//
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:nokken/src/core/ui/widgets/shared_widgets.dart';
import 'package:nokken/src/core/utils/date_time_formatter.dart';
import 'package:nokken/src/core/utils/get_icons_colors.dart';
import 'package:table_calendar/table_calendar.dart';
import 'package:nokken/src/features/medication_tracker/models/medication.dart';
import 'package:nokken/src/features/medication_tracker/models/medication_dose.dart';
import 'package:nokken/src/features/scheduler/services/medication_schedule_service.dart';
import 'package:nokken/src/features/medication_tracker/providers/medication_taken_provider.dart';
import 'package:nokken/src/features/bloodwork_tracker/models/bloodwork.dart';
import 'package:nokken/src/features/bloodwork_tracker/providers/bloodwork_state.dart';
import 'package:nokken/src/features/mood_tracker/models/mood_entry.dart';
import 'package:nokken/src/features/mood_tracker/providers/mood_state.dart';
import 'package:nokken/src/features/mood_tracker/widgets/mood_field_chips.dart';
import 'package:nokken/src/features/mood_tracker/utils/mood_utils.dart';
import 'package:nokken/src/features/mood_tracker/screens/mood_tracker_screen.dart';
import 'package:nokken/src/features/scheduler/screens/year_screen.dart';
import 'package:nokken/src/core/services/database/database_service.dart';
import 'package:nokken/src/core/services/navigation/navigation_service.dart';
import 'package:nokken/src/core/ui/theme/app_icons.dart';
import 'package:nokken/src/core/ui/theme/app_theme.dart';
import 'package:nokken/src/core/ui/theme/app_colors.dart';
import 'package:nokken/src/core/ui/theme/app_text_styles.dart';
import 'package:nokken/src/core/utils/get_labels.dart';
import 'package:nokken/src/core/utils/list_extensions.dart';
import 'package:nokken/src/core/constants/date_constants.dart';
import 'package:nokken/src/features/scheduler/widgets/calendar_day_cell.dart';
import 'package:nokken/src/features/scheduler/providers/calendar_event_tracker.dart';

//==============================================================================
// PROVIDERS & MODELS
//==============================================================================

/// Provider to track the current calendar view mode (medical or mood)
final calendarViewModeProvider =
    StateProvider<CalendarViewMode>((ref) => CalendarViewMode.medical);

/// Enum to track calendar view mode
enum CalendarViewMode {
  medical,
  mood,
}

//==============================================================================
// MAIN CALENDAR SCREEN
//==============================================================================

/// Main calendar screen that provides a monthly view of medications and mood entries
///
/// Displays a calendar with visual indicators for medication schedules and mood entries.
/// Users can toggle between medical and mood views to focus on different aspects of their data.
class CalendarScreen extends ConsumerStatefulWidget {
  const CalendarScreen({super.key});

  @override
  ConsumerState<CalendarScreen> createState() => _CalendarScreenState();
}

class _CalendarScreenState extends ConsumerState<CalendarScreen> {
  DateTime _selectedDay = DateTime.now();
  bool _isLoading = true;

  final ScrollController _scrollController = ScrollController();

  //----------------------------------------------------------------------------
  // LIFECYCLE METHODS
  //----------------------------------------------------------------------------

  @override
  void initState() {
    super.initState();
    _loadMedicationsFromDB();

    // Load taken medications after first build
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _loadTakenMedicationsForSelectedDay();
    });
  }

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

  //----------------------------------------------------------------------------
  // DATA LOADING METHODS
  //----------------------------------------------------------------------------

  /// Loads taken medications for the selected day from the database
  void _loadTakenMedicationsForSelectedDay() {
    // Use normalized date for consistency with MedicationDose model
    final normalizedDate = DateTimeFormatter.normalizeDate(_selectedDay);
    ref
        .read(medicationTakenProvider.notifier)
        .loadTakenMedicationsForDate(normalizedDate);
  }

  /// Loads all medications from the database
  ///
  /// Handles error states and updates UI accordingly
  Future<void> _loadMedicationsFromDB() async {
    try {
      setState(() {
        _isLoading = true;
      });

      final dbService = DatabaseService();
      final medications = await dbService.getAllMedications();

      // Sort medications by their first time slot
      final sortedMedications =
          MedicationScheduleService.sortMedicationsByTimeOfDay(medications);

      // Update the medications provider
      ref.read(medicationsProvider.notifier).state = sortedMedications;

      setState(() {
        _isLoading = false;
      });
    } catch (e) {
      // Handle database errors gracefully
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text('Failed to load medications: ${e.toString()}'),
            backgroundColor: AppColors.error,
          ),
        );
      }

      setState(() {
        _isLoading = false;
      });
    }
  }

  /// Filters medications to show only those scheduled for the selected day
  ///
  /// Uses the MedicationScheduleService to determine which medications
  /// should appear on the selected day based on their schedules
  List<Medication> _getMedicationsForSelectedDay() {
    final allMedications = ref.watch(medicationsProvider);
    final medicationsForDay = MedicationScheduleService.getMedicationsForDate(
        allMedications, _selectedDay);

    // Sort medications by time
    return MedicationScheduleService.sortMedicationsByTimeOfDay(
        medicationsForDay);
  }

  /// Gets bloodwork records for the selected day
  List<Bloodwork> _getBloodworkForSelectedDay() {
    final bloodworkRecords = ref.watch(bloodworkRecordsProvider);
    return bloodworkRecords.where((record) {
      // Compare just the date part (not time)
      final recordDate = DateTimeFormatter.normalizeDate(record.date);
      final selectedDate = DateTimeFormatter.normalizeDate(_selectedDay);
      return recordDate.isAtSameMomentAs(selectedDate);
    }).toList();
  }

  //----------------------------------------------------------------------------
  // NAVIGATION METHODS
  //----------------------------------------------------------------------------

  /// Navigates to the previous month and updates the calendar view
  void _navigateToPreviousMonth() {
    final previousMonth =
        DateTime(_selectedDay.year, _selectedDay.month - 1, 1);

    // Determine day (handle cases where the current day doesn't exist in the previous month)
    int day = _selectedDay.day;
    final daysInPreviousMonth =
        DateTime(_selectedDay.year, _selectedDay.month, 0).day;
    if (day > daysInPreviousMonth) {
      day = daysInPreviousMonth;
    }

    final previousDate = DateTime(previousMonth.year, previousMonth.month, day);

    setState(() {
      _selectedDay = previousDate;
    });
    _loadTakenMedicationsForSelectedDay();

    // Update the calendar focus using the key
    if (_calendarKey.currentState != null) {
      _calendarKey.currentState!.updateCalendarFocus(previousDate);
    }
  }

  /// Navigates to the next month and updates the calendar view
  void _navigateToNextMonth() {
    final nextMonth = DateTime(_selectedDay.year, _selectedDay.month + 1, 1);

    // Determine day (handle cases where the current day doesn't exist in the next month)
    int day = _selectedDay.day;
    final daysInNextMonth =
        DateTime(_selectedDay.year, _selectedDay.month + 2, 0).day;
    if (day > daysInNextMonth) {
      day = daysInNextMonth;
    }

    final nextDate = DateTime(nextMonth.year, nextMonth.month, day);

    setState(() {
      _selectedDay = nextDate;
    });
    _loadTakenMedicationsForSelectedDay();

    // Update the calendar focus using the key
    if (_calendarKey.currentState != null) {
      _calendarKey.currentState!.updateCalendarFocus(nextDate);
    }
  }

  // Global key for accessing the calendar state
  final GlobalKey<MedicationCalendarViewState> _calendarKey = GlobalKey();

  /// Navigates to the year view screen and handles the return date selection
  void _navigateToYearView() async {
    final selectedDate = await Navigator.of(context).push<DateTime>(
      MaterialPageRoute(
        builder: (context) => YearScreen(
          initialDate: _selectedDay,
        ),
      ),
    );

    // If a date was selected in the year view, update the current selected day
    if (selectedDate != null) {
      setState(() {
        _selectedDay = selectedDate;
      });
      _loadTakenMedicationsForSelectedDay();

      // Update the calendar focus using the key
      if (_calendarKey.currentState != null) {
        _calendarKey.currentState!.updateCalendarFocus(selectedDate);
      }
    }
  }

  /// Navigates to the mood tracker screen and handles return
  void _navigateToMoodTracker(
      BuildContext context, MoodEntry? existingEntry) async {
    await Navigator.of(context).push(
      MaterialPageRoute(
        builder: (context) => MoodTrackerScreen(
          selectedDate: _selectedDay,
          existingEntry: existingEntry,
        ),
      ),
    );

    // Reload mood entries when returning
    if (ref.exists(moodStateProvider)) {
      ref.read(moodStateProvider.notifier).loadMoodEntries();
    }
  }

  //----------------------------------------------------------------------------
  // UI BUILDING METHODS
  //----------------------------------------------------------------------------

  @override
  Widget build(BuildContext context) {
    // Get the current view mode
    final viewMode = ref.watch(calendarViewModeProvider);

    return Scaffold(
      appBar: AppBar(
        automaticallyImplyLeading: false,
        title: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            IconButton(
              icon: Icon(AppIcons.getIcon('chevron_left')),
              onPressed: _navigateToPreviousMonth,
            ),
            Text(
              '${DateConstants.months[_selectedDay.month - 1]} ${_selectedDay.year}',
              style: AppTextStyles.titleLarge,
            ),
            IconButton(
              icon: Icon(AppIcons.getIcon('chevron_right')),
              onPressed: _navigateToNextMonth,
            ),
          ],
        ),
        elevation: 0,
        leading: IconButton(
            onPressed: () => NavigationService.goBack(context),
            icon: Icon(AppIcons.getIcon('schedule'))),
        actions: [
          TextButton(
              onPressed: _navigateToYearView,
              child: Text(
                'Year View',
                style: AppTextStyles.titleMedium,
              )),
        ],
      ),
      body: _isLoading
          ? const Center(child: CircularProgressIndicator())
          : Scrollbar(
              controller: _scrollController,
              child: SingleChildScrollView(
                controller: _scrollController,
                child: Column(
                  children: [
                    // View mode tabs
                    _buildViewModeTabs(),

                    // Calendar component
                    MedicationCalendar(
                      calendarViewKey: _calendarKey,
                      onDaySelected: (day) {
                        setState(() {
                          _selectedDay = day;
                        });
                        // Load taken medications when day changes
                        _loadTakenMedicationsForSelectedDay();
                      },
                    ),

                    const Divider(),

                    // Display content for selected day based on view mode
                    viewMode == CalendarViewMode.medical
                        ? _buildMedicationsListContent()
                        : _buildMoodContent(),
                  ],
                ),
              ),
            ),
    );
  }

  /// Builds tabs for switching between medical and mood views
  Widget _buildViewModeTabs() {
    final viewMode = ref.watch(calendarViewModeProvider);

    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
      child: Row(
        children: [
          Expanded(
            child: _buildViewModeTab(
              context,
              icon: Icons.medication,
              label: 'Medical',
              isSelected: viewMode == CalendarViewMode.medical,
              onTap: () {
                ref.read(calendarViewModeProvider.notifier).state =
                    CalendarViewMode.medical;
              },
            ),
          ),
          SharedWidgets.horizontalSpace(8),
          Expanded(
            child: _buildViewModeTab(
              context,
              icon: Icons.mood,
              label: 'Mood',
              isSelected: viewMode == CalendarViewMode.mood,
              onTap: () {
                ref.read(calendarViewModeProvider.notifier).state =
                    CalendarViewMode.mood;
              },
            ),
          ),
        ],
      ),
    );
  }

  /// Builds a single view mode tab
  Widget _buildViewModeTab(
    BuildContext context, {
    required IconData icon,
    required String label,
    required bool isSelected,
    required VoidCallback onTap,
  }) {
    return Material(
      color: isSelected ? AppColors.primary : AppColors.surfaceContainer,
      borderRadius: BorderRadius.circular(8),
      child: InkWell(
        onTap: onTap,
        borderRadius: BorderRadius.circular(8),
        child: Padding(
          padding: const EdgeInsets.symmetric(vertical: 12),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Icon(
                icon,
                color: isSelected ? AppColors.onPrimary : AppColors.onSurface,
                size: 20,
              ),
              SharedWidgets.horizontalSpace(8),
              Text(
                label,
                style: TextStyle(
                  color: isSelected ? AppColors.onPrimary : AppColors.onSurface,
                  fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  /// Builds the mood content section for the selected day
  Widget _buildMoodContent() {
    final formattedDate = DateTimeFormatter.formatDateMMMDDYYYY(_selectedDay);

    // Check if there's a mood entry for this day
    final moodEntries = ref.watch(moodEntriesProvider);
    final normalizedDate = DateTimeFormatter.normalizeDate(_selectedDay);

    final moodEntry = moodEntries.firstWhereOrNull(
      (entry) => DateTimeFormatter.normalizeDate(entry.date)
          .isAtSameMomentAs(normalizedDate),
    );

    final bool hasMoodEntry = moodEntry != null;

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Padding(
          padding: const EdgeInsets.fromLTRB(16, 16, 16, 8),
          child: Text(
            formattedDate,
            style: Theme.of(context).textTheme.titleMedium,
          ),
        ),

        // Container with minimum height to ensure it's still visible when empty
        Container(
          constraints: const BoxConstraints(minHeight: 100),
          child: !hasMoodEntry
              ? Center(
                  child: Padding(
                    padding: const EdgeInsets.all(32.0),
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Text(
                          'No data for $formattedDate',
                          style: Theme.of(context).textTheme.titleMedium,
                        ),
                        SharedWidgets.verticalSpace(AppTheme.doubleSpacing),
                        ElevatedButton.icon(
                          icon: Icon(AppIcons.getIcon('add')),
                          label: const Text('Add Entry'),
                          onPressed: () =>
                              _navigateToMoodTracker(context, moodEntry),
                        ),
                      ],
                    ),
                  ),
                )
              : _buildMoodEntryCard(context, moodEntry),
        ),
      ],
    );
  }

  /// Builds a card displaying the mood entry with details
  Widget _buildMoodEntryCard(BuildContext context, MoodEntry moodEntry) {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 16),
      child: Card(
        child: InkWell(
          onTap: () => _navigateToMoodTracker(context, moodEntry),
          child: Padding(
            padding: AppTheme.standardCardPadding,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                // Mood display
                Row(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      moodEntry.mood.emoji,
                      style: const TextStyle(
                          fontSize: 32, fontFamily: AppTheme.emojiStyle),
                    ),
                    SharedWidgets.horizontalSpace(AppTheme.doubleSpacing),
                    Expanded(
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text(
                            moodEntry.mood.displayName,
                            style: AppTextStyles.titleLarge.copyWith(
                              color: MoodUtils.getMoodColor(moodEntry.mood),
                              fontWeight: FontWeight.bold,
                            ),
                          ),
                          SharedWidgets.verticalSpace(),
                          Wrap(
                            spacing: 8.0, // Space between chips
                            runSpacing: 4.0, // Space between lines
                            children:
                                MoodFieldChips.buildMoodFieldChips(moodEntry),
                          ),
                        ],
                      ),
                    ),
                  ],
                ),

                SharedWidgets.verticalSpace(AppTheme.doubleSpacing),

                // Notes display
                if (moodEntry.notes != null && moodEntry.notes!.isNotEmpty) ...[
                  Text(
                    'Notes:',
                    style: AppTextStyles.titleMedium,
                  ),
                  SharedWidgets.verticalSpace(AppTheme.spacing),
                  Container(
                    padding: const EdgeInsets.all(12),
                    decoration: BoxDecoration(
                      color: AppColors.surfaceContainer,
                      borderRadius: BorderRadius.circular(8),
                    ),
                    child: Text(moodEntry.notes!),
                  ),
                ],
              ],
            ),
          ),
        ),
      ),
    );
  }

  /// Builds the list of medications and bloodwork for the selected day
  Widget _buildMedicationsListContent() {
    final medicationsForDay = _getMedicationsForSelectedDay();
    final bloodworkForDay = _getBloodworkForSelectedDay();
    final formattedDate = DateTimeFormatter.formatDateDDMMYY(_selectedDay);

    final bool hasItems =
        bloodworkForDay.isNotEmpty || medicationsForDay.isNotEmpty;

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Padding(
          padding: const EdgeInsets.fromLTRB(16, 16, 16, 8),
          child: Text(
            DateTimeFormatter.formatDateMMMDDYYYY(_selectedDay),
            style: Theme.of(context).textTheme.titleMedium,
          ),
        ),
        // Container with minimum height to ensure it's still visible when empty
        Container(
          constraints: const BoxConstraints(minHeight: 200),
          padding: const EdgeInsets.only(bottom: 24),
          child: !hasItems
              ? Center(
                  child: Padding(
                    padding: const EdgeInsets.all(32.0),
                    child: Text(
                      'Nothing scheduled for $formattedDate',
                      style: Theme.of(context).textTheme.titleMedium,
                    ),
                  ),
                )
              : Column(
                  children: [
                    // Bloodwork records first
                    ...bloodworkForDay.map((bloodwork) => Padding(
                          padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
                          child: _buildBloodworkCard(bloodwork),
                        )),

                    // Then medications
                    ...medicationsForDay.map((medication) => Padding(
                          padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
                          child: _buildMedicationCard(medication),
                        )),
                  ],
                ),
        ),
      ],
    );
  }

  /// Builds a card for an individual bloodwork/appointment record
  Widget _buildBloodworkCard(Bloodwork bloodwork) {
    final isDateInFuture = DateTimeFormatter.normalizeDate(bloodwork.date)
        .isAfter(DateTimeFormatter.normalizeDate(DateTime.now()));

    // Format the appointment time
    final timeOfDay = TimeOfDay.fromDateTime(bloodwork.date);
    final formattedTimeString = DateTimeFormatter.formatTimeToAMPM(timeOfDay);
    final timeIcon = DateTimeFormatter.getTimeIcon(formattedTimeString);

    return Card(
      margin: const EdgeInsets.only(bottom: 16),
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // Appointment type icon
            GetIconsColors.getAppointmentIconWithColor(
                bloodwork.appointmentType),

            SharedWidgets.verticalSpace(AppTheme.doubleSpacing),

            // Appointment details
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  InkWell(
                    onTap: () => NavigationService.goToBloodworkAddEdit(
                      context,
                      bloodwork: bloodwork,
                    ),
                    child: Row(
                      children: [
                        Text(
                          GetLabels.getAppointmentTypeText(
                              bloodwork.appointmentType),
                          style: AppTextStyles.titleLarge,
                        ),
                        if (isDateInFuture) ...[
                          SharedWidgets.horizontalSpace(),
                          Container(
                            padding: const EdgeInsets.symmetric(
                                horizontal: 8, vertical: 2),
                            decoration: BoxDecoration(
                              color: AppColors.info.withAlpha(20),
                              borderRadius: BorderRadius.circular(12),
                              border: Border.all(
                                  color: AppColors.info.withAlpha(60)),
                            ),
                            child: Text(
                              'Scheduled',
                              style: TextStyle(
                                fontSize: 12,
                                color: AppColors.info,
                                fontWeight: FontWeight.w500,
                              ),
                            ),
                          ),
                        ],
                      ],
                    ),
                  ),

                  // Display appointment time with appropriate icon
                  Padding(
                    padding: const EdgeInsets.only(top: 8.0, bottom: 8.0),
                    child: Row(
                      children: [
                        Icon(
                          timeIcon,
                          size: 16,
                          color: GetIconsColors.getAppointmentColor(
                              bloodwork.appointmentType),
                        ),
                        SharedWidgets.verticalSpace(6),
                        Text(
                          formattedTimeString,
                          style: AppTextStyles.bodyMedium.copyWith(
                            color: GetIconsColors.getAppointmentColor(
                                bloodwork.appointmentType),
                            fontWeight: FontWeight.w500,
                          ),
                        ),
                      ],
                    ),
                  ),

                  // Display location if available
                  if (bloodwork.location?.isNotEmpty == true) ...[
                    Row(
                      children: [
                        Icon(
                          AppIcons.getOutlined('location'),
                          size: 16,
                          color: AppTheme.grey,
                        ),
                        SharedWidgets.verticalSpace(6),
                        Text(
                          bloodwork.location!,
                          style: AppTextStyles.bodyMedium,
                        ),
                      ],
                    ),
                    SharedWidgets.verticalSpace(2),
                  ],

                  // Display doctor if available
                  if (bloodwork.doctor?.isNotEmpty == true) ...[
                    Row(
                      children: [
                        Icon(
                          AppIcons.getIcon('profile'),
                          size: 16,
                          color: AppTheme.grey,
                        ),
                        SharedWidgets.verticalSpace(6),
                        Text(
                          bloodwork.doctor!,
                          style: AppTextStyles.bodyMedium,
                        ),
                      ],
                    ),
                    SharedWidgets.verticalSpace(2),
                  ],

                  // If future date, show scheduled message
                  if (isDateInFuture)
                    Text(
                      'Appointment scheduled',
                      style: AppTextStyles.bodyMedium,
                    )
                  // Otherwise show hormone levels if bloodwork type
                  else if (bloodwork.appointmentType ==
                      AppointmentType.bloodwork) ...[
                    // Display hormone readings if available
                    if (bloodwork.hormoneReadings.isNotEmpty)
                      ...bloodwork.hormoneReadings.take(2).map((reading) => Text(
                          '${reading.name}: ${reading.value.toStringAsFixed(1)} ${reading.unit}',
                          overflow: TextOverflow.ellipsis)),

                    // Show count if there are more readings
                    if (bloodwork.hormoneReadings.length > 2)
                      Text(
                          '...and ${bloodwork.hormoneReadings.length - 2} more',
                          style: AppTextStyles.bodySmall),
                  ],

                  // Display notes if any
                  if (bloodwork.notes?.isNotEmpty == true) ...[
                    SharedWidgets.verticalSpace(),
                    Text(
                      'Notes: ${bloodwork.notes}',
                      style: AppTextStyles.bodySmall,
                      maxLines: 2,
                      overflow: TextOverflow.ellipsis,
                    ),
                  ],
                ],
              ),
            )
          ],
        ),
      ),
    );
  }

  /// Builds a card for an individual medication
  Widget _buildMedicationCard(Medication medication) {
    return Card(
      margin: const EdgeInsets.only(bottom: 16),
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // Medication type icon
            GetIconsColors.getMedicationIconWithColor(
                medication.medicationType),

            SharedWidgets.verticalSpace(AppTheme.doubleSpacing),

            // Medication details
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  InkWell(
                    onTap: () => NavigationService.goToMedicationDetails(
                        context,
                        medication: medication),
                    child: Text(
                      medication.name,
                      style: AppTextStyles.titleLarge,
                    ),
                  ),
                  SharedWidgets.verticalSpace(),
                  Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      // Display dosage
                      Text(
                        medication.dosage,
                        style: AppTextStyles.bodyMedium,
                      ),
                      SharedWidgets.verticalSpace(4),

                      // Display times medication is taken
                      Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          ...(() {
                            // Create a sorted copy of all time slots
                            final sortedTimes =
                                List<DateTime>.from(medication.timeOfDay);

                            // Sort all time slots
                            sortedTimes.sort((a, b) {
                              final aTimeStr =
                                  DateTimeFormatter.formatTimeToAMPM(
                                      TimeOfDay.fromDateTime(a));
                              final bTimeStr =
                                  DateTimeFormatter.formatTimeToAMPM(
                                      TimeOfDay.fromDateTime(b));
                              return DateTimeFormatter.compareTimeSlots(
                                  aTimeStr, bTimeStr);
                            });

                            // Convert each time slot to a UI element with checkmark if taken
                            return sortedTimes.map((time) {
                              // Format times consistently
                              final timeOfDay = TimeOfDay.fromDateTime(time);
                              final formattedTimeString =
                                  DateTimeFormatter.formatTimeToAMPM(timeOfDay);

                              // Create a medication dose object for checking taken status
                              final dose = MedicationDose(
                                medicationId: medication.id,
                                date: _selectedDay,
                                timeSlot: formattedTimeString,
                              );

                              // Use the provider to check if taken
                              final isTaken =
                                  ref.watch(isDoseTakenProvider(dose));

                              return Padding(
                                padding: const EdgeInsets.only(left: 0, top: 2),
                                child: Row(
                                  children: [
                                    // Add time icon
                                    Icon(
                                      DateTimeFormatter.getTimeIcon(
                                          formattedTimeString),
                                      size: 16,
                                      color: GetIconsColors.getMedicationColor(
                                          medication.medicationType),
                                    ),
                                    SharedWidgets.verticalSpace(),
                                    // Display formatted time
                                    Text(
                                      formattedTimeString,
                                      style: AppTextStyles.bodyMedium,
                                    ),
                                    // Show checkmark if taken
                                    if (isTaken)
                                      Padding(
                                        padding: const EdgeInsets.only(left: 8),
                                        child: Icon(
                                          AppIcons.getIcon('success'),
                                          color: AppColors.tertiary,
                                          size: 16,
                                        ),
                                      ),
                                  ],
                                ),
                              );
                            }).toList();
                          })(),
                        ],
                      ),
                    ],
                  ),
                ],
              ),
            )
          ],
        ),
      ),
    );
  }
}

//==============================================================================
// MEDICATION CALENDAR COMPONENT
//==============================================================================

/// Calendar widget showing medication schedules with visual indicators
///
/// Shows different colors for different types of medications and appointments
/// and different colors for different mood entries
class MedicationCalendar extends ConsumerWidget {
  final Function(DateTime) onDaySelected;
  final GlobalKey<MedicationCalendarViewState>? calendarViewKey;

  const MedicationCalendar({
    super.key,
    required this.onDaySelected,
    this.calendarViewKey,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return MedicationCalendarView(
      key: calendarViewKey,
      onDaySelected: onDaySelected,
      ref: ref,
    );
  }
}

/// Implementation of the medication calendar view
class MedicationCalendarViewState extends State<MedicationCalendarView> {
  late DateTime _focusedDay;
  late DateTime _selectedDay;

  //----------------------------------------------------------------------------
  // LIFECYCLE METHODS
  //----------------------------------------------------------------------------

  @override
  void initState() {
    super.initState();
    _focusedDay = DateTime.now();
    _selectedDay = DateTime.now();
  }

  /// Updates the calendar focus to a specific date
  void updateCalendarFocus(DateTime date) {
    setState(() {
      _selectedDay = date;
      _focusedDay = date;
    });
  }

  //----------------------------------------------------------------------------
  // UI BUILDING METHODS
  //----------------------------------------------------------------------------

  @override
  Widget build(BuildContext context) {
    // Get current view mode from provider
    final viewMode = widget.ref.watch(calendarViewModeProvider);

    // Get medication dates for the current month
    final medicationDates =
        widget.ref.watch(medicationDatesProvider(_focusedDay));

    // Get bloodwork records for appointment types
    final bloodworkRecords = widget.ref.watch(bloodworkRecordsProvider);

    return Padding(
      padding: AppTheme.standardScreenMargins,
      child: TableCalendar(
        // Calendar configuration
        firstDay: DateTime.now().subtract(const Duration(days: 365)),
        lastDay: DateTime.now().add(const Duration(days: 365)),
        focusedDay: _focusedDay,
        selectedDayPredicate: (day) =>
            DateTimeFormatter.isSameDay(_selectedDay, day),
        calendarFormat: CalendarFormat.month,
        startingDayOfWeek: StartingDayOfWeek.sunday,

        headerStyle: HeaderStyle(
          titleCentered: true,
          formatButtonVisible: false,
          leftChevronVisible: false,
          rightChevronVisible: false,
          headerMargin: EdgeInsets.zero,
          headerPadding: EdgeInsets.zero,
          titleTextStyle: const TextStyle(
            fontSize: 0,
            color: Colors.transparent,
            height: 0,
          ),
          decoration: const BoxDecoration(
            color: Colors.transparent,
          ),
        ),

        daysOfWeekHeight: 40,
        daysOfWeekStyle: DaysOfWeekStyle(
          weekdayStyle: AppTextStyles.titleSmall,
          weekendStyle: AppTextStyles.titleSmall,
        ),
        calendarStyle: CalendarStyle(
          defaultTextStyle: AppTextStyles.labelMedium,
          weekendTextStyle: AppTextStyles.labelMedium,
          // Add transparency to out-of-month days
          outsideTextStyle: AppTextStyles.labelMedium.copyWith(
            color: AppTextStyles.labelMedium.color?.withAlpha(120),
          ),

          // Today styling
          todayDecoration: BoxDecoration(
            color: AppColors.primary.withAlpha(40),
            shape: BoxShape.circle,
            border: Border.all(color: AppColors.primary, width: 1.5),
          ),
          todayTextStyle:
              TextStyle(color: AppColors.primary, fontWeight: FontWeight.bold),

          // Selected day styling
          selectedDecoration: BoxDecoration(
            color: AppColors.primary,
            shape: BoxShape.circle,
          ),
          selectedTextStyle: TextStyle(
              color: AppColors.onPrimary, fontWeight: FontWeight.bold),

          // Cell margin for better spacing
          cellMargin: const EdgeInsets.all(4),
          cellPadding: const EdgeInsets.all(0),
        ),
        onDaySelected: (selectedDay, focusedDay) {
          setState(() {
            _selectedDay = selectedDay;
            _focusedDay = focusedDay;
          });
          widget.onDaySelected(selectedDay);
        },
        onPageChanged: (focusedDay) {
          _focusedDay = focusedDay;
        },
        calendarBuilders: CalendarBuilders(
          // Default builder for regular days
          defaultBuilder: (context, day, focusedDay) {
            final normalizedDay = DateTimeFormatter.normalizeDate(day);

            // Determine cell properties based on view mode
            if (viewMode == CalendarViewMode.medical) {
              // Medical mode - check for medical events on this day
              bool hasInjection =
                  medicationDates.injectionDates[normalizedDay] ?? false;
              bool hasPatch =
                  medicationDates.patchDates[normalizedDay] ?? false;
              bool hasOral = medicationDates.oralDates[normalizedDay] ?? false;
              bool hasTopical =
                  medicationDates.topicalDates[normalizedDay] ?? false;
              AppointmentType? appointmentType =
                  medicationDates.bloodworkDates[normalizedDay];

              // Build the cell with appropriate styling
              return CalendarDayCell(
                day: day,
                isOutsideMonth: true,
                hasInjection: hasInjection,
                hasPatch: hasPatch,
                hasOral: hasOral,
                hasTopical: hasTopical,
                appointmentType: appointmentType,
                isMoodView: false,
              );
            } else {
              // Mood mode - check for mood entries on this day
              final moodRating = medicationDates.moodEntryDates[normalizedDay];

              // Build the cell with appropriate styling
              return CalendarDayCell(
                day: day,
                isOutsideMonth: true,
                moodRating: moodRating,
                isMoodView: true,
              );
            }
          },

          // Builder for selected days
          selectedBuilder: (context, day, focusedDay) {
            final normalizedDay = DateTimeFormatter.normalizeDate(day);

            // Determine cell properties based on view mode
            if (viewMode == CalendarViewMode.medical) {
              // Medical mode - check for medical events on this day
              bool hasInjection =
                  medicationDates.injectionDates[normalizedDay] ?? false;
              bool hasPatch =
                  medicationDates.patchDates[normalizedDay] ?? false;
              bool hasOral = medicationDates.oralDates[normalizedDay] ?? false;
              bool hasTopical =
                  medicationDates.topicalDates[normalizedDay] ?? false;
              AppointmentType? appointmentType =
                  medicationDates.bloodworkDates[normalizedDay];

              // Build the cell with appropriate styling
              return CalendarDayCell(
                day: day,
                isSelected: true,
                hasInjection: hasInjection,
                hasPatch: hasPatch,
                hasOral: hasOral,
                hasTopical: hasTopical,
                appointmentType: appointmentType,
                isMoodView: false,
              );
            } else {
              // Mood mode - check for mood entries on this day
              final moodRating = medicationDates.moodEntryDates[normalizedDay];

              // Build the cell with appropriate styling
              return CalendarDayCell(
                day: day,
                isSelected: true,
                moodRating: moodRating,
                isMoodView: true,
              );
            }
          },

          // Builder for today
          todayBuilder: (context, day, focusedDay) {
            final normalizedDay = DateTimeFormatter.normalizeDate(day);

            // Determine cell properties based on view mode
            if (viewMode == CalendarViewMode.medical) {
              // Medical mode - check for medical events on this day
              bool hasInjection =
                  medicationDates.injectionDates[normalizedDay] ?? false;
              bool hasPatch =
                  medicationDates.patchDates[normalizedDay] ?? false;
              bool hasOral = medicationDates.oralDates[normalizedDay] ?? false;
              bool hasTopical =
                  medicationDates.topicalDates[normalizedDay] ?? false;
              AppointmentType? appointmentType =
                  medicationDates.bloodworkDates[normalizedDay];

              // Build the cell with appropriate styling
              return CalendarDayCell(
                day: day,
                isToday: true,
                hasInjection: hasInjection,
                hasPatch: hasPatch,
                hasOral: hasOral,
                hasTopical: hasTopical,
                appointmentType: appointmentType,
                isMoodView: false,
              );
            } else {
              // Mood mode - check for mood entries on this day
              final moodRating = medicationDates.moodEntryDates[normalizedDay];

              // Build the cell with appropriate styling
              return CalendarDayCell(
                day: day,
                isToday: true,
                moodRating: moodRating,
                isMoodView: true,
              );
            }
          },

          // Builder for days outside the current month
          outsideBuilder: (context, day, focusedDay) {
            final normalizedDay = DateTimeFormatter.normalizeDate(day);

            // Determine cell properties based on view mode
            if (viewMode == CalendarViewMode.medical) {
              // Medical mode - check for medical events on this day
              bool hasInjection =
                  medicationDates.injectionDates[normalizedDay] ?? false;
              bool hasPatch =
                  medicationDates.patchDates[normalizedDay] ?? false;
              bool hasOral = medicationDates.oralDates[normalizedDay] ?? false;
              bool hasTopical =
                  medicationDates.topicalDates[normalizedDay] ?? false;
              AppointmentType? appointmentType =
                  medicationDates.bloodworkDates[normalizedDay];

              // Build the cell with appropriate styling
              return CalendarDayCell(
                day: day,
                isOutsideMonth: true,
                hasInjection: hasInjection,
                hasPatch: hasPatch,
                hasOral: hasOral,
                hasTopical: hasTopical,
                appointmentType: appointmentType,
                isMoodView: false,
              );
            } else {
              // Mood mode - check for mood entries on this day
              final moodRating = medicationDates.moodEntryDates[normalizedDay];

              // Build the cell with appropriate styling
              return CalendarDayCell(
                day: day,
                isOutsideMonth: true,
                moodRating: moodRating,
                isMoodView: true,
              );
            }
          },
        ),
      ),
    );
  }
}

/// Internal implementation of the calendar view
class MedicationCalendarView extends StatefulWidget {
  final Function(DateTime) onDaySelected;
  final WidgetRef ref;

  const MedicationCalendarView({
    super.key,
    required this.onDaySelected,
    required this.ref,
  });

  @override
  MedicationCalendarViewState createState() => MedicationCalendarViewState();
}
