import { dayjs } from '@blocklet/payment-react';

export default dayjs;

/**
 * Time unit type definition
 */
export type TimeUnit = 'hour' | 'day' | 'week' | 'month' | 'year';

/**
 * Format options interface
 */
interface FormatDurationOptions {
  t: (key: string, options?: Record<string, any>) => string;
  pluralSuffix?: string;
  separator?: string;
}

/**
 * Conversion rule type
 */
export type ConversionRule = {
  threshold: number;
  convert: (value: number) => { main: number; remainder: number };
  format: (main: number, remainder: number, value: number) => Array<[TimeUnit, number]>;
};
/**
 * Smart duration formatter optimized for subscription periods
 *
 * Display Rules:
 * 1. Hours:
 *    - < 24h: show hours (e.g., "5 hours")
 *    - 24-47h: show days and hours (e.g., "1 day 5 hours")
 *    - >= 48h: convert to days
 *
 * 2. Days:
 *    - < 7 days: show days (e.g., "5 days")
 *    - 7-13 days: show 1 week + days (e.g., "1 week 3 days")
 *    - 14+ days: show weeks if divisible, else days (e.g., "2 weeks" or "15 days")
 *    - 30+ days: show months if divisible, else weeks/days (e.g., "1 month" or "5 weeks")
 *
 * 3. Weeks:
 *    - < 4 weeks: show weeks (e.g., "3 weeks")
 *    - 4-7 weeks: show 1 month + weeks (e.g., "1 month 2 weeks")
 *    - 8+ weeks: show months if divisible, else weeks (e.g., "2 months" or "9 weeks")
 *
 * 4. Months:
 *    - < 12: show months (e.g., "6 months")
 *    - 12+: show years if divisible, else months (e.g., "1 year" or "15 months")
 */
export const formatSmartDuration = (
  value: number,
  unit: TimeUnit,
  { t, separator = ' ' }: FormatDurationOptions
): string => {
  // Format single unit
  const formatUnit = (val: number, unitType: TimeUnit): string => {
    return `${val || 0} ${t(`common.${unitType}${val > 1 ? 's' : ''}`).toLowerCase()}`;
  };

  // Convert to largest possible unit
  const convertToLargest = (val: number, fromUnit: TimeUnit): [TimeUnit, number][] => {
    switch (fromUnit) {
      case 'hour': {
        if (val < 24) return [['hour', val]];
        if (val < 48)
          return [
            ['day', Math.floor(val / 24)],
            ['hour', val % 24],
          ];
        const days = Math.floor(val / 24);
        return convertToLargest(days, 'day');
      }
      case 'day': {
        if (val < 7) return [['day', val]];
        if (val < 14)
          return [
            ['week', Math.floor(val / 7)],
            ['day', val % 7],
          ];
        if (val < 30) return val % 7 === 0 ? [['week', val / 7]] : [['day', val]];
        const years = Math.floor(val / 365);
        const remainingDays = val % 365;
        const months = Math.floor(remainingDays / 30);
        if (years > 0) {
          return months > 0
            ? [
                ['year', years],
                ['month', months],
              ]
            : [['year', years]];
        }
        return months > 0
          ? [
              ['month', months],
              ['week', Math.floor((remainingDays % 30) / 7)],
            ]
          : [['week', Math.floor(val / 7)]];
      }
      case 'week': {
        if (val < 4) return [['week', val]];
        if (val < 8)
          return [
            ['month', Math.floor(val / 4)],
            ['week', val % 4],
          ];
        const months = Math.floor(val / 4);
        return convertToLargest(months, 'month');
      }
      case 'month': {
        const years = Math.floor(val / 12);
        const months = val % 12;
        if (years > 0) {
          if (months > 0) {
            return [
              ['year', years],
              ['month', months],
            ];
          }
          return [['year', years]];
        }
        return [['month', val]];
      }
      case 'year':
        return [['year', val]];
      default:
        return [[fromUnit, val]];
    }
  };

  // Get units and filter out zero values
  const units = convertToLargest(value, unit).filter(([, val]) => val > 0);
  if (units.length === 0) return formatUnit(0, unit);
  // Format all units
  return units.map(([u, val]) => formatUnit(val, u)).join(separator);
};
