import { useEffect, useMemo, useState } from "react";
import { Link, useParams } from "react-router-dom";
import type { Race } from "../api";
import { ApiError, getRaces } from "../api";
import {
  formatDistance,
  formatRaceDate,
  getRaceStatusClassName,
  getRaceStatusLabel,
  getRaceVisual,
  sortByDateAsc,
} from "../lib";

function getErrorMessage(error: unknown): string {
  if (error instanceof ApiError) {
    return error.message;
  }
  return "Не удалось загрузить старты.";
}

export function RaceDayPage(): JSX.Element {
  const { ymd } = useParams<{ ymd: string }>();
  const [races, setRaces] = useState<Race[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);

  const validYmd = ymd && /^\d{4}-\d{2}-\d{2}$/.test(ymd) ? ymd : null;
  const year = validYmd ? parseInt(validYmd.slice(0, 4), 10) : NaN;

  useEffect(() => {
    if (!validYmd || Number.isNaN(year)) {
      setIsLoading(false);
      setRaces([]);
      return;
    }

    const ac = new AbortController();
    let mounted = true;

    async function load(): Promise<void> {
      setIsLoading(true);
      try {
        const items = await getRaces({ year }, { signal: ac.signal });
        if (!mounted || ac.signal.aborted) {
          return;
        }
        const forDay = items.filter((r) => r.date.slice(0, 10) === validYmd);
        setRaces(sortByDateAsc(forDay));
        setErrorMessage(null);
      } catch (e) {
        if (ac.signal.aborted || !mounted) {
          return;
        }
        setErrorMessage(getErrorMessage(e));
        setRaces([]);
      } finally {
        if (mounted && !ac.signal.aborted) {
          setIsLoading(false);
        }
      }
    }

    void load();
    return () => {
      mounted = false;
      ac.abort();
    };
  }, [validYmd, year]);

  const heading = useMemo(() => {
    if (!validYmd) {
      return "Дата не указана";
    }
    return formatRaceDate(validYmd);
  }, [validYmd]);

  if (!validYmd) {
    return (
      <section className="page page--race-day">
        <div className="race-day-hero">
          <p className="race-day-hero__eyebrow">Страница дня</p>
          <h1 className="page__title">Некорректная дата</h1>
          <Link className="page-link" to="/races">
            Вернуться к календарю стартов
          </Link>
        </div>
      </section>
    );
  }

  return (
    <section className="page page--race-day">
      <section className="race-day-hero" aria-label="Старты дня">
        <Link className="page-link" to="/races">
          ← Календарь стартов
        </Link>
        <p className="race-day-hero__eyebrow">Старты дня</p>
        <h1 className="page__title">{heading}</h1>
        <p className="page__subtitle">
          {isLoading
            ? "Загружаем расписание..."
            : races.length > 0
              ? `Запланировано стартов: ${races.length}`
              : "Проверьте расписание или добавьте старт на эту дату."}
        </p>
      </section>

      {errorMessage ? (
        <p className="page__subtitle page__subtitle--error" role="alert">
          {errorMessage}
        </p>
      ) : null}

      {isLoading ? (
        <p className="page__subtitle" aria-busy="true">
          Загружаем…
        </p>
      ) : null}

      {!isLoading && !errorMessage && races.length === 0 ? (
        <p className="page__subtitle">На эту дату стартов нет.</p>
      ) : null}

      {!isLoading && races.length > 0 ? (
        <ul className="race-day__list">
          {races.map((race) => {
            const visual = getRaceVisual(race);

            return (
              <li key={race.id} className="race-day__item">
                <Link className="race-day__link" to={`/races/${race.id}`}>
                  <img
                    className={`race-day__image${
                      visual.imageFit === "contain" ? " race-day__image--contain" : ""
                    }`}
                    src={visual.imageSrc}
                    alt=""
                    loading="lazy"
                    referrerPolicy="no-referrer"
                    onError={(event) => {
                      event.currentTarget.onerror = null;
                      event.currentTarget.classList.remove("race-day__image--contain");
                      event.currentTarget.src = visual.fallbackSrc;
                    }}
                  />
                  <span className="race-day__body">
                    <span className="race-day__kicker">{visual.label}</span>
                    <span className="race-day__title">{race.title}</span>
                    <span className="race-day__meta">
                      {formatDistance(race.distanceKm)} ·{" "}
                      <span className={getRaceStatusClassName(race.status, race.date)}>
                        {getRaceStatusLabel(race.status, race.date)}
                      </span>
                    </span>
                  </span>
                </Link>
              </li>
            );
          })}
        </ul>
      ) : null}

      <div className="race-day__actions">
        <Link className="btn btn--primary" to={`/races/new?date=${validYmd}`}>
          Добавить
        </Link>
      </div>
    </section>
  );
}
