// SPDX-FileCopyrightText: © 2025 Nøkken.io <nokken.io@proton.me>
// SPDX-License-Identifier: AGPL-3.0
//
//  as_needed_medication_provider.dart
//  Providers for convenient access to as-needed medications
//
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:nokken/src/core/utils/list_extensions.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/medication_tracker/providers/medication_providers.dart';
import 'package:nokken/src/features/medication_tracker/providers/medication_state.dart';
import 'package:nokken/src/core/utils/date_time_formatter.dart';

/// Provider for medications marked as "take as needed"
final asNeededMedicationsProvider = Provider<List<Medication>>((ref) {
  final allMedications = ref.watch(medicationsProvider);
  final result = allMedications.where((med) => med.asNeeded).toList();
  print("Debug - Found ${result.length} as-needed medications");
  return result;
});

/// Provider for checking if an individual medication is configured for as-needed use
final isAsNeededMedicationProvider =
    Provider.family<bool, String>((ref, medicationId) {
  final allMedications = ref.watch(medicationsProvider);
  final medication = allMedications.firstWhereOrNull(
    (med) => med.id == medicationId,
  );

  return medication?.asNeeded ?? false;
});

/// Model for as-needed doses taken on a specific day
class AsNeededDose {
  final Medication medication;
  final DateTime date;
  final String timeSlot;
  final String key; // Original key from database for deletion

  AsNeededDose({
    required this.medication,
    required this.date,
    required this.timeSlot,
    required this.key,
  });
}

/// Provider for as-needed doses taken on a specific date
final asNeededDosesForDateProvider =
    Provider.family<List<AsNeededDose>, DateTime>((ref, date) {
  final takenMedications = ref.watch(medicationTakenProvider);
  final allMedications = ref.watch(medicationsProvider);
  final asNeededMedications =
      allMedications.where((med) => med.asNeeded).toList();

  print(
      "DEBUG: Found ${asNeededMedications.length} medications marked as as-needed");
  print("DEBUG: Taken medication keys: ${takenMedications.length} keys");
  if (takenMedications.isNotEmpty) {
    print("DEBUG: Sample key: ${takenMedications.first}");
  }

  final List<AsNeededDose> asNeededDoses = [];

  // Extract as-needed doses from taken medications
  for (final key in takenMedications) {
    print("DEBUG: Processing key: $key");
    try {
      // Skip keys that don't look like our format
      if (!key.contains('-')) {
        print("DEBUG: Key doesn't contain hyphen: $key");
        continue;
      }

      // Find the ISO date part (contains 'T' character)
      final isoDateRegex = RegExp(r'\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}');
      final match = isoDateRegex.firstMatch(key);

      if (match == null) {
        print("DEBUG: No ISO date found in key: $key");
        continue;
      }

      // Get the matched date string and its position
      final dateStr = match.group(0)!;
      final dateStartIndex = match.start;

      // Everything before the date is the medication ID
      final medicationId =
          key.substring(0, dateStartIndex - 1); // -1 to remove the hyphen
      print("DEBUG: Extracted medicationId: $medicationId");

      // Find the timeSlot (after the date, before the timestamp)
      final afterDateStr = key.substring(dateStartIndex + dateStr.length + 1);
      final timeSlotEndIndex = afterDateStr.lastIndexOf('-');

      if (timeSlotEndIndex == -1) {
        print("DEBUG: No timestamp found after timeSlot: $afterDateStr");
        continue;
      }

      final timeSlot = afterDateStr.substring(0, timeSlotEndIndex);
      print("DEBUG: Extracted timeSlot: $timeSlot");

      // Find the medication
      final medication = asNeededMedications.firstWhereOrNull(
        (med) => med.id == medicationId,
      );

      if (medication == null) {
        print("DEBUG: No matching medication found for ID: $medicationId");
        continue;
      }

      print("DEBUG: Found medication: ${medication.name}");

      // Parse the date from the ISO string
      final doseDate = DateTime.parse(dateStr);
      print("DEBUG: Comparing dates - dose: $doseDate, selected: $date");

      // Compare just the date part
      if (doseDate.year == date.year &&
          doseDate.month == date.month &&
          doseDate.day == date.day) {
        print("DEBUG: Date match found! Adding to list");
        // Create an as-needed dose entry
        asNeededDoses.add(AsNeededDose(
          medication: medication,
          date: doseDate,
          timeSlot: timeSlot,
          key: key, // Store the original key for deletion
        ));
      } else {
        print("DEBUG: Date mismatch - dose: $doseDate, selected: $date");
      }
    } catch (e) {
      // Skip this entry if parsing fails
      print("DEBUG: Error parsing key $key: $e");
      continue;
    }
  }

  print("DEBUG: Final asNeededDoses count: ${asNeededDoses.length}");

  // Sort the as-needed doses by time
  asNeededDoses.sort(
      (a, b) => DateTimeFormatter.compareTimeSlots(a.timeSlot, b.timeSlot));

  return asNeededDoses;
});

/// Function to parse an as-needed dose key to get the medication dose
MedicationDose? parseDoseFromKey(String key) {
  try {
    // Use the same regex approach as in the provider for consistency
    final isoDateRegex = RegExp(r'\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}');
    final match = isoDateRegex.firstMatch(key);

    if (match == null) return null;

    // Get the matched date string and its position
    final dateStr = match.group(0)!;
    final dateStartIndex = match.start;

    // Everything before the date is the medication ID
    final medicationId =
        key.substring(0, dateStartIndex - 1); // -1 to remove the hyphen

    // Find the timeSlot (after the date, before the timestamp)
    final afterDateStr = key.substring(dateStartIndex + dateStr.length + 1);
    final timeSlotEndIndex = afterDateStr.lastIndexOf('-');

    if (timeSlotEndIndex == -1) return null;

    final timeSlot = afterDateStr.substring(0, timeSlotEndIndex);

    // Parse date
    final date = DateTime.parse(dateStr);

    // Create a dose object
    return MedicationDose(
      medicationId: medicationId,
      date: date,
      timeSlot: timeSlot,
    );
  } catch (e) {
    return null;
  }
}
