export enum DateFormat {
  //'yyyy-mm-dd'
  YYYYhMMhDD,
  //'yyyy-mm-dd HH:mm:ss'
  YYYYhMMhDDkHHdMMdSS,
  //'yyyy-mm-dd HH:mm:ss.sss'
  YYYYhMMhDDkHHdMMdSSdSSS,
  //yyyy/mm/dd
  YYYYxMMxDD,
  //yyyy/mm/dd HH:mm:ss
  YYYYxMMxDDkHHdMMdSS,
  //yyyy/mm/dd HH:mm:ss.sss
  YYYYxMMxDDkHHdMMdSSdSSS,
  //yyyy年mm月dd
  YYYYnMMyDDr,
  //yyyy年mm月dd日 HH:mm:ss
  YYYYnMMyDDrkHHdMMdSS,
  //yyyy年mm月dd日 HH:mm:ss.sss
  YYYYnMMyDDrkHHdMMdSSdSSS,
}

export class DateUtils {
  static formatDateStr(nowData: Date | undefined | null, format: DateFormat | undefined | null): string {
    if (nowData == null || nowData == undefined) {
      nowData = new Date();
    }
    //年
    let year = nowData.getFullYear()
    //月
    let month = ("0" + (nowData.getMonth() + 1)).slice(-2); // 月份是从0开始计数的，所以需要加1
    //日
    let day = ("0" + nowData.getDate()).slice(-2); // 为了保证始终是两位数，不足两位前面补0
    //时
    let hours = nowData.getHours()>9?nowData.getHours():`0${nowData.getHours()}`;
    //分
    let minutes = nowData.getMinutes()>9?nowData.getMinutes():`0${nowData.getMinutes()}`;
    //秒
    let seconds = nowData.getSeconds()>9?nowData.getSeconds():`0${nowData.getSeconds()}`;
    //毫秒
    let milliSeconds = nowData.getMilliseconds();
    if (format == null || format == undefined) {
      format = DateFormat.YYYYhMMhDDkHHdMMdSS
    }
    if (format == DateFormat.YYYYhMMhDD) {
      return year + "-" + month + "-" + day
    }
    if (format == DateFormat.YYYYhMMhDDkHHdMMdSS) {
      return year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds
    }
    if (format == DateFormat.YYYYhMMhDDkHHdMMdSSdSSS) {
      return year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds + "." + milliSeconds
    }
    if (format == DateFormat.YYYYxMMxDD) {
      return year + "/" + month + "/" + day
    }
    if (format == DateFormat.YYYYxMMxDDkHHdMMdSS) {
      return year + "/" + month + "/" + day + " " + hours + ":" + minutes + ":" + seconds
    }
    if (format == DateFormat.YYYYxMMxDDkHHdMMdSSdSSS) {
      return year + "/" + month + "/" + day + " " + hours + ":" + minutes + ":" + seconds + "." + milliSeconds
    }
    if (format == DateFormat.YYYYnMMyDDr) {
      return year + "年" + month + "月" + day + "日"
    }
    if (format == DateFormat.YYYYnMMyDDrkHHdMMdSS) {
      return year + "年" + month + "月" + day + "日 " + hours + ":" + minutes + ":" + seconds
    }
    if (format == DateFormat.YYYYnMMyDDrkHHdMMdSSdSSS) {
      return year + "年" + month + "月" + day + "日 " + hours + ":" + minutes + ":" + seconds + "." + milliSeconds
    }
    return year + "-" + month + "-" + day
  }

  static pastStrDate(strDate: string | null): Date | null {
    if (strDate == null) {
      return null;
    }
    let formatting = strDate.trim()
    //   .replaceAll(' ', '')
    //   .replace(' ', '')
    //   .replaceAll('-', "")
    //   .replace('-', "")
    //   .replaceAll('.', "")
    //   .replace('.', "")
    //   .replaceAll('/', "")
    //   .replace('/', "")
    //   .replace('年', "")
    //   .replace('月', "")
    //   .replace('日', "")
    //   .replaceAll(':', "")
    //   .replace(':', "")
    //   .replaceAll('—', "")
    //   .replace('—', "")
    //   .replaceAll('：', "")
    //   .replace('：', "")
    //   .replaceAll('。', "")
    //   .replace('。', "")
    //   .trim()

    let f = new Array();
    for (let i = 0; i < formatting.length; i++) {
      let s = formatting.charAt(i);
      if (!this.isNum(s)) {
        f.push(s)
      }
    }

    for (let i = 0; i < f.length; i++) {
      formatting = formatting.replace(f[i], "")
    }

    switch (formatting.length) {
      case 4:
        return new Date(formatting)
      case 6: //202306
        let y = formatting.substring(0, 4)
        let m = formatting.substring(4, 6)
        return new Date(y + "-" + m)
      case 8: //20230612
        y = formatting.substring(0, 4)
        m = formatting.substring(4, 6)
        let d = formatting.substring(6, 8)
        return new Date(y + "-" + m + "-" + d)
      case 10: //2023061211
        y = formatting.substring(0, 4)
        m = formatting.substring(4, 6)
        d = formatting.substring(6, 8)
        let h = formatting.substring(8, 10)
        return new Date(y + "-" + m + "-" + d + " " + h)
      case 12: //2023061211
        y = formatting.substring(0, 4)
        m = formatting.substring(4, 6)
        d = formatting.substring(6, 8)
        h = formatting.substring(8, 10)
        let f = formatting.substring(10, 12)
        return new Date(y + "-" + m + "-" + d + " " + h + ":" + f)
      case 14: //20230612101533
        y = formatting.substring(0, 4)
        m = formatting.substring(4, 6)
        d = formatting.substring(6, 8)
        h = formatting.substring(8, 10)
        f = formatting.substring(10, 12)
        let ms = formatting.substring(12, 14)
        return new Date(y + "-" + m + "-" + d + " " + h + ":" + f + ":" + ms)
      case 17: //20230612101533333
        y = formatting.substring(0, 4)
        m = formatting.substring(4, 6)
        d = formatting.substring(6, 8)
        h = formatting.substring(8, 10)
        f = formatting.substring(10, 12)
        ms = formatting.substring(12, 14)
        let hms = formatting.substring(14, 17)
        return new Date(y + "-" + m + "-" + d + " " + h + ":" + f + ":" + ms + '.' + hms)
      default :
        return null
    }
  }

  /**
   * 将 "M/D/YY, h:mm A" 时间格式字符 转换成 "yyyy-MM-dd HH:mm:ss"
   * @param dateStr      8/12/25, 3:23 PM
   * @returns             2025-08-12 15:23:00
   */
  static formatMdyHmA(dateStr: string): string {
    if (dateStr == null||dateStr == undefined ||dateStr.toString().trim().length<1) {
      return "";
    }
    // 解析原始时间字符串
    const [datePart, timePart] = dateStr.split(", ");
    const [month, day, year] = datePart.split("/").map(Number);
    const [time, period] = timePart.split(" ");
    const [hoursStr, minutesStr] = time.split(":");
    let hours = parseInt(hoursStr, 10);
    const minutes = parseInt(minutesStr, 10);

    // 处理 AM/PM
    if (period === "PM" && hours < 12) hours += 12;
    if (period === "AM" && hours === 12) hours = 0;

    // 补零操作
    const pad = (num: number) => num.toString().padStart(2, "0");
    return "yyyy-MM-dd HH:mm:ss"
      .replace("yyyy", `${2000 + year}`)  // 假设年份简写为后两位（如25表示2025）
      .replace("MM", pad(month))
      .replace("dd", pad(day))
      .replace("HH", pad(hours))
      .replace("mm", pad(minutes))
      .replace("ss", "00");  // 秒数未提供，默认补零
  }

  /**
   * 数字验证
   *
   * @param val 需要验证的字符串
   */
  public static isNum(val: string): boolean {
    const reg = new RegExp('^[0-9]*$');
    return val != null && "" != (val) && reg.test(val);
  }

  /**
   * 获取日期字符
   * @param nowData 日期
   * @returns yyyy-MM-dd
   */
  static getNowDats(nowData: Date | null): string {
    if (!nowData) {
      nowData = new Date();
    }
    let year = nowData.getFullYear()
    let month = ("0" + (nowData.getMonth() + 1)).slice(-2); // 月份是从0开始计数的，所以需要加1
    let day = ("0" + nowData.getDate()).slice(-2); // 为了保证始终是两位数，不足两位前面补0
    return year + "-" + month + "-" + day
  }

  /**
   * 当获取指定日期工作周的第一天
   * @param nowData
   * @returns yyyy-MM-dd
   */
  static getWeekFirstDay(nowData: Date | null): string {
    if (!nowData) {
      nowData = new Date();
    }
    const currentDay = nowData.getDay(); // 0（星期日）到 6（星期六）
    let firstDay = new Date()
    firstDay.setDate(nowData.getDate() - currentDay + 1)

    return firstDay.getFullYear() + "-" + ("0" + (firstDay.getMonth() + 1)).slice(-2) + "-" +
    ("0" + firstDay.getDate()).slice(-2);
  }

  /**
   * 当获取指定日期工作周的最后一天时间
   * @param nowData
   * @returns yyyy-MM-dd
   */
  static getWeekLastDay(nowData: Date | null): string {
    if (!nowData) {
      nowData = new Date();
    }
    const currentDay = nowData.getDay(); // 0（星期日）到 6（星期六）
    let lastDay = new Date()
    lastDay.setDate(nowData.getDate() + (6 - currentDay + 1))

    return lastDay.getFullYear() + "-" + ("0" + (lastDay.getMonth() + 1)).slice(-2) + "-" +
    ("0" + lastDay.getDate()).slice(-2);

  }

  /**
   * 获取指定日期所在月份的最后一天
   * @param nowData
   * @returns yyyy-MM-dd
   */
  static getLastDayOfMonth(nowData: Date | null): string {
    if (!nowData) {
      nowData = new Date();
    }
    let year = nowData.getFullYear(); // 获取当前年份
    let month = nowData.getMonth(); // 获取当前月份（从0开始）
    // 创建一个表示当前月份最后一天的Date对象
    let lastDayOfMonth = new Date(year, month + 1, 0);
    return lastDayOfMonth.getFullYear() + "-" + ("0" + (lastDayOfMonth.getMonth() + 1)).slice(-2) + "-" +
    ("0" + lastDayOfMonth.getDate()).slice(-2);
  }

  /**
   * 获取当前日期是第几周
   * @param dateTime 当前传入的日期值
   * @returns 返回第几周数字值
   */
  static getWeek(dateTime: Date): number {
    const temptTime = new Date(dateTime);
    const weekday = temptTime.getDay() || 7; // 周几 (0-6，0代表星期天)

    // 调整日期到上周一
    temptTime.setDate(temptTime.getDate() - weekday + 1);
    const firstDay = new Date(temptTime.getFullYear(), 0, 1);

    // 获取第一周的第一天
    const dayOfWeek = firstDay.getDay();
    const spendDay = dayOfWeek === 0 ? 7 : 7 - dayOfWeek + 1;

    // 计算周数
    const startOfYear = new Date(temptTime.getFullYear(), 0, 1 + spendDay);
    const days = Math.ceil((temptTime.getTime() - startOfYear.getTime()) / 86400000);
    return Math.ceil(days / 7);
  }

  /**
   * 将时间转换为 `几秒前`、`几分钟前`、`几小时前`、`几天前`
   * @param param 当前时间，new Date() 格式或者字符串时间格式
   * @param format 需要转换的时间格式字符串
   * @returns 返回拼接后的时间字符串
   */
  static formatPast(param: string | Date, format: string = 'YYYY-mm-dd'): string {
    const time = new Date().getTime();
    let t = typeof param === 'string' || param instanceof Date ? new Date(param).getTime() : param;
    const diff = time - t;

    if (diff < 10000) {
      return '刚刚';
    } // 10秒内
    if (diff < 60000) {
      return `${Math.floor(diff / 1000)}秒前`;
    } // 少于1分钟
    if (diff < 3600000) {
      return `${Math.floor(diff / 60000)}分钟前`;
    } // 少于1小时
    if (diff < 86400000) {
      return `${Math.floor(diff / 3600000)}小时前`;
    } // 少于24小时
    if (diff < 259200000) {
      return `${Math.floor(diff / 86400000)}天前`;
    } // 少于3天

    return DateUtils.formatDate(new Date(param), format); // 超过3天
  }

  /**
   * 时间日期转换
   * @param date 当前时间，new Date() 格式
   * @param format 需要转换的时间格式字符串
   * @returns 返回拼接后的时间字符串
   */
  static formatDate(date: Date, format: string): string {
    const week: { [key: string]: string } = {
      '0': '日',
      '1': '一',
      '2': '二',
      '3': '三',
      '4': '四',
      '5': '五',
      '6': '六',
    };
    const quarter: { [key: string]: string } = {
      '1': '一',
      '2': '二',
      '3': '三',
      '4': '四'
    };

    const we = date.getDay(); // 星期
    const z = DateUtils.getWeek(date); // 周
    const qut = Math.floor((date.getMonth() + 3) / 3).toString(); // 季度

    const opt: { [key: string]: string } = {
      'Y+': date.getFullYear().toString(),
      'm+': (date.getMonth() + 1).toString(),
      'd+': date.getDate().toString(),
      'H+': date.getHours().toString(),
      'M+': date.getMinutes().toString(),
      'S+': date.getSeconds().toString(),
      'q+': quarter[qut], // 季度
    };

    // 处理格式中的特殊标记
    format = format.replace(/(W+)/, (match) => match.length > 1 ? `周${week[we]}` : week[we]);
    format = format.replace(/(Q+)/, (match) => match.length === 4 ? `第${quarter[qut]}季度` : quarter[qut]);
    format = format.replace(/(Z+)/, (match) => match.length === 3 ? `第${z}周` : `${z}`);

    // 替换日期格式中的部分
    Object.keys(opt).forEach((key) => {
      const reg = new RegExp(`(${key})`);
      format = format.replace(reg, (match) => match.length === 1 ? opt[key] : opt[key].padStart(match.length, '0'));
    });

    return format;
  }

  /**
   * 补零操作
   * @param num
   * @returns
   */
  public  static padZero(num: number): string {
    return num.toString().padStart(2, "0");
  }
}