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

class WeekView extends StatelessWidget {
  final DateTime focusedDay;
  final List<EventModel> events;
  final Function(int) onWeekChange;
  final Function(EventModel) onEventSelected;
  final Function() onSwitchToMonth;
  final Function(DateTime) onDaySelected;
  final EventModel? selectedEvent;

  const WeekView({
    super.key,
    required this.focusedDay,
    required this.events,
    required this.onWeekChange,
    required this.onEventSelected,
    required this.onSwitchToMonth,
    required this.onDaySelected,
    required this.selectedEvent,
  });

  @override
  Widget build(BuildContext context) {
    final weekStart =
        focusedDay.subtract(Duration(days: focusedDay.weekday - 1));
    final weekEnd = weekStart.add(const Duration(days: 6));

    return Column(
      children: [
        _buildWeekHeader(weekStart, weekEnd),
        Expanded(
          child: LayoutBuilder(
            builder: (context, constraints) {
              final availableHeight = constraints.maxHeight - 80;
              final hourHeight = availableHeight / 24;
              final dayWidth = (constraints.maxWidth - 50) / 7;

              return SingleChildScrollView(
                child: SizedBox(
                  height: 24 * hourHeight,
                  child: Row(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      _buildHourColumn(hourHeight),
                      Expanded(
                        child: _buildWeekGrid(
                          weekStart,
                          hourHeight,
                          dayWidth,
                          constraints,
                        ),
                      ),
                    ],
                  ),
                ),
              );
            },
          ),
        ),
      ],
    );
  }

  Widget _buildWeekHeader(DateTime weekStart, DateTime weekEnd) {
    return Column(
      children: [
        Padding(
          padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              IconButton(
                icon: const Icon(Icons.chevron_left),
                onPressed: () => onWeekChange(-1),
              ),
              Text(
                CalendarUtils.getMonthYearString(weekStart, weekEnd),
                style:
                    const TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
              ),
              Row(
                children: [
                  TextButton(
                    onPressed: onSwitchToMonth,
                    style: TextButton.styleFrom(
                      backgroundColor: AppColors.rouge,
                      foregroundColor: Colors.white,
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(16),
                      ),
                      padding: const EdgeInsets.symmetric(
                          horizontal: 12, vertical: 8),
                    ),
                    child: const Text('Semaine'),
                  ),
                  IconButton(
                    icon: const Icon(Icons.chevron_right),
                    onPressed: () => onWeekChange(1),
                  ),
                ],
              ),
            ],
          ),
        ),
        _buildDaysHeader(weekStart),
      ],
    );
  }

  Widget _buildDaysHeader(DateTime weekStart) {
    return SizedBox(
      height: 40,
      child: Row(
        children: [
          Container(
            width: 50,
            color: Colors.transparent,
          ),
          ...List.generate(7, (index) {
            final day = weekStart.add(Duration(days: index));
            return Expanded(
              child: Container(
                decoration: BoxDecoration(
                  border: Border(
                    right: BorderSide(
                      color:
                          index < 6 ? Colors.grey.shade300 : Colors.transparent,
                      width: 1,
                    ),
                  ),
                ),
                child: Stack(
                  children: [
                    Center(
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          Text(
                            CalendarUtils.getShortDayName(day.weekday),
                            style: const TextStyle(fontWeight: FontWeight.bold),
                          ),
                          Text(
                            '${day.day}',
                            style: const TextStyle(fontSize: 13),
                          ),
                        ],
                      ),
                    ),
                    if (CalendarUtils.getEventsForDay(day, events).isNotEmpty)
                      Positioned(
                        top: 4,
                        right: 4,
                        child: Container(
                          padding: const EdgeInsets.symmetric(
                              horizontal: 6, vertical: 2),
                          decoration: BoxDecoration(
                            color: AppColors.rouge,
                            borderRadius: BorderRadius.circular(10),
                          ),
                          child: Text(
                            CalendarUtils.getEventsForDay(day, events)
                                .length
                                .toString(),
                            style: const TextStyle(
                              color: Colors.white,
                              fontSize: 10,
                              fontWeight: FontWeight.bold,
                            ),
                          ),
                        ),
                      ),
                  ],
                ),
              ),
            );
          }),
        ],
      ),
    );
  }

  Widget _buildHourColumn(double hourHeight) {
    return Column(
      children: List.generate(24, (index) {
        return Container(
          width: 50,
          height: hourHeight,
          alignment: Alignment.topRight,
          padding: const EdgeInsets.only(right: 4),
          child: Text(
            '${index.toString().padLeft(2, '0')}:00',
            style: TextStyle(
              color: Colors.grey.shade600,
              fontSize: 12,
            ),
          ),
        );
      }),
    );
  }

  Widget _buildWeekGrid(
    DateTime weekStart,
    double hourHeight,
    double dayWidth,
    BoxConstraints constraints,
  ) {
    final eventsByDay = _prepareEventsByDay(weekStart);
    final eventsWithColumnsByDay = _assignColumnsToEvents(eventsByDay);

    return Stack(
      children: [
        // Lignes horizontales
        Column(
          children: List.generate(24, (index) {
            return Container(
              height: hourHeight,
              decoration: BoxDecoration(
                border: Border(
                  bottom: BorderSide(
                    color: Colors.grey.shade300,
                    width: 0.5,
                  ),
                ),
              ),
            );
          }),
        ),
        // Bordures verticales entre jours
        Positioned.fill(
          child: Row(
            children: List.generate(7, (i) {
              return Container(
                width: dayWidth,
                decoration: BoxDecoration(
                  border: Border(
                    right: BorderSide(
                      color: i < 6 ? Colors.grey.shade300 : Colors.transparent,
                      width: 1,
                    ),
                  ),
                ),
              );
            }),
          ),
        ),
        // Événements
        ...List.generate(7, (dayIdx) {
          final dayEvents = eventsWithColumnsByDay[dayIdx];
          return Stack(
            children: dayEvents.map((e) {
              final startHour = e.start.hour + e.start.minute / 60;
              final endHour = e.end.hour + e.end.minute / 60;
              final duration = endHour - startHour;
              final width = dayWidth / e.totalColumns;
              final isSelected =
                  selectedEvent != null && e.event.id == selectedEvent!.id;

              return Positioned(
                left: dayIdx * dayWidth + e.column * width,
                top: startHour * hourHeight,
                width: width,
                height: duration * hourHeight,
                child: GestureDetector(
                  onTap: () => onEventSelected(e.event),
                  child: Container(
                    margin: const EdgeInsets.all(2),
                    padding: const EdgeInsets.all(4),
                    decoration: BoxDecoration(
                      color: isSelected
                          ? _getStatusColor(e.event.status).withAlpha(220)
                          : _getStatusColor(e.event.status).withOpacity(0.18),
                      border: Border.all(
                        color: _getStatusColor(e.event.status),
                        width: isSelected ? 3 : 1,
                      ),
                      borderRadius: BorderRadius.circular(4),
                    ),
                    child: Row(
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: [
                        Expanded(
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              Text(
                                e.event.name,
                                style: TextStyle(
                                  color: _getStatusTextColor(e.event.status),
                                  fontSize: 12,
                                  fontWeight: FontWeight.bold,
                                ),
                                maxLines: 1,
                                overflow: TextOverflow.ellipsis,
                              ),
                              if (CalendarUtils.isMultiDayEvent(e.event))
                                Text(
                                  'Jour ${CalendarUtils.calculateDayNumber(e.event.startDateTime, weekStart.add(Duration(days: dayIdx)))}/${CalendarUtils.calculateTotalDays(e.event)}',
                                  style: TextStyle(
                                    color: _getStatusTextColor(e.event.status),
                                    fontSize: 10,
                                  ),
                                  maxLines: 1,
                                ),
                            ],
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              );
            }).toList(),
          );
        }),
      ],
    );
  }

  List<List<_PositionedEvent>> _prepareEventsByDay(DateTime weekStart) {
    List<List<_PositionedEvent>> eventsByDay = List.generate(7, (i) => []);

    for (final event in events) {
      for (int i = 0; i < 7; i++) {
        final day = weekStart.add(Duration(days: i));
        final dayStart = DateTime(day.year, day.month, day.day, 0, 0);
        final dayEnd = DateTime(day.year, day.month, day.day, 23, 59, 59);

        if (!(event.endDateTime.isBefore(dayStart) ||
            event.startDateTime.isAfter(dayEnd))) {
          final start = event.startDateTime.isBefore(dayStart)
              ? dayStart
              : event.startDateTime;
          final end =
              event.endDateTime.isAfter(dayEnd) ? dayEnd : event.endDateTime;
          eventsByDay[i].add(_PositionedEvent(event, start, end));
        }
      }
    }

    return eventsByDay;
  }

  List<List<_PositionedEventWithColumn>> _assignColumnsToEvents(
      List<List<_PositionedEvent>> eventsByDay) {
    return eventsByDay.map((dayEvents) {
      dayEvents.sort((a, b) => a.start.compareTo(b.start));
      List<_PositionedEventWithColumn> result = [];
      List<List<_PositionedEventWithColumn>> columns = [];

      for (final e in dayEvents) {
        bool placed = false;
        for (int col = 0; col < columns.length; col++) {
          if (columns[col].isEmpty || !_overlap(columns[col].last, e)) {
            columns[col].add(
                _PositionedEventWithColumn(e.event, e.start, e.end, col, 0));
            placed = true;
            break;
          }
        }
        if (!placed) {
          columns.add([
            _PositionedEventWithColumn(
                e.event, e.start, e.end, columns.length, 0)
          ]);
        }
      }

      int totalCols = columns.length;
      for (final col in columns) {
        for (final e in col) {
          result.add(_PositionedEventWithColumn(
              e.event, e.start, e.end, e.column, totalCols));
        }
      }
      return result;
    }).toList();
  }

  bool _overlap(_PositionedEvent a, _PositionedEvent b) {
    return a.end.isAfter(b.start) && a.start.isBefore(b.end);
  }

  Color _getStatusColor(EventStatus status) {
    switch (status) {
      case EventStatus.confirmed:
        return Colors.green;
      case EventStatus.canceled:
        return Colors.red;
      case EventStatus.waitingForApproval:
      default:
        return Colors.amber;
    }
  }

  Color _getStatusTextColor(EventStatus status) {
    switch (status) {
      case EventStatus.confirmed:
      case EventStatus.canceled:
        return Colors.white;
      case EventStatus.waitingForApproval:
      default:
        return Colors.black;
    }
  }

  IconData _getStatusIcon(EventStatus status) {
    switch (status) {
      case EventStatus.confirmed:
        return Icons.check;
      case EventStatus.canceled:
        return Icons.close;
      case EventStatus.waitingForApproval:
      default:
        return Icons.hourglass_empty;
    }
  }
}

class _PositionedEvent {
  final EventModel event;
  final DateTime start;
  final DateTime end;
  _PositionedEvent(this.event, this.start, this.end);
}

class _PositionedEventWithColumn extends _PositionedEvent {
  final int column;
  final int totalColumns;
  _PositionedEventWithColumn(
      super.event, super.start, super.end, this.column, this.totalColumns);
}
