import type { Race } from "../api";

const MS_IN_DAY = 24 * 60 * 60 * 1000;

/** API date: YYYY-MM-DD или ISO-строка от сериализации (не склеивать с «T00:00:00» повторно). */
export function parseRaceDate(date: string): Date {
  const ymd = date.slice(0, 10);
  if (/^\d{4}-\d{2}-\d{2}$/.test(ymd)) {
    return new Date(`${ymd}T00:00:00`);
  }
  const parsed = new Date(date);
  return parsed;
}

/** Дата старта (календарный день) строго раньше сегодняшней полуночи по локали. */
export function isRaceDateInPast(raceDate: string, now: Date = new Date()): boolean {
  const today = new Date(now);
  today.setHours(0, 0, 0, 0);
  return parseRaceDate(raceDate).getTime() < today.getTime();
}

export function parseFinishTimeToSeconds(value: string | null): number | null {
  if (!value) {
    return null;
  }

  const parts = value.split(":").map((part) => Number(part));
  if (parts.some((part) => Number.isNaN(part) || part < 0)) {
    return null;
  }

  if (parts.length === 2) {
    const [minutes, seconds] = parts;
    return minutes * 60 + seconds;
  }

  if (parts.length === 3) {
    const [hours, minutes, seconds] = parts;
    return hours * 3600 + minutes * 60 + seconds;
  }

  return null;
}

export function formatDistance(distanceKm: number): string {
  return `${distanceKm.toLocaleString("ru-RU", { maximumFractionDigits: 1 })} км`;
}

export function formatRaceDate(date: string): string {
  return parseRaceDate(date).toLocaleDateString("ru-RU", {
    day: "2-digit",
    month: "long",
    year: "numeric",
  });
}

export function sortByDateAsc(races: Race[]): Race[] {
  return [...races].sort((left, right) => parseRaceDate(left.date).getTime() - parseRaceDate(right.date).getTime());
}

export function sortByDateDesc(races: Race[]): Race[] {
  return [...races].sort((left, right) => parseRaceDate(right.date).getTime() - parseRaceDate(left.date).getTime());
}

export function splitRacesByDate(races: Race[], now: Date = new Date()): { upcoming: Race[]; past: Race[] } {
  const today = new Date(now);
  today.setHours(0, 0, 0, 0);

  const upcoming: Race[] = [];
  const past: Race[] = [];

  for (const race of races) {
    if (parseRaceDate(race.date).getTime() >= today.getTime()) {
      upcoming.push(race);
    } else {
      past.push(race);
    }
  }

  return {
    upcoming: sortByDateAsc(upcoming),
    past: sortByDateDesc(past),
  };
}

function pluralizeDays(n: number): string {
  const mod10 = n % 10;
  const mod100 = n % 100;

  if (mod100 >= 11 && mod100 <= 19) {
    return "дней";
  }
  if (mod10 === 1) {
    return "день";
  }
  if (mod10 >= 2 && mod10 <= 4) {
    return "дня";
  }
  return "дней";
}

export function getRaceCountdownLabel(date: string, now: Date = new Date()): string {
  const today = new Date(now);
  today.setHours(0, 0, 0, 0);

  const target = parseRaceDate(date);
  const days = Math.ceil((target.getTime() - today.getTime()) / MS_IN_DAY);

  if (days <= 0) {
    return "сегодня";
  }
  return `через ${days} ${pluralizeDays(days)}`;
}

export function isCloseDistance(left: number, right: number): boolean {
  return Math.abs(left - right) < 0.05;
}

export function getPaceLabel(finishTime: string | null, distanceKm: number): string | null {
  const totalSeconds = parseFinishTimeToSeconds(finishTime);
  if (!totalSeconds || distanceKm <= 0) {
    return null;
  }

  const paceSeconds = Math.round(totalSeconds / distanceKm);
  const paceMinutes = Math.floor(paceSeconds / 60);
  const paceRemainder = paceSeconds % 60;

  return `${String(paceMinutes).padStart(2, "0")}:${String(paceRemainder).padStart(2, "0")} /км`;
}

function isPastDateNeedingResult(status: Race["status"], raceDate: string): boolean {
  if (status !== "planned" && status !== "registered") {
    return false;
  }
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  return parseRaceDate(raceDate).getTime() < today.getTime();
}

export function raceNeedsResultEntry(race: Race): boolean {
  return isPastDateNeedingResult(race.status, race.date);
}

export function getRaceStatusClassName(status: Race["status"], raceDate?: string): string {
  const base = "race-card__status";
  let tier = `${base}--planned`;
  if (status === "completed") {
    tier = `${base}--completed`;
  } else if (status === "registered") {
    tier = `${base}--registered`;
  }
  const needs =
    raceDate && isPastDateNeedingResult(status, raceDate) ? ` ${base}--needs-result` : "";
  return `${base} ${tier}${needs}`;
}

export function getRaceStatusLabel(status: Race["status"], raceDate?: string): string {
  if (raceDate && isPastDateNeedingResult(status, raceDate)) {
    return "внесите результат";
  }
  if (status === "completed") {
    return "пробежал";
  }
  if (status === "registered") {
    return "зарегистрирован";
  }
  return "планирую";
}
