import { type FC, type ReactNode, useEffect, useRef } from "react";
import { useTranslation } from "@/i18n/provider.js";
import type { ISimpleFlight } from "@/features/online-board/types.js";
import { FlightCard } from "./FlightCard.js";
import { FlightListSkeleton } from "./FlightListSkeleton.js";
import "./FlightList.scss";

export interface FlightListProps {
  /** Array of flights to display */
  flights: ISimpleFlight[];
  /** Whether the list is in a loading state */
  loading?: boolean;
  /** Number of skeleton rows when loading (default: 5) */
  skeletonCount?: number;
  /** Click handler — makes each card act as a link to the details page */
  onFlightClick?: (flight: ISimpleFlight) => void;
  /**
   * Id of a flight to auto-expand and scroll into view on mount / list
   * change. Matches Angular's 'closest flight' behavior (today → closest
   * to now; other days → first/last).
   */
  initialCurrentFlightId?: string | null;
  /**
   * Search direction. Drives which transition (boarding vs deboarding)
   * surfaces in the expanded card and what its row title reads. Matches
   * Angular's `Посадка` / `Высадка` switch on departure vs arrival pages.
   */
  direction?: "departure" | "arrival" | "route" | "flight" | "schedule";
  /**
   * Optional override for the expanded body — receives the flight and
   * returns the React node to render inside the expanded panel. Used by
   * schedule pages to render the per-leg route diagram instead of the
   * default time/transition rows.
   */
  renderExpandedBody?: (flight: ISimpleFlight) => ReactNode;
  /**
   * Extra action buttons rendered in the default expanded-body actions
   * row, right before the share/details buttons. Threads down to each
   * FlightCard for the online-board search page where Angular shows
   * Купить / Онлайн регистрация alongside Детали рейса.
   */
  renderActions?: (flight: ISimpleFlight) => ReactNode;
  /**
   * Aeroflot booking URL per flight for the hover-reveal inline
   * "Купить билет" link (TIRREDESIGN-6). Return null to hide.
   */
  buyUrlFor?: (flight: ISimpleFlight) => string | null;
}

/**
 * List of FlightCards with loading skeleton support.
 *
 * Shows FlightListSkeleton when loading, the flight list otherwise.
 * Displays an empty-state message when flights array is empty and not loading.
 */
export const FlightList: FC<FlightListProps> = ({
  flights,
  loading = false,
  skeletonCount = 5,
  onFlightClick,
  initialCurrentFlightId,
  direction = "route",
  renderExpandedBody,
  renderActions,
  buyUrlFor,
}) => {
  const { t } = useTranslation();
  const cardRefs = useRef<Map<string, HTMLDivElement>>(new Map());
  // Track which flight ID has already been scrolled to — prevents re-scrolling
  // on every live SignalR update while preserving the first-load behavior
  // per TZ §4.1.13 ¶1.
  const scrolledToIdRef = useRef<string | null>(null);

  useEffect(() => {
    if (!initialCurrentFlightId) return;
    // Only scroll once per unique initialCurrentFlightId (i.e. per search /
    // day change). Subsequent live-update re-renders leave the viewport alone
    // so the user isn't yanked back after manually scrolling elsewhere.
    if (scrolledToIdRef.current === initialCurrentFlightId) return;
    const el = cardRefs.current.get(initialCurrentFlightId);
    // jsdom doesn't implement scrollIntoView, so guard the call.
    if (el && typeof el.scrollIntoView === "function") {
      el.scrollIntoView({ block: "center", behavior: "smooth" });
      scrolledToIdRef.current = initialCurrentFlightId;
    }
  }, [initialCurrentFlightId, flights]);

  if (loading) {
    return <FlightListSkeleton count={skeletonCount} />;
  }

  if (flights.length === 0) {
    // Mirrors Angular `page-empty-list`: icon (left / top on mobile) +
    // title + body copy. Matches the same translation keys.
    return (
      <section className="page-empty" data-testid="page-empty" role="status">
        <div className="page-empty__title">{t("SHARED.FLIGHTS-NOT-FOUND")}</div>
        <div className="page-empty__text">{t("SHARED.FLIGHTS-NOT-FOUND-TEXT")}</div>
      </section>
    );
  }

  return (
    <div className="flight-list">
      {flights.map((flight) => (
        <div
          key={flight.id}
          ref={(el) => {
            if (el) {
              cardRefs.current.set(flight.id, el);
            } else {
              cardRefs.current.delete(flight.id);
            }
          }}
        >
          <FlightCard
            flight={flight}
            direction={direction}
            // Both Board and Schedule rows expand inline on click, matching
            // Angular's `list-scheduled-flight` / `list-flight` (verified
            // 2026-04-23 against the live test site — the spec's "no
            // expanded view" change in TIRREDESIGN-4 is forward-looking
            // and Angular hasn't migrated yet, so React must not lead).
            // Schedule's expanded body is supplied by `renderExpandedBody`
            // from DayGroupedFlightList (ScheduleFlightBody — timeline,
            // leg rows, transfer pills, action buttons). Navigation to
            // the details page is triggered by `Детали рейса` inside it.
            expandable={Boolean(onFlightClick) || Boolean(renderExpandedBody)}
            initialExpanded={flight.id === initialCurrentFlightId}
            {...(onFlightClick
              ? { onViewDetails: () => onFlightClick(flight) }
              : {})}
            {...(renderExpandedBody ? { renderExpandedBody } : {})}
            {...(renderActions ? { renderActions } : {})}
            {...(() => {
              const url = buyUrlFor?.(flight);
              return url ? { inlineBuyUrl: url } : {};
            })()}
          />
        </div>
      ))}
    </div>
  );
};
