// ABOUTME: Validated date picker widget with constraints and real-time validation feedback
// ABOUTME: Provides consistent date selection with validation across all forms in the app
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

class ValidatedDatePicker extends StatefulWidget {
  final String label;
  final DateTime? initialDate;
  final DateTime? firstDate;
  final DateTime? lastDate;
  final bool isRequired;
  final ValueChanged<DateTime?>? onChanged;
  final String? Function(DateTime?)? validator;
  final List<String> warnings;
  final bool showWarnings;
  final DateFormat? dateFormat;
  final bool allowFutureDates;
  final bool showTimeSelection;

  const ValidatedDatePicker({
    super.key,
    required this.label,
    this.initialDate,
    this.firstDate,
    this.lastDate,
    this.isRequired = false,
    this.onChanged,
    this.validator,
    this.warnings = const [],
    this.showWarnings = true,
    this.dateFormat,
    this.allowFutureDates = false,
    this.showTimeSelection = false,
  });

  @override
  State<ValidatedDatePicker> createState() => _ValidatedDatePickerState();
}

class _ValidatedDatePickerState extends State<ValidatedDatePicker> {
  DateTime? _selectedDate;
  TimeOfDay? _selectedTime;
  String? _errorText;
  List<String> _currentWarnings = [];
  late DateFormat _formatter;

  @override
  void initState() {
    super.initState();
    _selectedDate = widget.initialDate;
    if (widget.showTimeSelection && widget.initialDate != null) {
      _selectedTime = TimeOfDay.fromDateTime(widget.initialDate!);
    }
    
    _formatter = widget.dateFormat ?? 
        (widget.showTimeSelection 
            ? DateFormat('MMM dd, yyyy - HH:mm')
            : DateFormat('MMM dd, yyyy'));
    
    // Initial validation
    _validateDate(_getCombinedDateTime(), showErrors: false);
  }

  DateTime? _getCombinedDateTime() {
    if (_selectedDate == null) return null;
    
    if (widget.showTimeSelection && _selectedTime != null) {
      return DateTime(
        _selectedDate!.year,
        _selectedDate!.month,
        _selectedDate!.day,
        _selectedTime!.hour,
        _selectedTime!.minute,
      );
    }
    
    return _selectedDate;
  }

  void _validateDate(DateTime? date, {required bool showErrors}) {
    String? error;
    List<String> warnings = [];
    
    // Required field validation
    if (widget.isRequired && date == null) {
      error = '${widget.label} is required';
    }
    
    if (date != null) {
      final now = DateTime.now();
      
      // Future date validation
      if (!widget.allowFutureDates && date.isAfter(now)) {
        error = '${widget.label} cannot be in the future';
      }
      
      // Range validation
      if (widget.firstDate != null && date.isBefore(widget.firstDate!)) {
        error = '${widget.label} cannot be before ${_formatter.format(widget.firstDate!)}';
      }
      
      if (widget.lastDate != null && date.isAfter(widget.lastDate!)) {
        error = '${widget.label} cannot be after ${_formatter.format(widget.lastDate!)}';
      }
      
      // Custom validation
      if (error == null && widget.validator != null) {
        error = widget.validator!(date);
      }
      
      // Warning checks
      if (widget.showWarnings) {
        // Warn if entry is more than 24 hours old
        if (date.isBefore(now.subtract(const Duration(days: 1)))) {
          final daysDifference = now.difference(date).inDays;
          warnings.add('Entry is from $daysDifference day${daysDifference > 1 ? 's' : ''} ago');
        }
        
        // Warn if entry is very recent (possible duplicate)
        // Only warn if there are existing entries and this timestamp is very close to them
        // For now, we'll skip this warning since we don't have access to existing entries here
        // This should be handled at the form level where we can check against existing data
        
        // Note: Duplicate detection should be moved to the BLoC layer where we have access
        // to existing entries to make proper comparisons
        
        // Add any external warnings
        warnings.addAll(widget.warnings);
      }
    }
    
    setState(() {
      _errorText = showErrors ? error : null;
      _currentWarnings = warnings;
    });
  }

  Future<void> _selectDate() async {
    final initialDate = _selectedDate ?? DateTime.now();
    final firstDate = widget.firstDate ?? DateTime(1900);
    final lastDate = widget.lastDate ?? 
        (widget.allowFutureDates ? DateTime(2100) : DateTime.now());
    
    final pickedDate = await showDatePicker(
      context: context,
      initialDate: initialDate,
      firstDate: firstDate,
      lastDate: lastDate,
      helpText: 'Select ${widget.label}',
    );
    
    if (pickedDate != null && pickedDate != _selectedDate) {
      setState(() {
        _selectedDate = pickedDate;
      });
      
      if (widget.showTimeSelection) {
        _selectTime();
      } else {
        final combinedDate = _getCombinedDateTime();
        widget.onChanged?.call(combinedDate);
        _validateDate(combinedDate, showErrors: true);
      }
    }
  }

  Future<void> _selectTime() async {
    final initialTime = _selectedTime ?? TimeOfDay.now();
    
    final pickedTime = await showTimePicker(
      context: context,
      initialTime: initialTime,
      helpText: 'Select Time',
    );
    
    if (pickedTime != null) {
      setState(() {
        _selectedTime = pickedTime;
      });
      
      final combinedDate = _getCombinedDateTime();
      widget.onChanged?.call(combinedDate);
      _validateDate(combinedDate, showErrors: true);
    }
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final hasError = _errorText != null;
    final hasWarnings = _currentWarnings.isNotEmpty && widget.showWarnings;
    final combinedDate = _getCombinedDateTime();
    
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        // Label
        RichText(
          text: TextSpan(
            text: widget.label,
            style: theme.textTheme.titleMedium?.copyWith(
              fontWeight: FontWeight.w600,
            ),
            children: [
              if (widget.isRequired)
                TextSpan(
                  text: ' *',
                  style: TextStyle(
                    color: theme.colorScheme.error,
                    fontWeight: FontWeight.w600,
                  ),
                ),
            ],
          ),
        ),
        const SizedBox(height: 8),
        
        // Date picker button
        InkWell(
          onTap: _selectDate,
          borderRadius: BorderRadius.circular(8),
          child: Container(
            padding: const EdgeInsets.all(16),
            decoration: BoxDecoration(
              border: Border.all(
                color: hasError
                    ? theme.colorScheme.error
                    : hasWarnings
                        ? Colors.orange.shade400
                        : theme.colorScheme.outline,
                width: hasError || hasWarnings ? 2 : 1,
              ),
              borderRadius: BorderRadius.circular(8),
            ),
            child: Row(
              children: [
                Icon(
                  widget.showTimeSelection 
                      ? Icons.schedule 
                      : Icons.calendar_today,
                  color: hasError
                      ? theme.colorScheme.error
                      : hasWarnings
                          ? Colors.orange.shade600
                          : theme.colorScheme.onSurfaceVariant,
                  size: 20,
                ),
                const SizedBox(width: 12),
                Expanded(
                  child: Text(
                    combinedDate != null
                        ? _formatter.format(combinedDate)
                        : 'Select ${widget.label.toLowerCase()}',
                    style: theme.textTheme.bodyLarge?.copyWith(
                      color: combinedDate != null
                          ? theme.colorScheme.onSurface
                          : theme.colorScheme.onSurfaceVariant,
                    ),
                  ),
                ),
                Icon(
                  Icons.arrow_drop_down,
                  color: theme.colorScheme.onSurfaceVariant,
                ),
              ],
            ),
          ),
        ),
        
        // Error display
        if (hasError) ...[
          const SizedBox(height: 4),
          Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Icon(
                Icons.error_outline,
                size: 14,
                color: theme.colorScheme.error,
              ),
              const SizedBox(width: 4),
              Expanded(
                child: Text(
                  _errorText!,
                  style: theme.textTheme.bodySmall?.copyWith(
                    color: theme.colorScheme.error,
                  ),
                ),
              ),
            ],
          ),
        ],
        
        // Warnings display
        if (hasWarnings && !hasError) ...[
          const SizedBox(height: 4),
          ...(_currentWarnings.map((warning) => Container(
            margin: const EdgeInsets.only(bottom: 2),
            child: Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Icon(
                  Icons.warning_amber,
                  size: 14,
                  color: Colors.orange.shade600,
                ),
                const SizedBox(width: 4),
                Expanded(
                  child: Text(
                    warning,
                    style: theme.textTheme.bodySmall?.copyWith(
                      color: Colors.orange.shade700,
                    ),
                  ),
                ),
              ],
            ),
          ))),
        ],
        
        // Helper text
        const SizedBox(height: 4),
        Text(
          _getHelperText(),
          style: theme.textTheme.bodySmall?.copyWith(
            color: theme.colorScheme.onSurfaceVariant,
          ),
        ),
        
        // Time selection button (if enabled and date is selected)
        if (widget.showTimeSelection && _selectedDate != null && !hasError) ...[
          const SizedBox(height: 8),
          OutlinedButton.icon(
            onPressed: _selectTime,
            icon: const Icon(Icons.access_time, size: 18),
            label: Text(
              _selectedTime != null
                  ? 'Time: ${_selectedTime!.format(context)}'
                  : 'Select time',
            ),
            style: OutlinedButton.styleFrom(
              side: BorderSide(
                color: hasWarnings
                    ? Colors.orange.shade400
                    : theme.colorScheme.outline,
              ),
            ),
          ),
        ],
      ],
    );
  }

  String _getHelperText() {
    if (widget.firstDate != null && widget.lastDate != null) {
      return 'Valid range: ${_formatter.format(widget.firstDate!)} - ${_formatter.format(widget.lastDate!)}';
    } else if (widget.firstDate != null) {
      return 'Cannot be before: ${_formatter.format(widget.firstDate!)}';
    } else if (widget.lastDate != null) {
      return 'Cannot be after: ${_formatter.format(widget.lastDate!)}';
    } else if (!widget.allowFutureDates) {
      return 'Cannot be in the future';
    }
    return 'Tap to select date${widget.showTimeSelection ? ' and time' : ''}';
  }
}

/// Extension methods for common date validation patterns
extension ValidatedDatePickerValidators on ValidatedDatePicker {
  /// Create a validator that ensures the date is not too far in the past
  static String? pastDateValidator(DateTime? date, {int maxYearsAgo = 10}) {
    if (date == null) return null;
    
    final maxPastDate = DateTime.now().subtract(Duration(days: 365 * maxYearsAgo));
    if (date.isBefore(maxPastDate)) {
      return 'Date cannot be more than $maxYearsAgo years ago';
    }
    
    return null;
  }
  
  /// Create a validator that ensures the date is reasonable for health entries
  static String? healthEntryDateValidator(DateTime? date) {
    if (date == null) return null;
    
    final now = DateTime.now();
    
    // Cannot be in the future
    if (date.isAfter(now)) {
      return 'Health entry cannot be in the future';
    }
    
    // Cannot be more than 10 years ago
    final tenYearsAgo = now.subtract(const Duration(days: 365 * 10));
    if (date.isBefore(tenYearsAgo)) {
      return 'Entry cannot be more than 10 years old';
    }
    
    return null;
  }
}
