part of '../custom_workweek_calendar.dart';

class _OutsideHoursStrip extends StatelessWidget {
  final DateTime weekStart;
  final List<Appointment> appointments;
  final double rulerWidth;
  final void Function(Appointment) onAppointmentTap;
  final bool Function(Appointment) isCrossedOut;

  const _OutsideHoursStrip({
    super.key,
    required this.weekStart,
    required this.appointments,
    required this.rulerWidth,
    required this.onAppointmentTap,
    required this.isCrossedOut,
  });

  @override
  Widget build(BuildContext context) {
    final outside = partitionAppointmentsForWeek(
      appointments,
      weekStart,
    ).outside;
    if (outside.every((day) => day.isEmpty)) return const SizedBox.shrink();

    final theme = Theme.of(context);
    final maxChipsPerDay = outside
        .map(
          (day) => day.length > kOutsideChipsMaxVisible
              ? kOutsideChipsMaxVisible
              : day.length,
        )
        .fold<int>(0, (m, c) => c > m ? c : m);
    final stripHeight =
        kOutsideStripVerticalPadding * 2 +
        maxChipsPerDay * kOutsideChipHeight +
        (maxChipsPerDay > 1 ? (maxChipsPerDay - 1) * kOutsideChipSpacing : 0);

    return Container(
      // Scaffold-Background, damit die Ganztagestermine-Leiste optisch nahtlos
      // an Header und Stundenplan-Hintergrund anschließt; surfaceContainerLowest
      // ist in M3-Light reinweiß und sticht gegen die getönte Seed-Surface ab.
      color: theme.scaffoldBackgroundColor,
      padding: const EdgeInsets.symmetric(
        vertical: kOutsideStripVerticalPadding,
      ),
      child: SizedBox(
        height: stripHeight - kOutsideStripVerticalPadding * 2,
        child: Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            SizedBox(width: rulerWidth),
            for (var d = 0; d < 5; d++)
              Expanded(
                child: _OutsideDayColumn(
                  appointments: outside[d],
                  onAppointmentTap: onAppointmentTap,
                  isCrossedOut: isCrossedOut,
                ),
              ),
          ],
        ),
      ),
    );
  }
}

class _OutsideDayColumn extends StatelessWidget {
  final List<Appointment> appointments;
  final void Function(Appointment) onAppointmentTap;
  final bool Function(Appointment) isCrossedOut;

  const _OutsideDayColumn({
    required this.appointments,
    required this.onAppointmentTap,
    required this.isCrossedOut,
  });

  void _showOverflow(BuildContext context, List<Appointment> hidden) {
    _showAppointmentOverflowSheet(
      context,
      hidden,
      onAppointmentTap: onAppointmentTap,
      isCrossedOut: isCrossedOut,
      subtitle: _subtitleFor,
    );
  }

  static String _subtitleFor(Appointment a) {
    if (isAllDayLike(a)) return A11yLabels.allDay;
    return '${a.startTime.formatHm()}–${a.endTime.formatHm()}';
  }

  @override
  Widget build(BuildContext context) {
    if (appointments.isEmpty) return const SizedBox.shrink();
    final sorted = [...appointments]
      ..sort((a, b) {
        final aLike = isAllDayLike(a);
        final bLike = isAllDayLike(b);
        if (aLike && !bLike) return -1;
        if (!aLike && bLike) return 1;
        return a.startTime.compareTo(b.startTime);
      });
    final visible = sorted.length <= kOutsideChipsMaxVisible
        ? sorted
        : sorted.take(kOutsideChipsMaxVisible - 1).toList();
    final overflow = sorted.length <= kOutsideChipsMaxVisible
        ? const <Appointment>[]
        : sorted.skip(kOutsideChipsMaxVisible - 1).toList();

    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 2),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          for (var i = 0; i < visible.length; i++) ...[
            if (i > 0) const SizedBox(height: kOutsideChipSpacing),
            SizedBox(
              height: kOutsideChipHeight,
              child: _OutsideChip(
                appointment: visible[i],
                crossedOut: isCrossedOut(visible[i]),
                onTap: () => onAppointmentTap(visible[i]),
              ),
            ),
          ],
          if (overflow.isNotEmpty) ...[
            const SizedBox(height: kOutsideChipSpacing),
            SizedBox(
              height: kOutsideChipHeight,
              child: _OutsideOverflowChip(
                count: overflow.length,
                onTap: () => _showOverflow(context, overflow),
              ),
            ),
          ],
        ],
      ),
    );
  }
}

class _OutsideChip extends StatelessWidget {
  final Appointment appointment;
  final bool crossedOut;
  final VoidCallback onTap;

  const _OutsideChip({
    required this.appointment,
    required this.crossedOut,
    required this.onTap,
  });

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final allDay = isAllDayLike(appointment);
    final timeLabel = allDay ? null : appointment.startTime.formatHm();
    final semanticsLabel = [
      appointment.subject,
      if (allDay)
        A11yLabels.allDay
      else
        '${appointment.startTime.formatHm()}–${appointment.endTime.formatHm()}',
      if (crossedOut) A11yLabels.cancelled,
    ].join(', ');

    // Past chips fade further, future/ongoing ones get a more saturated tint
    // so the strip no longer reads as one uniform grey block.
    final isPast = appointment.endTime.isBefore(DateTime.now());
    final backgroundAlpha = isPast ? 38 : 120;
    final subjectColor = isPast
        ? theme.colorScheme.onSurfaceVariant
        : theme.colorScheme.onSurface;
    final subjectWeight = isPast ? FontWeight.w400 : FontWeight.w600;

    return Semantics(
      button: true,
      label: semanticsLabel,
      onTap: onTap,
      child: ExcludeSemantics(
        child: Material(
          color: appointment.color.withAlpha(backgroundAlpha),
          shape: const RoundedRectangleBorder(
            borderRadius: BorderRadius.all(Radius.circular(7)),
          ),
          clipBehavior: Clip.antiAlias,
          child: InkWell(
            onTap: onTap,
            child: Padding(
              padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 2),
              child: Row(
                mainAxisSize: MainAxisSize.max,
                children: [
                  Expanded(
                    child: Text(
                      appointment.subject,
                      maxLines: 1,
                      overflow: TextOverflow.ellipsis,
                      softWrap: false,
                      style: theme.textTheme.labelSmall?.copyWith(
                        color: subjectColor,
                        fontWeight: subjectWeight,
                      ),
                    ),
                  ),
                  if (timeLabel != null) ...[
                    const SizedBox(width: 4),
                    Flexible(
                      child: Text(
                        timeLabel,
                        maxLines: 1,
                        overflow: TextOverflow.fade,
                        softWrap: false,
                        style: theme.textTheme.labelSmall?.copyWith(
                          color: theme.colorScheme.onSurfaceVariant,
                          fontSize: 10,
                        ),
                      ),
                    ),
                  ],
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

class _OutsideOverflowChip extends StatelessWidget {
  final int count;
  final VoidCallback onTap;

  const _OutsideOverflowChip({required this.count, required this.onTap});

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    return Semantics(
      button: true,
      label: A11yLabels.moreAppointments(count),
      onTap: onTap,
      child: ExcludeSemantics(
        child: Material(
          color: theme.colorScheme.secondaryContainer,
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)),
          clipBehavior: Clip.antiAlias,
          child: InkWell(
            onTap: onTap,
            child: Center(
              child: Text(
                '+$count weitere',
                style: theme.textTheme.labelSmall?.copyWith(
                  color: theme.colorScheme.onSecondaryContainer,
                  fontWeight: FontWeight.w600,
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}
