class HijriDate {
  final int year;
  final int month;
  final int day;

  const HijriDate({
    required this.year,
    required this.month,
    required this.day,
  });
}

class HijriDateFormatter {
  HijriDateFormatter._();

  static const List<String> _monthNames = [
    'Muharram',
    'Safar',
    'Rabiul Awal',
    'Rabiul Akhir',
    'Jumadil Awal',
    'Jumadil Akhir',
    'Rajab',
    'Syaban',
    'Ramadan',
    'Syawal',
    'Zulkaidah',
    'Zulhijah',
  ];

  static String format(DateTime date) {
    final hijri = fromGregorian(date);
    final monthName = _monthNames[hijri.month - 1];
    return '${hijri.day} $monthName ${hijri.year} H';
  }

  // Tabular Islamic calendar conversion. This is deterministic and avoids
  // adding a new dependency just to replace the hardcoded placeholder dates.
  static HijriDate fromGregorian(DateTime date) {
    final jd = _gregorianToJulianDay(date.year, date.month, date.day);

    var l = jd - 1948440 + 10632;
    final n = ((l - 1) ~/ 10631);
    l = l - 10631 * n + 354;

    final j = (((10985 - l) ~/ 5316) * ((50 * l) ~/ 17719)) +
        ((l ~/ 5670) * ((43 * l) ~/ 15238));

    l = l -
        (((30 - j) ~/ 15) * ((17719 * j) ~/ 50)) -
        ((j ~/ 16) * ((15238 * j) ~/ 43)) +
        29;

    final month = (24 * l) ~/ 709;
    final day = l - ((709 * month) ~/ 24);
    final year = 30 * n + j - 30;

    return HijriDate(year: year, month: month, day: day);
  }

  static int _gregorianToJulianDay(int year, int month, int day) {
    final a = (14 - month) ~/ 12;
    final y = year + 4800 - a;
    final m = month + 12 * a - 3;

    return day +
        ((153 * m + 2) ~/ 5) +
        365 * y +
        (y ~/ 4) -
        (y ~/ 100) +
        (y ~/ 400) -
        32045;
  }
}
