import { useCallback, useEffect, useMemo, useState } from "react";
import { Link, useNavigate, useParams } from "react-router-dom";
import { ApiError, deleteRace, getRaceById } from "../api";
import {
  formatDistance,
  formatRaceDate,
  getPaceLabel,
  getRaceStatusClassName,
  getRaceStatusLabel,
  getRaceVisual,
  raceNeedsResultEntry,
} from "../lib";
import type { Race } from "../api";

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

function DetailItem(props: { label: string; value: string | null | undefined }): JSX.Element | null {
  const text = props.value?.trim();
  if (!text) {
    return null;
  }
  return (
    <div className="race-details-meta__item">
      <dt className="race-details-meta__key">{props.label}</dt>
      <dd className="race-details-meta__value">{text}</dd>
    </div>
  );
}

function DetailLink(props: { label: string; url: string | null | undefined }): JSX.Element | null {
  const href = props.url?.trim();
  if (!href) {
    return null;
  }
  return (
    <div className="race-details-meta__item">
      <dt className="race-details-meta__key">{props.label}</dt>
      <dd className="race-details-meta__value">
        <a href={href} target="_blank" rel="noopener noreferrer" className="race-details-meta__link">
          {href}
        </a>
      </dd>
    </div>
  );
}

export function RaceDetailsPage(): JSX.Element {
  const { raceId } = useParams<{ raceId: string }>();
  const navigate = useNavigate();
  const [race, setRace] = useState<Race | null>(null);
  const [isLoading, setIsLoading] = useState<boolean>(true);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);
  const [isDeleting, setIsDeleting] = useState<boolean>(false);
  const [showDeleteConfirm, setShowDeleteConfirm] = useState<boolean>(false);

  useEffect(() => {
    const ac = new AbortController();
    let isMounted = true;

    async function loadRace(): Promise<void> {
      if (!raceId) {
        setErrorMessage("Не найден идентификатор старта.");
        setIsLoading(false);
        return;
      }

      try {
        const item = await getRaceById(raceId, { signal: ac.signal });
        if (!isMounted || ac.signal.aborted) {
          return;
        }
        setRace(item);
        setErrorMessage(null);
      } catch (error) {
        if (ac.signal.aborted || !isMounted) {
          return;
        }
        setErrorMessage(getErrorMessage(error));
      } finally {
        if (isMounted && !ac.signal.aborted) {
          setIsLoading(false);
        }
      }
    }

    void loadRace();
    return () => {
      isMounted = false;
      ac.abort();
    };
  }, [raceId]);

  const paceLabel = useMemo(() => {
    if (!race || race.status !== "completed") {
      return null;
    }
    return getPaceLabel(race.finishTime, race.distanceKm);
  }, [race]);

  const handleDelete = useCallback(async () => {
    if (!raceId) {
      return;
    }
    setIsDeleting(true);
    try {
      await deleteRace(raceId);
      navigate("/races", { replace: true });
    } catch (error) {
      setErrorMessage(error instanceof ApiError ? error.message : "Не удалось удалить старт.");
      setShowDeleteConfirm(false);
    } finally {
      setIsDeleting(false);
    }
  }, [raceId, navigate]);

  if (isLoading) {
    return (
      <section className="page page--race-details" aria-busy="true">
        <h1 className="page__title">Карточка старта</h1>
        <p className="page__subtitle">Загружаем данные старта...</p>
      </section>
    );
  }

  if (errorMessage || !race) {
    return (
      <section className="page page--race-details" role="alert">
        <h1 className="page__title">Карточка старта</h1>
        <p className="page__subtitle page__subtitle--error">{errorMessage ?? "Старт не найден."}</p>
        <Link className="page-link" to="/races">
          Вернуться к списку стартов
        </Link>
      </section>
    );
  }

  const isCompleted = race.status === "completed";
  const visual = getRaceVisual(race);

  return (
    <section className="page page--race-details">
      <section className={`race-details-hero race-details-hero--${visual.variant}`} aria-label="Карточка старта">
        <img
          className={`race-details-hero__image${
            visual.imageFit === "contain" ? " race-details-hero__image--contain" : ""
          }`}
          src={visual.imageSrc}
          alt=""
          loading="eager"
          referrerPolicy="no-referrer"
          onError={(event) => {
            event.currentTarget.onerror = null;
            event.currentTarget.classList.remove("race-details-hero__image--contain");
            event.currentTarget.src = visual.fallbackSrc;
          }}
        />
        <div className="race-details-hero__shade" aria-hidden="true" />
        <div className="race-details-hero__content">
          <Link className="race-details-hero__back" to="/races">
            ← Календарь стартов
          </Link>
          <p className="race-details-hero__eyebrow">{visual.label}</p>
          <h1 className="page__title">{race.title}</h1>
          <p className="page__subtitle">
            {formatRaceDate(race.date)} · {formatDistance(race.distanceKm)}
          </p>
          <span className={getRaceStatusClassName(race.status, race.date)}>
            {getRaceStatusLabel(race.status, race.date)}
          </span>
        </div>
      </section>

      {raceNeedsResultEntry(race) ? (
        <p className="race-details-past-hint" role="status">
          Дата старта уже прошла —{" "}
          <Link className="race-details-past-hint__link" to={`/races/${race.id}/edit`}>
            внесите результат или обновите статус
          </Link>
          .
        </p>
      ) : null}

      <div className="race-details-actions">
        <Link className="btn btn--primary" to={`/races/${race.id}/edit`}>
          Редактировать
        </Link>
        <button
          className="btn btn--danger"
          type="button"
          onClick={() => setShowDeleteConfirm(true)}
        >
          Удалить
        </button>
      </div>

      {showDeleteConfirm ? (
        <div className="confirm-banner" role="alertdialog" aria-label="Подтверждение удаления">
          <p className="confirm-banner__text">Удалить «{race.title}»? Это действие необратимо.</p>
          <div className="confirm-banner__actions">
            <button
              className="btn btn--danger"
              type="button"
              disabled={isDeleting}
              onClick={handleDelete}
            >
              {isDeleting ? "Удаляем…" : "Да, удалить"}
            </button>
            <button
              className="btn btn--secondary"
              type="button"
              disabled={isDeleting}
              onClick={() => setShowDeleteConfirm(false)}
            >
              Отмена
            </button>
          </div>
        </div>
      ) : null}

      <div className="race-details-grid">
        <article className="race-details-card">
          <h2 className="race-details-card__title">Основная информация</h2>
          <dl className="race-details-meta">
            <div className="race-details-meta__item">
              <dt className="race-details-meta__key">Дата</dt>
              <dd className="race-details-meta__value">{formatRaceDate(race.date)}</dd>
            </div>
            <div className="race-details-meta__item">
              <dt className="race-details-meta__key">Дистанция</dt>
              <dd className="race-details-meta__value">{formatDistance(race.distanceKm)}</dd>
            </div>
            <div className="race-details-meta__item">
              <dt className="race-details-meta__key">Статус</dt>
              <dd className="race-details-meta__value">{getRaceStatusLabel(race.status, race.date)}</dd>
            </div>
            <DetailLink label="Сайт организатора" url={race.officialUrl} />
            <DetailItem label="Время старта" value={race.startTime} />
            <DetailItem label="Расписание кластеров" value={race.clusterSchedule} />
            <DetailItem label="Выдача номеров" value={race.bibPickup} />
            <DetailItem label="Стартовый номер" value={race.bibNumber} />
          </dl>
        </article>

        <article className="race-details-card">
          <h2 className="race-details-card__title">Результаты</h2>
          {isCompleted ? (
            <dl className="race-details-meta">
              <div className="race-details-meta__item">
                <dt className="race-details-meta__key">Время</dt>
                <dd className="race-details-meta__value">{race.finishTime ?? "время не указано"}</dd>
              </div>
              <div className="race-details-meta__item">
                <dt className="race-details-meta__key">Темп</dt>
                <dd className="race-details-meta__value">{paceLabel ?? "не удалось вычислить"}</dd>
              </div>
              <DetailItem label="Место" value={race.finishPlace} />
            </dl>
          ) : (
            <p className="race-details-card__empty">
              Метрики появятся после завершения старта и ввода результата.
            </p>
          )}
        </article>
      </div>

      <article className="race-details-card race-details-card--notes">
        <h2 className="race-details-card__title">Заметки</h2>
        <p className="race-details-card__notes">{race.notes?.trim() ? race.notes : "Заметок пока нет."}</p>
      </article>

      <Link className="page-link" to="/races">
        Назад к календарю стартов
      </Link>
    </section>
  );
}
