import 'package:fis_i18n/i18n.dart';
import 'package:flyinsono/pages/schedule/calendar/utils/chinese_calendar_utils.dart';
import 'package:intl/intl.dart';

extension StringExtension on String {
  /// 利用 0 宽字符打散字符串，实现中文断句
  String breakWord() {
    if (this.isEmpty) {
      return this;
    }
    String result = '';
    for (var element in this.runes) {
      result += String.fromCharCode(element);
      result += '\u200B';
    }
    return result;
  }
}

/// 日历通用工具集
class CalendarUtils {
  ///  获取日期，将 时 分 秒 归 0
  static DateTime getDay(DateTime date) {
    return DateTime(date.year, date.month, date.day);
  }

  /// 传入起始年月，返回35/42个日期
  static List<DateTime> getDaysListByMonth(int year, int month) {
    final maxDaysLength = isNeedExtraRow(year, month) ? 42 : 35;
    final daysList = <DateTime>[];
    final firstDay = DateTime(year, month, 1);
    final firstDayWeek = firstDay.weekday;
    final lastDay = DateTime(year, month + 1, 0);
    final lastDayOfMonth = lastDay.day;
    final lastDayOfLastMonth = DateTime(year, month, 0).day;
    // final today = DateTime.now();

    /// 转换后的 firstDayWeek
    final firstDayWeekIndex = (firstDayWeek) % 7;
    int nextMonthDay = 1;

    // 上个月的日期
    for (var i = 0; i < firstDayWeekIndex; i++) {
      daysList.add(
        DateTime(
            year, month - 1, lastDayOfLastMonth - firstDayWeekIndex + i + 1),
      );
    }

    // 当月的日期
    for (var i = 0;
        (i < lastDayOfMonth) && daysList.length < maxDaysLength;
        i++) {
      daysList.add(
        DateTime(year, month, i + 1),
      );
    }

    while (daysList.length < maxDaysLength) {
      daysList.add(
        DateTime(month == 12 ? year + 1 : year, month == 12 ? 1 : month + 1,
            nextMonthDay),
      );
      nextMonthDay++;
    }
    return daysList;
  }

  /// 传入起始时间，返回42个日期
  static List<DateTime> get42DaysListByDateTime(DateTime date) {
    final daysList = <DateTime>[];
    final firstDay = DateTime(date.year, date.month, 1);
    final firstDayWeek = firstDay.weekday;
    if (firstDayWeek == 7) {
      /// 如果第一天为周日，直接返回接下来的42天
      for (var i = 0; i < 42; i++) {
        daysList.add(
          DateTime(date.year, date.month, i + 1),
        );
      }
    } else {
      /// 否则，先要补全上个月的日期
      for (var i = firstDayWeek; i > 0; i--) {
        daysList.add(
          DateTime(date.year, date.month, 1 - i),
        );
      }

      /// 再补全剩余天数
      for (var i = 0; i < 42 - firstDayWeek; i++) {
        daysList.add(
          DateTime(date.year, date.month, i + 1),
        );
      }
    }
    assert(daysList.length == 42);
    return daysList;
  }

  /// 传入起始时间，返回42个日期的起始和结束时间
  static List<DateTime> get42DaysStartEndByDateTime(DateTime date) {
    final daysList = <DateTime>[];
    final firstDay = DateTime(date.year, date.month, 1);
    final firstDayWeek = firstDay.weekday;
    if (firstDayWeek == 7) {
      daysList.add(
        DateTime(date.year, date.month, 1),
      );
      daysList.add(
        DateTime(date.year, date.month, 42),
      );
    } else {
      daysList.add(
        DateTime(date.year, date.month, 1 - firstDayWeek),
      );
      daysList.add(
        DateTime(date.year, date.month, 42 - firstDayWeek),
      );
    }
    assert(daysList.length == 2);
    return daysList;
  }

  /// 计算是否需要显示六行日期，一般为5行，但是有时候会有6行
  static bool isNeedExtraRow(int year, int month) {
    final firstDay = DateTime(year, month, 1);
    final firstDayWeek = firstDay.weekday;
    final lastDay = DateTime(year, month + 1, 0);
    final lastDayOfMonth = lastDay.day;

    /// 转换后的firstDayWeek，%7是因为DateTime的weekday是从周日开始的，而我们的日历是从周一开始的
    final firstDayWeekIndex = (firstDayWeek) % 7;
    return firstDayWeekIndex + lastDayOfMonth > 35;
  }

  /// 获取下个月
  static DateTime getNextMonth(DateTime date) {
    final year = date.year;
    final month = date.month;
    if (month == 12) {
      return DateTime(year + 1, 1);
    } else {
      return DateTime(year, month + 1);
    }
  }

  /// 获取上个月
  static DateTime getPreviousMonth(DateTime date) {
    final year = date.year;
    final month = date.month;
    if (month == 1) {
      return DateTime(year - 1, 12);
    } else {
      return DateTime(year, month - 1);
    }
  }

  /// 获取x个月后的日期
  static DateTime getMonthAfter(DateTime date, int x) {
    int year = date.year;
    int month = date.month;
    int monthAfter = month + x;
    int yearAfter = year;
    if (monthAfter > 12) {
      yearAfter += (monthAfter ~/ 12);
      monthAfter = monthAfter % 12;
    }
    return DateTime(yearAfter, monthAfter);
  }

  /// 是否是同一个月
  static bool isSameMonth(DateTime date1, DateTime date2) {
    return date1.year == date2.year && date1.month == date2.month;
  }

  /// 年月格式化 返回 e.g. 2021年12月
  static String formatYearMonth(DateTime date) {
    return i18nBook.calendar.yearAndMonth.translate(
      [
        date.year.toString(),
        date.month.toString(),
      ],
    );
  }

  /// 获取开始时间 e.g. 12:00
  static String getStartTime(DateTime? startTime) {
    if (startTime == null) {
      return i18nBook.calendar.allDay.t;
    }
    return DateFormat('HH:mm').format(startTime);
  }

  static String getWeekMap(int week) {
    switch (week) {
      case 1:
        return i18nBook.calendar.monday.t;
      case 2:
        return i18nBook.calendar.tuesday.t;
      case 3:
        return i18nBook.calendar.wednesday.t;
      case 4:
        return i18nBook.calendar.thursday.t;
      case 5:
        return i18nBook.calendar.friday.t;
      case 6:
        return i18nBook.calendar.saturday.t;
      case 7:
        return i18nBook.calendar.sunday.t;
      default:
        return '';
    }
  }

  static String getSingleWeekMap(int week) {
    switch (week) {
      case 1:
        return i18nBook.calendar.singleMonday.t;
      case 2:
        return i18nBook.calendar.singleTuesday.t;
      case 3:
        return i18nBook.calendar.singleWednesday.t;
      case 4:
        return i18nBook.calendar.singleThursday.t;
      case 5:
        return i18nBook.calendar.singleFriday.t;
      case 6:
        return i18nBook.calendar.singleSaturday.t;
      case 7:
        return i18nBook.calendar.singleSunday.t;
      default:
        return '';
    }
  }

  /// 格式化时间段例如：
  /// ZH：12月12日 周一 12:00 - 13:00
  /// EN：12/12 Mon 12:00 - 13:00
  /// 如果不同天
  /// 12月12日 周一 12:00 - 12月13日 周二 13:00
  /// 12/12 Mon 12:00 - 12/13 Tue 13:00
  static String formatDateRange(DateTime? start, DateTime? end) {
    if (start == null || end == null) {
      return i18nBook.calendar.allDay.t;
    }
    if (isSameDay(start, end)) {
      return '${DateFormat(i18nBook.calendar.monthAndDayFormat.t).format(start)} ${getWeekMap(start.weekday)} ${DateFormat('HH:mm').format(start)} - ${DateFormat('HH:mm').format(end)}';
    } else {
      return '${DateFormat('${i18nBook.calendar.monthAndDayFormat.t} HH:mm').format(start)} - ${DateFormat('${i18nBook.calendar.monthAndDayFormat.t} HH:mm').format(end)}';
    }
  }

  /// 格式化时间段例如：
  /// ZH：12:00 - 13:00
  /// EN：12:00 - 13:00
  /// 如果不同天
  /// 12月12日 12:00 - 12月13日 13:00
  /// 12/12 12:00 - 12/13 13:00
  static String formatTimeRange(DateTime? start, DateTime? end) {
    if (start == null || end == null) {
      return i18nBook.calendar.allDay.t;
    }
    if (isSameDay(start, end)) {
      return '${DateFormat('HH:mm').format(start)} - ${DateFormat('HH:mm').format(end)}';
    } else {
      return '${DateFormat('${i18nBook.calendar.monthAndDayFormat.t} HH:mm').format(start)} - ${DateFormat('${i18nBook.calendar.monthAndDayFormat.t} HH:mm').format(end)}';
    }
  }

  /// 另一种格式化时间段例如：
  /// ZH：2023-12-12 12:00 - 13:00
  /// EN：2023-12-12 12:00 - 13:00
  static String formatDateRangeWithYear(DateTime? start, DateTime? end) {
    if (start == null || end == null) {
      return i18nBook.calendar.allDay.t;
    }
    if (isSameDay(start, end)) {
      return '${DateFormat('yyyy-MM-dd HH:mm').format(start)} - ${DateFormat('HH:mm').format(end)}';
    } else {
      return '${DateFormat('yyyy-MM-dd HH:mm').format(start)} - ${DateFormat('yyyy-MM-dd HH:mm').format(end)}';
    }
  }

  /// 获取节气和农历日
  static String getLunarDay(DateTime date) {
    ChineseCalendarInfo lunarDate = ChineseCalendarUtils.getInfo(date);
    return lunarDate.term ?? lunarDate.lunarDayName ?? '';
  }

  /// 格式化为日期例如：2023-02-01
  static String formatDate(DateTime date) {
    return DateFormat('yyyy-MM-dd').format(date);
  }

  /// 格式化为日期例如：2023-02-01 10:15
  static String formatDateTime(DateTime date) {
    return DateFormat('yyyy-MM-dd HH:mm').format(date);
  }

  /// 判定是否在同一天
  static bool isSameDay(DateTime? date1, DateTime? date2) {
    if (date1 == null || date2 == null) {
      return false;
    }
    return date1.year == date2.year &&
        date1.month == date2.month &&
        date1.day == date2.day;
  }

  /// 分钟数转为时间段字符串
  /// 例如：120min -> 2h
  /// 例如：121min -> 2h1min
  /// 例如：60min -> 1h
  /// 例如：59min -> 59min
  static String minutesToDuration(int minutes) {
    if (minutes < 60) {
      return '$minutes${i18nBook.calendar.minute4Duration.t}';
    } else {
      int hour = minutes ~/ 60;
      int min = minutes % 60;
      if (min == 0) {
        return '$hour${i18nBook.calendar.hour4Duration.t}';
      } else {
        return '$hour${i18nBook.calendar.hour4Duration.t}$min${i18nBook.calendar.minute4Duration.t}';
      }
    }
  }
}
