import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/activity.dart';
import 'package:styled_widget/styled_widget.dart';
import 'package:island/widgets/account/event_details_widget.dart';
import 'package:table_calendar/table_calendar.dart';

/// A reusable widget for displaying an event calendar with event details
/// This can be used in various places throughout the app
class EventCalendarWidget extends HookConsumerWidget {
  /// The list of calendar entries to display
  final AsyncValue<List<SnEventCalendarEntry>> events;

  /// Initial date to focus on
  final DateTime? initialDate;

  /// Whether to show the event details below the calendar
  final bool showEventDetails;

  /// Whether to constrain the width of the calendar
  final bool constrainWidth;

  /// Maximum width constraint when constrainWidth is true
  final double maxWidth;

  /// Callback when a day is selected
  final void Function(DateTime)? onDaySelected;

  /// Callback when the focused month changes
  final void Function(int year, int month)? onMonthChanged;

  const EventCalendarWidget({
    super.key,
    required this.events,
    this.initialDate,
    this.showEventDetails = true,
    this.constrainWidth = false,
    this.maxWidth = 480,
    this.onDaySelected,
    this.onMonthChanged,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final selectedMonth = useState(initialDate?.month ?? DateTime.now().month);
    final selectedYear = useState(initialDate?.year ?? DateTime.now().year);
    final selectedDay = useState(initialDate ?? DateTime.now());

    final content = Column(
      children: [
        TableCalendar(
          locale: EasyLocalization.of(context)!.locale.toString(),
          firstDay: DateTime.now().add(Duration(days: -3650)),
          lastDay: DateTime.now().add(Duration(days: 3650)),
          focusedDay: DateTime.utc(
            selectedYear.value,
            selectedMonth.value,
            selectedDay.value.day,
          ),
          weekNumbersVisible: false,
          calendarFormat: CalendarFormat.month,
          selectedDayPredicate: (day) {
            return isSameDay(selectedDay.value, day);
          },
          onDaySelected: (value, _) {
            selectedDay.value = value;
            onDaySelected?.call(value);
          },
          onPageChanged: (focusedDay) {
            selectedMonth.value = focusedDay.month;
            selectedYear.value = focusedDay.year;
            onMonthChanged?.call(focusedDay.year, focusedDay.month);
          },
          eventLoader: (day) {
            return events.value
                    ?.where((e) => isSameDay(e.date, day))
                    .expand((e) => [...e.statuses, e.checkInResult])
                    .where((e) => e != null)
                    .toList() ??
                [];
          },
          calendarBuilders: CalendarBuilders(
            dowBuilder: (context, day) {
              final text = DateFormat.EEEEE().format(day);
              return Center(child: Text(text));
            },
            markerBuilder: (context, day, events) {
              var checkInResult =
                  events.whereType<SnCheckInResult>().firstOrNull;
              if (checkInResult != null) {
                return Positioned(
                  top: 32,
                  child: Text(
                    'checkInResultT${checkInResult.level}'.tr(),
                    style: TextStyle(
                      fontSize: 9,
                      color:
                          isSameDay(selectedDay.value, day)
                              ? Theme.of(context).colorScheme.onPrimaryContainer
                              : isSameDay(DateTime.now(), day)
                              ? Theme.of(
                                context,
                              ).colorScheme.onSecondaryContainer
                              : Theme.of(context).colorScheme.onSurface,
                    ),
                  ),
                );
              }
              return null;
            },
          ),
        ),
        if (showEventDetails) ...[
          const Divider(height: 1).padding(top: 8),
          AnimatedSwitcher(
            duration: const Duration(milliseconds: 300),
            child: Builder(
              builder: (context) {
                final event =
                    events.value
                        ?.where((e) => isSameDay(e.date, selectedDay.value))
                        .firstOrNull;
                return EventDetailsWidget(
                  selectedDay: selectedDay.value,
                  event: event,
                );
              },
            ),
          ),
        ],
      ],
    );

    if (constrainWidth) {
      return ConstrainedBox(
        constraints: BoxConstraints(maxWidth: maxWidth),
        child: Card(margin: EdgeInsets.all(16), child: content),
      ).center();
    }

    return content;
  }
}
