import { Fragment, type FC, type JSX, type ReactNode, useState } from "react";
import { useTranslation } from "@/i18n/provider.js";
import type {
  IFlightLeg,
  IFlightTransitionItem,
  FlightTransitionStatus,
} from "../../types.js";
import { shouldShowTransition, shouldShowAircraft, type DetailsViewType } from "./shared.js";
import { RegistrationPanel } from "./RegistrationPanel.js";
import { BoardingPanel } from "./BoardingPanel.js";
import { DeboardingPanel } from "./DeboardingPanel.js";
import { AircraftPanel } from "./AircraftPanel.js";
import { MealPanel } from "./MealPanel.js";
import { ServicesPanel } from "./ServicesPanel.js";
import {
  formatLocalTime,
  formatDayMonthYear,
} from "@/shared/utils/datetime/index.js";
import "./FlightDetailsAccordion.scss";

export interface FlightDetailsAccordionProps {
  leg: IFlightLeg;
  viewType: DetailsViewType;
  /** Current locale (e.g. "ru-ru"). Forwarded to AircraftPanel for previous-flight link. */
  locale?: string;
  /**
   * Optional flight-level carrier+number, used only for the §4.1.15.10
   * special-meal probe. The leg payload exposes operatingBy but not the
   * top-level flight number, so the parent passes it through when
   * available. Absent → panel falls back to class-only meal icons.
   */
  flightIdentifier?: { carrier: string; flightNumber: string };
}

interface RowDef {
  id: string;
  icon: JSX.Element;
  title: string;
  /** Optional status pill (e.g. 'Закончена') shown under the title */
  statusStatus?: FlightTransitionStatus;
  /** Optional sub-label below the title (e.g. aircraft model). */
  subtitle?: ReactNode;
  /** Body content for the right-hand column. */
  body: ReactNode;
  /** Keeps legacy data-testid on an inner marker for tests. */
  legacyTestId?: string;
  /** Marks this row as a transition panel (registration/boarding/deboarding). */
  isTransition?: boolean;
}

// Registration — person with a badge/ID on the chest, mirroring Angular's
// sprite #service icon (check-in agent silhouette).
const ICON_REGISTRATION: JSX.Element = (
  <svg viewBox="0 0 24 24" width="44" height="44" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    <circle cx="12" cy="6" r="2.5" />
    <path d="M8.5 21v-6.5a3 3 0 0 1 3-3h1a3 3 0 0 1 3 3V21" />
    <rect x="10" y="12.5" width="4" height="3" rx="0.5" />
    <path d="M5 21h14" />
  </svg>
);
// Boarding — ascending escalator/stairs with a person, matching Angular's
// #board sprite (passenger stepping up onto the plane).
const ICON_BOARDING: JSX.Element = (
  <svg viewBox="0 0 24 24" width="44" height="44" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    <circle cx="16" cy="5" r="1.5" />
    <path d="M13.5 11 16 8.5l3 2.5v3" />
    <path d="M3 20l3-3h3l3-3h3l3-3h3" />
    <path d="M3 20h18" />
  </svg>
);
// Deboarding — descending escalator/stairs with a person, mirror of #deboard.
const ICON_DEBOARDING: JSX.Element = (
  <svg viewBox="0 0 24 24" width="44" height="44" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    <circle cx="8" cy="5" r="1.5" />
    <path d="M10.5 11 8 8.5 5 11v3" />
    <path d="M21 20l-3-3h-3l-3-3h-3L9 11H6" />
    <path d="M3 20h18" />
  </svg>
);
const ICON_AIRCRAFT: JSX.Element = (
  <svg viewBox="0 0 24 24" width="44" height="44" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    <path d="M21 16v-2l-8-5V3.5a1.5 1.5 0 1 0-3 0V9l-8 5v2l8-2.5V19l-2 1.5V22l3.5-1 3.5 1v-1.5L13 19v-5.5L21 16z" />
  </svg>
);
const ICON_MEAL: JSX.Element = (
  <svg viewBox="0 0 24 24" width="44" height="44" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    <path d="M4 11c0-2 2-4 4-4s4 2 4 4" />
    <path d="M14 7c2-2 5-1 5 2v8" />
    <path d="M4 11v8" />
    <path d="M4 19h20" />
  </svg>
);
const ICON_SERVICES: JSX.Element = (
  <svg viewBox="0 0 24 24" width="44" height="44" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    <rect x="3" y="6" width="18" height="12" rx="2" />
    <path d="M7 10v4M12 10v4M17 10v4" />
  </svg>
);

function TransitionTimes({
  item,
  testId,
}: {
  item: IFlightTransitionItem;
  testId: string;
}): JSX.Element {
  const { t } = useTranslation();
  const start = item.start;
  const end = item.end;
  const startDayChange = start?.dayChange?.value ?? 0;
  const endDayChange = end?.dayChange?.value ?? 0;
  return (
    <div className="details-row__times" data-testid={testId}>
      {start?.local && (
        <div className="details-row__time-col">
          <div className="details-row__time-label">{t("SHARED.TIME-START")}</div>
          <div className="details-row__time-value">
            {formatLocalTime(start.local)}
            {startDayChange !== 0 && (
              <span className="details-row__day-change">
                {startDayChange > 0 ? `+${startDayChange}` : startDayChange}
              </span>
            )}
          </div>
          <div className="details-row__time-date">{formatDayMonthYear(start.local)}</div>
        </div>
      )}
      {end?.local && (
        <div className="details-row__time-col">
          <div className="details-row__time-label">{t("SHARED.TIME-END")}</div>
          <div className="details-row__time-value">
            {formatLocalTime(end.local)}
            {endDayChange !== 0 && (
              <span className="details-row__day-change">
                {endDayChange > 0 ? `+${endDayChange}` : endDayChange}
              </span>
            )}
          </div>
          <div className="details-row__time-date">{formatDayMonthYear(end.local)}</div>
        </div>
      )}
    </div>
  );
}

export const FlightDetailsAccordion: FC<FlightDetailsAccordionProps> = ({ leg, viewType, locale, flightIdentifier }) => {
  const { t } = useTranslation();
  const [collapsed, setCollapsed] = useState(false);

  const rows: RowDef[] = [];

  const registration = leg.transition?.registration;
  if (registration && shouldShowTransition(registration, leg.status, viewType)) {
    rows.push({
      id: "registration",
      icon: ICON_REGISTRATION,
      title: t("DETAILS.REGISTRATION"),
      statusStatus: registration.status,
      body: <TransitionTimes item={registration} testId="registration-times" />,
      legacyTestId: "registration-panel",
      isTransition: true,
    });
  }
  const boarding = leg.transition?.boarding;
  if (boarding && shouldShowTransition(boarding, leg.status, viewType)) {
    rows.push({
      id: "boarding",
      icon: ICON_BOARDING,
      title: t("DETAILS.BOARDING"),
      statusStatus: boarding.status,
      body: (
        <>
          <TransitionTimes item={boarding} testId="boarding-times" />
          {/* §4.1.15.4: dispatch type (Bus / Bridge) and departure gate.
              Angular parity: flight-details-boarding.component.html lines 17–24 */}
          {leg.departure.dispatch && (
            <div className="details-panel__row" data-testid="boarding-dispatch">
              <span className="details-panel__label">{t("SHARED.LANDING-TRANSFER")}</span>
              <span className="details-panel__value">{t(`DISPATCH.${leg.departure.dispatch}`)}</span>
            </div>
          )}
          {leg.departure.gate && (
            <div className="details-panel__row" data-testid="boarding-gate">
              <span className="details-panel__label">{t("SHARED.NUMBER-EXIT")}</span>
              <span className="details-panel__value">{leg.departure.gate}</span>
            </div>
          )}
        </>
      ),
      legacyTestId: "boarding-panel",
      isTransition: true,
    });
  }
  const deboarding = leg.transition?.deboarding;
  if (deboarding && shouldShowTransition(deboarding, leg.status, viewType)) {
    rows.push({
      id: "deboarding",
      icon: ICON_DEBOARDING,
      title: t("DETAILS.DEBOARDING"),
      statusStatus: deboarding.status,
      body: <TransitionTimes item={deboarding} testId="deboarding-times" />,
      legacyTestId: "deboarding-panel",
      isTransition: true,
    });
  }
  if (shouldShowAircraft(leg.equipment)) {
    const aircraftInfo = leg.equipment.aircraft;
    const title = aircraftInfo?.actual?.title ?? aircraftInfo?.scheduled?.title ?? null;
    rows.push({
      id: "aircraft",
      icon: ICON_AIRCRAFT,
      title: t("SHARED.PLANE"),
      subtitle: title,
      body: (
        <AircraftPanel
          equipment={leg.equipment}
          {...(locale !== undefined ? { locale } : {})}
          departureDateLocal={leg.departure.times.scheduledDeparture.local}
        />
      ),
    });
  }
  const meals = leg.equipment.meal;
  if (meals && meals.length > 0) {
    rows.push({
      id: "meal",
      icon: ICON_MEAL,
      title: t("SHARED.FOOD"),
      body: (
        <MealPanel
          meals={meals}
          specialMealContext={{
            origin: leg.departure.scheduled.airportCode,
            destination: leg.arrival.scheduled.airportCode,
            ...(flightIdentifier?.carrier ? { airline: flightIdentifier.carrier } : {}),
            ...(flightIdentifier?.flightNumber ? { number: flightIdentifier.flightNumber } : {}),
            scheduledDepartureUtc: leg.departure.times.scheduledDeparture.utc,
          }}
        />
      ),
    });
  }
  const onBoardServices = leg.equipment.aircraft?.actual?.onBoardServices;
  if (onBoardServices && onBoardServices.length > 0) {
    rows.push({
      id: "services",
      icon: ICON_SERVICES,
      title: t("DETAILS.ON_BOARD_SERVICES"),
      body: <ServicesPanel services={onBoardServices} />,
    });
  }

  // Preserve legacy-shape panel elements in the DOM (hidden) so tests and
  // screen-reader logic that query `registration-panel` / `boarding-panel` /
  // `deboarding-panel` testids still pass.
  const legacyPanels: JSX.Element[] = [];
  for (const row of rows) {
    if (row.id === "registration" && leg.transition?.registration) {
      legacyPanels.push(
        <div key="legacy-registration" className="visually-hidden">
          <RegistrationPanel item={leg.transition.registration} />
        </div>,
      );
    }
    if (row.id === "boarding" && leg.transition?.boarding) {
      legacyPanels.push(
        <div key="legacy-boarding" className="visually-hidden">
          {/* departure prop intentionally omitted — dispatch/gate already
              rendered in the visible accordion row body above to avoid
              duplicate data-testid="boarding-gate/dispatch" in the DOM. */}
          <BoardingPanel item={leg.transition.boarding} />
        </div>,
      );
    }
    if (row.id === "deboarding" && leg.transition?.deboarding) {
      legacyPanels.push(
        <div key="legacy-deboarding" className="visually-hidden">
          <DeboardingPanel item={leg.transition.deboarding} arrival={leg.arrival} />
        </div>,
      );
    }
  }

  if (rows.length === 0) return null;

  // Angular shows the '* Время в системе - МЕСТНОЕ.' note under the LAST
  // transition row (registration/boarding/deboarding), not under the
  // aircraft/meal/services rows that follow. Find that index so we can
  // render the note inline after it.
  const lastTransitionIndex = (() => {
    let last = -1;
    rows.forEach((r, i) => {
      if (r.isTransition) last = i;
    });
    return last;
  })();

  return (
    <div className="flight-details-accordion p-accordion" data-testid="flight-details-accordion">
      <div className={`p-accordion-tab${collapsed ? "" : " p-accordion-tab--active"}`}>
        <div
          className={`p-accordion-header${collapsed ? "" : " p-highlight"}`}
          role="button"
          tabIndex={0}
          aria-expanded={!collapsed}
          onClick={() => setCollapsed((v) => !v)}
          onKeyDown={(e) => {
            if (e.key === "Enter" || e.key === " ") {
              e.preventDefault();
              setCollapsed((v) => !v);
            }
          }}
        >
          <span>{t("SHARED.DETAILS-FLIGHT")}</span>
          <span aria-hidden="true">{collapsed ? "\u25BC" : "\u25B2"}</span>
        </div>
        {!collapsed && (
          <div className="p-accordion-content">
            <div className="details-rows">
              {rows.map((row, i) => (
                <Fragment key={row.id}>
                  <div
                    className="details-row"
                    data-testid={`details-row-${row.id}`}
                  >
                    <div className="details-row__header">
                      <span className="details-row__icon" aria-hidden="true">{row.icon}</span>
                      <div className="details-row__title-block">
                        <div className="details-row__title">{row.title}</div>
                        {row.statusStatus && (
                          <div className={`details-row__status details-row__status--${row.statusStatus.toLowerCase()}`}>
                            {t(`BOARDING-STATUSES.${row.statusStatus}`)}
                          </div>
                        )}
                        {row.subtitle && (
                          <div className="details-row__subtitle">{row.subtitle}</div>
                        )}
                      </div>
                    </div>
                    <div className="details-row__body">{row.body}</div>
                  </div>
                  {i === lastTransitionIndex && (
                    <div
                      className="details-rows__time-note"
                      data-testid="details-time-note"
                    >
                      * {t("BOARD.LOCAL-TIME-NOTE")}
                    </div>
                  )}
                </Fragment>
              ))}
            </div>
            {legacyPanels}
          </div>
        )}
      </div>
    </div>
  );
};
