/**
 * 可接受的日期输入类型
 */
type DateInput = Date | string | number;

/**
 * 时间单位类型
 */
type TimeUnit = 'year' | 'month' | 'day' | 'hour' | 'minute' | 'second';

/**
 * 时间段类型
 */
type RangeType = 'today' | 'week' | 'month' | 'year';

/**
 * 时间范围对象
 */
export interface TimeRange {
  start: Date;
  end: Date;
}

/**
 * 格式化日期后的完整对象
 */
interface FormattedDate {
  date: string;
  datetime: string;
  iso: string;
}

/**
 * 近七天时间范围返回结构
 */
export interface Last7DaysRange {
  startTime: Date;
  endTime: Date;
  startTimeStr: FormattedDate;
  endTimeStr: FormattedDate;
  startTimestamp: number;
  endTimestamp: number;
}

/**
 * 格式化日期为指定格式
 * @param date - 日期对象、字符串或时间戳
 * @param format - 格式模板，如 'YYYY-MM-DD HH:mm:ss'
 * @param format - 格式模板，如 'YYYY-MM-DD HH:mm:ss'
 * @returns 格式化后的日期字符串
 */
export function formatDate(date: DateInput, format = 'YYYY-MM-DD HH:mm:ss'): string {
  const d = new Date(date);

  const map: Record<string, string | number> = {
    YYYY: d.getFullYear(),
    MM: String(d.getMonth() + 1).padStart(2, '0'),
    DD: String(d.getDate()).padStart(2, '0'),
    HH: String(d.getHours()).padStart(2, '0'),
    mm: String(d.getMinutes()).padStart(2, '0'),
    ss: String(d.getSeconds()).padStart(2, '0'),
  };

  return format.replace(/YYYY|MM|DD|HH|mm|ss/g, (match) => String(map[match]));
}

// 使用示例
// formatDate(new Date(), 'YYYY-MM-DD');           // "2026-03-16"
// formatDate(Date.now(), 'YYYY年MM月DD日');        // "2026年03月16日"
// formatDate('2026-03-16', 'MM/DD/YYYY HH:mm');   // "03/16/2026 08:00"

/**
 * 计算相对于当前时间的友好提示
 * @param date - 目标日期
 * @returns 友好时间描述
 */
function timeAgo(date: DateInput): string {
  const now = new Date();
  const past = new Date(date);
  const diff = now.getTime() - past.getTime();

  const seconds = Math.floor(diff / 1000);
  const minutes = Math.floor(seconds / 60);
  const hours = Math.floor(minutes / 60);
  const days = Math.floor(hours / 24);
  const months = Math.floor(days / 30);
  const years = Math.floor(days / 365);

  if (seconds < 60) return '刚刚';
  if (minutes < 60) return `${minutes}分钟前`;
  if (hours < 24) return `${hours}小时前`;
  if (days < 30) return `${days}天前`;
  if (months < 12) return `${months}个月前`;
  return `${years}年前`;
}

// 使用示例
// timeAgo(Date.now() - 1000 * 60 * 5);   // "5分钟前"
// timeAgo('2026-03-14');                  // "2天前"

/**
 * 对日期进行加减运算
 * @param date - 基准日期
 * @param amount - 数量（可为负数）
 * @param unit - 单位：year|month|day|hour|minute|second
 * @returns 运算后的新 Date 对象
 */
function addTime(date: DateInput, amount: number, unit: TimeUnit): Date {
  const d = new Date(date);

  const map: Record<TimeUnit, string> = {
    year: 'FullYear',
    month: 'Month',
    day: 'Date',
    hour: 'Hours',
    minute: 'Minutes',
    second: 'Seconds',
  };

  const method = `set${map[unit]}` as keyof Date;
  const getMethod = `get${map[unit]}` as keyof Date;

  (d as any)[method]((d as any)[getMethod]() + amount);
  return d;
}

// 使用示例
// addTime(new Date(), 3, 'day');      // 3天后
// addTime(new Date(), -1, 'month');   // 1个月前
// addTime('2026-03-16', 2, 'year');   // 2028-03-16

/**
 * 获取指定时间段的开始和结束时间
 * @param type - 时间段类型
 * @param date - 基准日期，默认为今天
 * @returns 包含 start 和 end 的对象
 */
function getTimeRange(type: RangeType, date: Date = new Date()): TimeRange {
  const d = new Date(date);
  let start: Date;
  let end: Date;

  switch (type) {
    case 'today':
      start = new Date(d.setHours(0, 0, 0, 0));
      end = new Date(d.setHours(23, 59, 59, 999));
      break;
    case 'week': {
      const day = d.getDay() || 7; // 周日设为7
      start = new Date(d.setDate(d.getDate() - day + 1));
      start.setHours(0, 0, 0, 0);
      end = new Date(d.setDate(start.getDate() + 6));
      end.setHours(23, 59, 59, 999);
      break;
    }
    case 'month':
      start = new Date(d.getFullYear(), d.getMonth(), 1);
      end = new Date(d.getFullYear(), d.getMonth() + 1, 0, 23, 59, 59, 999);
      break;
    case 'year':
      start = new Date(d.getFullYear(), 0, 1);
      end = new Date(d.getFullYear(), 11, 31, 23, 59, 59, 999);
      break;
    default:
      // 兜底处理，理论上不会进入
      start = new Date(d.setHours(0, 0, 0, 0));
      end = new Date(d.setHours(23, 59, 59, 999));
  }

  return { start, end };
}

// 使用示例
// getTimeRange('today');   // 今天 00:00:00 ~ 23:59:59
// getTimeRange('week');    // 本周一 00:00:00 ~ 本周日 23:59:59
// getTimeRange('month');   // 本月1号 00:00:00 ~ 本月最后一天 23:59:59

/**
 * 将秒数转换为可读的持续时间
 * @param seconds - 秒数
 * @param showSeconds - 是否显示秒
 * @returns 格式化后的时长字符串
 */
function formatDuration(seconds: number, showSeconds = true): string {
  const hours = Math.floor(seconds / 3600);
  const minutes = Math.floor((seconds % 3600) / 60);
  const secs = Math.floor(seconds % 60);

  const parts: string[] = [];
  if (hours > 0) parts.push(`${hours}小时`);
  if (minutes > 0 || hours > 0) parts.push(`${minutes}分钟`);
  if (showSeconds && (secs > 0 || parts.length === 0)) {
    parts.push(`${secs}秒`);
  }

  return parts.join('') || '0秒';
}

// 使用示例
// formatDuration(3665);      // "1小时1分钟5秒"
// formatDuration(125, false); // "2分钟"
// formatDuration(45);         // "45秒"

/**
 * 判断是否为闰年
 * @param year - 年份
 */
function isLeapYear(year: number): boolean {
  return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
}

/**
 * 获取某月的天数
 * @param year - 年份
 * @param month - 月份（1-12）
 */
function getDaysInMonth(year: number, month: number): number {
  return new Date(year, month, 0).getDate();
}

/**
 * 判断是否为工作日（周一至周五）
 * @param date - 日期
 */
function isWeekday(date: DateInput): boolean {
  const day = new Date(date).getDay();
  return day !== 0 && day !== 6;
}

// 使用示例
// isLeapYear(2024);              // true
// getDaysInMonth(2026, 2);         // 28
// isWeekday('2026-03-16');       // true (周一)

/**
 * 将 ISO 字符串转为时间戳
 * @param isoString - ISO 8601 格式字符串
 * @returns 毫秒时间戳
 */
export function toTimestamp(isoString: string): number {
  return new Date(isoString).getTime();
}

/**
 * 获取近七天的开始和结束时间
 * @returns 包含开始时间、结束时间及其各种格式的对象
 */
export function getLast7DaysRange(): Last7DaysRange {
  const endDate = new Date();
  const startDate = new Date();

  // 结束时间：今天 23:59:59.999
  endDate.setHours(23, 59, 59, 999);

  // 开始时间：7天前 00:00:00.000（今天也算一天，所以减6）
  startDate.setDate(startDate.getDate() - 6);
  startDate.setHours(0, 0, 0, 0);

  return {
    startTime: startDate,
    endTime: endDate,
    startTimeStr: formatDates(startDate),
    endTimeStr: formatDates(endDate),
    startTimestamp: startDate.getTime(),
    endTimestamp: endDate.getTime(),
  };
}

/**
 * 格式化日期为常用字符串格式
 * @param date - 日期
 * @returns 包含 date、datetime、iso 的对象
 */
function formatDates(date: DateInput): FormattedDate {
  const d = new Date(date);
  const year = d.getFullYear();
  const month = String(d.getMonth() + 1).padStart(2, '0');
  const day = String(d.getDate()).padStart(2, '0');
  const hours = String(d.getHours()).padStart(2, '0');
  const minutes = String(d.getMinutes()).padStart(2, '0');
  const seconds = String(d.getSeconds()).padStart(2, '0');

  return {
    date: `${year}-${month}-${day}`,
    datetime: `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`,
    iso: d.toISOString(),
  };
}

// ============ 使用示例 ============

// const range = getLast7DaysRange();

// console.log('近七天时间范围：');
// console.log('开始时间对象:', range.startTime);
// console.log('结束时间对象:', range.endTime);
// console.log('开始日期:', range.startTimeStr.date);      // 2026-03-24
// console.log('结束日期:', range.endTimeStr.date);        // 2026-03-30
// console.log('开始时间戳:', range.startTimestamp);
// console.log('结束时间戳:', range.endTimestamp);