const MINUTES_PER_HOUR = 60;
const DEFAULT_MAX_DURATION_MINUTES = 30 * MINUTES_PER_HOUR;

function normalizeMinutes(minutes: number, maxMinutes = DEFAULT_MAX_DURATION_MINUTES) {
  if (!Number.isFinite(minutes)) {
    return 0;
  }

  return Math.max(0, Math.min(Math.round(minutes), maxMinutes));
}

export function decimalHoursToMinutes(hours: number, maxMinutes = DEFAULT_MAX_DURATION_MINUTES) {
  if (!Number.isFinite(hours)) {
    return 0;
  }

  return normalizeMinutes(hours * MINUTES_PER_HOUR, maxMinutes);
}

export function minutesToDecimalHours(minutes: number) {
  if (!Number.isFinite(minutes)) {
    return 0;
  }

  return Number((minutes / MINUTES_PER_HOUR).toFixed(2));
}

export function getDurationMinutes(
  minutesField?: number | null,
  legacyHoursField?: number | null,
  maxMinutes = DEFAULT_MAX_DURATION_MINUTES
) {
  if (minutesField !== null && minutesField !== undefined && Number.isFinite(minutesField)) {
    return normalizeMinutes(minutesField, maxMinutes);
  }

  if (legacyHoursField !== null && legacyHoursField !== undefined && Number.isFinite(legacyHoursField)) {
    return decimalHoursToMinutes(legacyHoursField, maxMinutes);
  }

  return null;
}

export function minutesToDurationParts(minutes?: number | null) {
  if (minutes === null || minutes === undefined || !Number.isFinite(minutes)) {
    return { hours: null, minutes: null };
  }

  const safeMinutes = Math.max(0, Math.round(minutes));
  return {
    hours: Math.floor(safeMinutes / MINUTES_PER_HOUR),
    minutes: safeMinutes % MINUTES_PER_HOUR
  };
}

export function durationPartsToMinutes(hours?: number | null, minutes?: number | null) {
  if (
    hours === null ||
    hours === undefined ||
    minutes === null ||
    minutes === undefined ||
    !Number.isFinite(hours) ||
    !Number.isFinite(minutes)
  ) {
    return null;
  }

  return Math.max(0, Math.round(hours) * MINUTES_PER_HOUR + Math.round(minutes));
}

export function formatDurationHHMM(minutes?: number | null) {
  if (minutes === null || minutes === undefined || !Number.isFinite(minutes)) {
    return '--:--';
  }

  const parts = minutesToDurationParts(minutes);

  if (parts.hours === null || parts.minutes === null) {
    return '--:--';
  }

  return `${String(parts.hours).padStart(2, '0')}:${String(parts.minutes).padStart(2, '0')}`;
}

export function formatDurationThai(minutes?: number | null) {
  if (minutes === null || minutes === undefined || !Number.isFinite(minutes)) {
    return '-';
  }

  const parts = minutesToDurationParts(minutes);

  if (parts.hours === null || parts.minutes === null) {
    return '-';
  }

  if (parts.hours === 0 && parts.minutes === 0) {
    return '0 นาที';
  }

  if (parts.hours === 0) {
    return `${parts.minutes} นาที`;
  }

  if (parts.minutes === 0) {
    return `${parts.hours} ชั่วโมง`;
  }

  return `${parts.hours} ชั่วโมง ${parts.minutes} นาที`;
}

export function formatDecimalHours(hours?: number | null) {
  if (hours === undefined || hours === null || Number.isNaN(hours)) {
    return '-';
  }

  const formatted = Number.isInteger(hours)
    ? String(hours)
    : hours.toFixed(2).replace(/0+$/, '').replace(/\.$/, '');

  return formatted;
}
