import 'package:flutter/material.dart';
import 'package:table_calendar/table_calendar.dart';
import 'package:em2rp/utils/colors.dart';
import 'package:em2rp/models/event_model.dart';
import 'package:em2rp/utils/calendar_utils.dart';

class MonthView extends StatelessWidget {
  static const double _calendarPadding = 8.0;
  static const double _headerHeight = 52.0;
  static const double _headerVerticalPadding = 16.0;
  static const double _daysOfWeekHeight = 16.0;

  final DateTime focusedDay;
  final DateTime? selectedDay;
  final CalendarFormat calendarFormat;
  final Function(DateTime, DateTime) onDaySelected;
  final Function(CalendarFormat) onFormatChanged;
  final Function(DateTime) onPageChanged;
  final List<EventModel> events;
  final Function(EventModel) onEventSelected;

  const MonthView({
    super.key,
    required this.focusedDay,
    required this.selectedDay,
    required this.calendarFormat,
    required this.onDaySelected,
    required this.onFormatChanged,
    required this.onPageChanged,
    required this.events,
    required this.onEventSelected,
  });

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        final rowCount = _computeRowCount(focusedDay);
        // TableCalendar has internal vertical padding and margins (approx 16px) that cause overflow
        // if not accounted for. We subtract an extra 16.0 pixels to be safe.
        final availableHeight = constraints.maxHeight -
            (_calendarPadding * 2) -
            _headerHeight -
            _headerVerticalPadding -
            _daysOfWeekHeight -
            16.0;
        final rowHeight = (availableHeight > 0 ? availableHeight : 200.0) / rowCount;

        return Container(
          height: constraints.maxHeight,
          padding: const EdgeInsets.all(_calendarPadding),
          child: TableCalendar(
            firstDay: DateTime.utc(2020, 1, 1),
            lastDay: DateTime.utc(2030, 12, 31),
            focusedDay: focusedDay,
            calendarFormat: calendarFormat,
            startingDayOfWeek: StartingDayOfWeek.monday,
            locale: 'fr_FR',
            daysOfWeekHeight: _daysOfWeekHeight,
            availableCalendarFormats: const {
              CalendarFormat.month: 'Mois',
              CalendarFormat.week: 'Semaine',
            },
            selectedDayPredicate: (day) => isSameDay(selectedDay, day),
            onDaySelected: onDaySelected,
            onFormatChanged: onFormatChanged,
            onPageChanged: onPageChanged,
            calendarStyle: _buildCalendarStyle(),
            rowHeight: rowHeight,
            headerStyle: _buildHeaderStyle(),
            calendarBuilders: _buildCalendarBuilders(),
          ),
        );
      },
    );
  }

  CalendarStyle _buildCalendarStyle() {
    return CalendarStyle(
      defaultDecoration: BoxDecoration(
        border: Border.all(color: Colors.grey.shade300),
        borderRadius: BorderRadius.circular(4),
      ),
      selectedDecoration: BoxDecoration(
        color: AppColors.rouge,
        border: Border.all(color: AppColors.rouge),
        borderRadius: BorderRadius.circular(4),
      ),
      todayDecoration: BoxDecoration(
        color: AppColors.rouge.withAlpha(26),
        border: Border.all(color: AppColors.rouge),
        borderRadius: BorderRadius.circular(4),
      ),
      outsideDecoration: BoxDecoration(
        border: Border.all(color: Colors.grey.shade300),
        borderRadius: BorderRadius.circular(4),
      ),
      outsideDaysVisible: false,
      cellMargin: EdgeInsets.zero,
      cellPadding: EdgeInsets.zero,
    );
  }

  HeaderStyle _buildHeaderStyle() {
    return HeaderStyle(
      formatButtonVisible: true,
      titleCentered: true,
      formatButtonShowsNext: false,
      formatButtonDecoration: BoxDecoration(
        color: AppColors.rouge,
        borderRadius: BorderRadius.circular(16),
      ),
      formatButtonTextStyle: const TextStyle(color: Colors.white),
      leftChevronIcon: const Icon(Icons.chevron_left, color: AppColors.rouge),
      rightChevronIcon: const Icon(Icons.chevron_right, color: AppColors.rouge),
      headerPadding: const EdgeInsets.symmetric(vertical: 8),
      titleTextStyle: const TextStyle(
        fontSize: 18,
        fontWeight: FontWeight.bold,
      ),
    );
  }

  CalendarBuilders _buildCalendarBuilders() {
    return CalendarBuilders(
      dowBuilder: (context, day) {
        return Center(
          child: Text(
            CalendarUtils.getShortDayName(day.weekday),
            style: const TextStyle(
              fontWeight: FontWeight.bold,
            ),
          ),
        );
      },
      defaultBuilder: (context, day, focusedDay) {
        return _buildDayCell(day, false);
      },
      selectedBuilder: (context, day, focusedDay) {
        return _buildDayCell(day, true);
      },
      todayBuilder: (context, day, focusedDay) {
        return _buildDayCell(day, false, isToday: true);
      },
    );
  }

  Widget _buildDayCell(DateTime day, bool isSelected, {bool isToday = false}) {
    final dayEvents = CalendarUtils.getEventsForDay(day, events);
    final statusCounts = _getStatusCounts(dayEvents);
    final textColor =
        isSelected ? Colors.white : (isToday ? AppColors.rouge : null);

    BoxDecoration decoration;
    if (isSelected) {
      decoration = BoxDecoration(
        color: AppColors.rouge,
        border: Border.all(color: AppColors.rouge),
        borderRadius: BorderRadius.circular(4),
      );
    } else if (isToday) {
      decoration = BoxDecoration(
        color: AppColors.rouge.withAlpha(26),
        border: Border.all(color: AppColors.rouge),
        borderRadius: BorderRadius.circular(4),
      );
    } else {
      decoration = BoxDecoration(
        color: null,
        border: Border.all(color: Colors.grey.shade300),
        borderRadius: BorderRadius.circular(4),
      );
    }

    return Container(
      margin: const EdgeInsets.all(4),
      decoration: decoration,
      child: Padding(
        padding: const EdgeInsets.all(4),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  day.day.toString(),
                  style: TextStyle(color: textColor),
                ),
                const SizedBox(width: 4),
                Expanded(
                  child: Align(
                    alignment: Alignment.topRight,
                    child: Wrap(
                      spacing: 4,
                      runSpacing: 2,
                      alignment: WrapAlignment.end,
                      children: _buildStatusBadges(statusCounts),
                    ),
                  ),
                ),
              ],
            ),
            if (dayEvents.isNotEmpty) ...[
              const SizedBox(height: 4),
              Expanded(
                child: SingleChildScrollView(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: dayEvents
                        .map((event) => _buildEventItem(event, isSelected, day))
                        .toList(),
                  ),
                ),
              ),
            ],
          ],
        ),
      ),
    );
  }

  Map<EventStatus, int> _getStatusCounts(List<EventModel> dayEvents) {
    final counts = <EventStatus, int>{
      EventStatus.confirmed: 0,
      EventStatus.waitingForApproval: 0,
      EventStatus.canceled: 0,
    };

    for (final event in dayEvents) {
      counts[event.status] = (counts[event.status] ?? 0) + 1;
    }

    return counts;
  }

  List<Widget> _buildStatusBadges(Map<EventStatus, int> statusCounts) {
    final badges = <Widget>[];

    void addBadge({
      required EventStatus status,
      required Color backgroundColor,
      required Color textColor,
      required String tooltipLabel,
    }) {
      final count = statusCounts[status] ?? 0;
      if (count <= 0) {
        return;
      }

      badges.add(
        Tooltip(
          message: '$count $tooltipLabel',
          child: Container(
            padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
            decoration: BoxDecoration(
              color: backgroundColor,
              borderRadius: BorderRadius.circular(999),
            ),
            child: Text(
              count.toString(),
              style: TextStyle(
                color: textColor,
                fontSize: 11,
                fontWeight: FontWeight.bold,
              ),
            ),
          ),
        ),
      );
    }

    addBadge(
      status: EventStatus.confirmed,
      backgroundColor: Colors.green,
      textColor: Colors.white,
      tooltipLabel:
          'validé${(statusCounts[EventStatus.confirmed] ?? 0) > 1 ? 's' : ''}',
    );
    addBadge(
      status: EventStatus.waitingForApproval,
      backgroundColor: Colors.amber,
      textColor: Colors.black,
      tooltipLabel: 'en attente',
    );
    addBadge(
      status: EventStatus.canceled,
      backgroundColor: Colors.red,
      textColor: Colors.white,
      tooltipLabel:
          'annulé${(statusCounts[EventStatus.canceled] ?? 0) > 1 ? 's' : ''}',
    );

    return badges;
  }

  Widget _buildEventItem(
      EventModel event, bool isSelected, DateTime currentDay) {
    Color color;
    Color textColor;
    IconData icon;
    switch (event.status) {
      case EventStatus.confirmed:
        color = Colors.green;
        textColor = Colors.white;
        icon = Icons.check;
        break;
      case EventStatus.canceled:
        color = Colors.red;
        textColor = Colors.white;
        icon = Icons.close;
        break;
      case EventStatus.waitingForApproval:
        color = Colors.amber;
        textColor = Colors.black;
        icon = Icons.hourglass_empty;
        break;
    }
    return GestureDetector(
      onTap: () {
        onDaySelected(currentDay, currentDay);
        onEventSelected(event);
      },
      child: Container(
        margin: const EdgeInsets.only(bottom: 2),
        padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 2),
        decoration: BoxDecoration(
          color:
              isSelected ? color.withAlpha(220) : color.withValues(alpha: 0.18),
          borderRadius: BorderRadius.circular(4),
        ),
        child: Row(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Icon(icon, color: textColor, size: 16),
            const SizedBox(width: 4),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    event.name,
                    style: TextStyle(
                      fontSize: 12,
                      color: textColor,
                      fontWeight: FontWeight.bold,
                    ),
                    maxLines: 1,
                    overflow: TextOverflow.ellipsis,
                  ),
                  if (CalendarUtils.isMultiDayEvent(event))
                    Text(
                      'Jour ${CalendarUtils.calculateDayNumber(event.startDateTime, currentDay)}/${CalendarUtils.calculateTotalDays(event)}',
                      style: TextStyle(
                        fontSize: 10,
                        color: textColor,
                      ),
                      maxLines: 1,
                    ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

  /// Calcule le nombre de rangées affichées pour le mois de [focusedDay]
  /// (calendrier commençant le lundi : offset = weekday - 1)
  int _computeRowCount(DateTime focusedDay) {
    final firstOfMonth = DateTime(focusedDay.year, focusedDay.month, 1);
    final daysInMonth = DateTime(focusedDay.year, focusedDay.month + 1, 0).day;
    final offset = (firstOfMonth.weekday - 1) % 7; // 0 = lundi, 6 = dimanche
    return ((daysInMonth + offset) / 7).ceil();
  }
}
