import 'package:flutter/material.dart';
import 'package:jiffy/jiffy.dart';

extension IsSameDay on DateTime {
  bool isSameDay(DateTime other) =>
      year == other.year && month == other.month && day == other.day;

  DateTime nextWeekday(int day) =>
      addDays((day - weekday) % DateTime.daysPerWeek);

  DateTime withTime(TimeOfDay time) =>
      copyWith(hour: time.hour, minute: time.minute);

  TimeOfDay toTimeOfDay() => TimeOfDay(hour: hour, minute: minute);

  bool isSameDateTime(DateTime other) =>
      isSameDay(other) && toTimeOfDay() == other.toTimeOfDay();

  bool isSameOrAfter(DateTime other) => isSameDateTime(other) || isAfter(other);
}

/// Calendar-aware day arithmetic. `DateTime.add(Duration(days: n))` adds real
/// time that drifts ±1h across DST, shifting a whole week onto the wrong
/// calendar day. [addDays]/[subtractDays] normalize through
/// `DateTime(year, month, day + n)` so the wall-clock fields stay fixed.
extension CalendarDayArithmetic on DateTime {
  DateTime addDays(int days) => DateTime(
        year,
        month,
        day + days,
        hour,
        minute,
        second,
        millisecond,
        microsecond,
      );

  DateTime subtractDays(int days) => addDays(-days);
}

/// Formatting helpers backed by Jiffy. Centralises the patterns that previously
/// were repeated as `Jiffy.parseFromDateTime(dt).format(pattern: '...')`.
extension DateTimeFormatting on DateTime {
  String formatHm() => Jiffy.parseFromDateTime(this).format(pattern: 'HH:mm');

  String formatDate() =>
      Jiffy.parseFromDateTime(this).format(pattern: 'dd.MM.yyyy');

  String formatDateTime() =>
      Jiffy.parseFromDateTime(this).format(pattern: 'dd.MM.yyyy HH:mm');

  String formatDateShort() =>
      Jiffy.parseFromDateTime(this).format(pattern: 'dd.MM.');

  String formatDateShortHm() =>
      Jiffy.parseFromDateTime(this).format(pattern: 'dd.MM. HH:mm');

  String formatMonthYear() =>
      Jiffy.parseFromDateTime(this).format(pattern: 'MMMM yyyy');

  String formatRelative() => Jiffy.parseFromDateTime(this).fromNow();

  /// Compact `yyyyMMdd` key, e.g. to identify a week-start in timetable caches.
  String weekKey() => Jiffy.parseFromDateTime(this).format(pattern: 'yyyyMMdd');

  String timeRangeTo(DateTime end) => '${formatHm()} - ${end.formatHm()}';

  String formatDateRelativeShort({DateTime? now}) {
    final reference = now ?? DateTime.now();
    final today = DateTime(reference.year, reference.month, reference.day);
    final self = DateTime(year, month, day);
    final diff = today.difference(self).inDays;

    if (diff == 0) return 'Heute';
    if (diff == 1) return 'Gestern';
    if (diff > 1 && diff <= 6) {
      return Jiffy.parseFromDateTime(this).format(pattern: 'EEEE');
    }
    return formatDate();
  }
}
