/**
 * SEO builder functions for Online Board route pages.
 *
 * Each function is PURE — all data arrives via parameters, no hooks or
 * side effects. Returns a SeoHeadProps object ready for <SeoHead>.
 *
 * Translation keys follow the Angular pattern from meta-tags.service.ts:
 * SEO.BOARD.{MAIN,FLIGHT-SEARCH,DEPARTURE-SEARCH,ARRIVAL-SEARCH,ROUTE-SEARCH,FLIGHT-DETAILS}.{TITLE,DESCRIPTION}
 *
 * @module
 */

import type { SeoHeadProps } from "@/ui/seo/SeoHead.js";
import { buildHreflangSet } from "@/shared/seo/hreflang.js";
import { buildWebsiteJsonLd } from "@/shared/seo/jsonLdBuilders.js";
import { buildOnlineBoardUrl } from "./url.js";
import type { OnlineBoardParams } from "./url.js";
import type { ISimpleFlight } from "./types.js";

// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------

/**
 * Translation function signature — intentionally loose to accept
 * both i18next's TFunction and simple test stubs.
 */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type TFunction = (key: string, opts?: any) => string;

/** Optional city names for station/route searches */
export interface CityNames {
  departure?: string;
  arrival?: string;
}

// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------

const OG_IMAGE = "https://www.aeroflot.ru/static/images/aeroflot-og-default.png";
const SITE_NAME = "Aeroflot";

// ---------------------------------------------------------------------------
// Internal helpers
// ---------------------------------------------------------------------------

/**
 * Format a date string to dd.MM.yyyy for display in SEO strings.
 * Accepts both 'yyyyMMdd' (URL param shape) and 'yyyy-MM-dd' (API response).
 * Used for descriptions only — titles use formatDateForTitle.
 */
function formatDateForSeo(input: string): string {
  const digits = input.replace(/-/g, "");
  if (digits.length !== 8) return input;
  const day = digits.slice(6, 8);
  const month = digits.slice(4, 6);
  const year = digits.slice(0, 4);
  return `${day}.${month}.${year}`;
}

/**
 * Format a date for title display per TZ §4.1.3 Table 6:
 * - t("SHARED.TODAY") if date is today (local)
 * - t("SHARED.TOMORROW") if date is today + 1 day (local)
 * - "dd.MM.yyyy" otherwise
 *
 * Input: "yyyyMMdd" (URL shape) or "yyyy-MM-dd" (API shape).
 */
function formatDateForTitle(input: string, t: TFunction): string {
  const digits = input.replace(/-/g, "");
  if (digits.length !== 8) return input;

  const y = Number(digits.slice(0, 4));
  const m = Number(digits.slice(4, 6)) - 1;
  const d = Number(digits.slice(6, 8));
  const inputDate = new Date(y, m, d);
  inputDate.setHours(0, 0, 0, 0);

  const today = new Date();
  today.setHours(0, 0, 0, 0);

  const deltaDays = Math.round((inputDate.getTime() - today.getTime()) / 86_400_000);
  if (deltaDays === 0) return t("SHARED.TODAY");
  if (deltaDays === 1) return t("SHARED.TOMORROW");
  return `${digits.slice(6, 8)}.${digits.slice(4, 6)}.${digits.slice(0, 4)}`;
}

/**
 * Build the canonical URL for a given set of params + locale.
 */
function buildCanonical(
  canonicalOrigin: string,
  locale: string,
  params: OnlineBoardParams,
): string {
  const path = buildOnlineBoardUrl(params);
  return `${canonicalOrigin}/${locale}/${path}`;
}

/**
 * Build the path without locale prefix for hreflang generation.
 */
function buildPathWithoutLocale(params: OnlineBoardParams): string {
  const path = buildOnlineBoardUrl(params);
  return `/${path}`;
}

/**
 * Assemble the common OG + Twitter fields from title, description, canonical, locale.
 */
function buildCommonSeoProps(args: {
  title: string;
  description: string;
  canonical: string;
  hreflangPath: string;
  canonicalOrigin: string;
  locale: string;
  ogType: "website" | "article";
}): Pick<SeoHeadProps, "og" | "twitter" | "hreflang"> {
  return {
    hreflang: buildHreflangSet({
      canonicalOrigin: args.canonicalOrigin,
      pathWithoutLocale: args.hreflangPath,
    }),
    og: {
      title: args.title,
      description: args.description,
      url: args.canonical,
      image: OG_IMAGE,
      type: args.ogType,
      locale: args.locale,
      siteName: SITE_NAME,
    },
    twitter: {
      card: "summary",
    },
  };
}

// ---------------------------------------------------------------------------
// Public SEO builder functions
// ---------------------------------------------------------------------------

/**
 * SEO props for the Online Board start page.
 */
export function buildOnlineBoardStartSeo(
  t: TFunction,
  locale: string,
  canonicalOrigin: string,
): SeoHeadProps {
  const params: OnlineBoardParams = { type: "start" };
  const title = t("SEO.BOARD.MAIN.TITLE");
  const description = t("SEO.BOARD.MAIN.DESCRIPTION");
  const canonical = buildCanonical(canonicalOrigin, locale, params);
  const hreflangPath = buildPathWithoutLocale(params);

  return {
    title,
    description,
    canonical,
    jsonLd: buildWebsiteJsonLd({
      name: SITE_NAME,
      url: canonical,
      description,
    }),
    ...buildCommonSeoProps({
      title,
      description,
      canonical,
      hreflangPath,
      canonicalOrigin,
      locale,
      ogType: "website",
    }),
  };
}

/**
 * SEO props for flight number search results page.
 */
export function buildFlightSearchSeo(
  t: TFunction,
  params: { type: "flight"; carrier: string; flightNumber: string; suffix?: string; date: string },
  locale: string,
  canonicalOrigin: string,
): SeoHeadProps {
  const flightDisplay = `${params.carrier} ${params.flightNumber}${params.suffix ?? ""}`;
  const dateForTitle = formatDateForTitle(params.date, t);
  const dateForDesc = formatDateForSeo(params.date);

  const title = t("SEO.BOARD.FLIGHT-SEARCH.TITLE", {
    flightNumber: flightDisplay,
    date: dateForTitle,
  });
  const description = t("SEO.BOARD.FLIGHT-SEARCH.DESCRIPTION", {
    flightNumber: flightDisplay,
    date: dateForDesc,
  });
  const canonical = buildCanonical(canonicalOrigin, locale, params);
  const hreflangPath = buildPathWithoutLocale(params);

  return {
    title,
    description,
    canonical,
    ...buildCommonSeoProps({
      title,
      description,
      canonical,
      hreflangPath,
      canonicalOrigin,
      locale,
      ogType: "website",
    }),
  };
}

/**
 * SEO props for departure search results page.
 */
export function buildDepartureSearchSeo(
  t: TFunction,
  params: { type: "departure"; station: string; date: string; timeFrom?: string; timeTo?: string },
  locale: string,
  canonicalOrigin: string,
  cityNames?: CityNames,
): SeoHeadProps {
  const departureCity = cityNames?.departure ?? params.station;
  const dateForTitle = formatDateForTitle(params.date, t);
  const dateForDesc = formatDateForSeo(params.date);

  const title = t("SEO.BOARD.DEPARTURE-SEARCH.TITLE", {
    departureCity,
    date: dateForTitle,
  });
  const description = t("SEO.BOARD.DEPARTURE-SEARCH.DESCRIPTION", {
    departureCity,
    date: dateForDesc,
  });
  const canonical = buildCanonical(canonicalOrigin, locale, params);
  const hreflangPath = buildPathWithoutLocale(params);

  return {
    title,
    description,
    canonical,
    ...buildCommonSeoProps({
      title,
      description,
      canonical,
      hreflangPath,
      canonicalOrigin,
      locale,
      ogType: "website",
    }),
  };
}

/**
 * SEO props for arrival search results page.
 */
export function buildArrivalSearchSeo(
  t: TFunction,
  params: { type: "arrival"; station: string; date: string; timeFrom?: string; timeTo?: string },
  locale: string,
  canonicalOrigin: string,
  cityNames?: CityNames,
): SeoHeadProps {
  const arrivalCity = cityNames?.arrival ?? params.station;
  const dateForTitle = formatDateForTitle(params.date, t);
  const dateForDesc = formatDateForSeo(params.date);

  const title = t("SEO.BOARD.ARRIVAL-SEARCH.TITLE", {
    arrivalCity,
    date: dateForTitle,
  });
  const description = t("SEO.BOARD.ARRIVAL-SEARCH.DESCRIPTION", {
    arrivalCity,
    date: dateForDesc,
  });
  const canonical = buildCanonical(canonicalOrigin, locale, params);
  const hreflangPath = buildPathWithoutLocale(params);

  return {
    title,
    description,
    canonical,
    ...buildCommonSeoProps({
      title,
      description,
      canonical,
      hreflangPath,
      canonicalOrigin,
      locale,
      ogType: "website",
    }),
  };
}

/**
 * SEO props for route search results page.
 */
export function buildRouteSearchSeo(
  t: TFunction,
  params: { type: "route"; departure: string; arrival: string; date: string; timeFrom?: string; timeTo?: string },
  locale: string,
  canonicalOrigin: string,
  cityNames?: CityNames,
): SeoHeadProps {
  const departureCity = cityNames?.departure ?? params.departure;
  const arrivalCity = cityNames?.arrival ?? params.arrival;
  const dateForTitle = formatDateForTitle(params.date, t);
  const dateForDesc = formatDateForSeo(params.date);

  const title = t("SEO.BOARD.ROUTE-SEARCH.TITLE", {
    departureCity,
    arrivalCity,
    date: dateForTitle,
  });
  const description = t("SEO.BOARD.ROUTE-SEARCH.DESCRIPTION", {
    departureCity,
    arrivalCity,
    date: dateForDesc,
  });
  const canonical = buildCanonical(canonicalOrigin, locale, params);
  const hreflangPath = buildPathWithoutLocale(params);

  return {
    title,
    description,
    canonical,
    ...buildCommonSeoProps({
      title,
      description,
      canonical,
      hreflangPath,
      canonicalOrigin,
      locale,
      ogType: "website",
    }),
  };
}

/**
 * SEO props for flight details page from already-parsed flight id.
 * Accepts a plain object so the route page can render SeoHead
 * synchronously without waiting for the flight data to load — SSR
 * needs the title + meta in the <head> of the first response.
 *
 * @param cityNames - Optional departure/arrival city names. When available
 *   (e.g. after flight data has loaded client-side), supply these so the
 *   title includes the route cities per TZ Table 6 rows 6-8. When not
 *   available at SSR time the title will omit the route segment.
 */
export function buildFlightDetailsSeoFromId(
  t: TFunction,
  flightId: { carrier: string; flightNumber: string; suffix?: string; date: string },
  locale: string,
  canonicalOrigin: string,
  cityNames?: CityNames,
): SeoHeadProps {
  const flight: ISimpleFlight = { flightId } as unknown as ISimpleFlight;
  return buildFlightDetailsSeo(t, flight, locale, canonicalOrigin, cityNames);
}

/**
 * SEO props for flight details page.
 * Title per TZ Table 6 rows 6-8: "Информация о рейсе: {flightNumber}, {fromCity}-{toCity}"
 * No date in the title. Description keeps the full dd.MM.yyyy date.
 */
export function buildFlightDetailsSeo(
  t: TFunction,
  flight: ISimpleFlight,
  locale: string,
  canonicalOrigin: string,
  cityNames?: CityNames,
): SeoHeadProps {
  const { carrier, flightNumber, suffix, date } = flight.flightId;
  const flightDisplay = `${carrier} ${flightNumber}${suffix ?? ""}`;
  const dateForDesc = formatDateForSeo(date);

  // Derive route cities: prefer explicit cityNames, then flight leg data.
  let departureCity = cityNames?.departure;
  let arrivalCity = cityNames?.arrival;
  if (!departureCity || !arrivalCity) {
    if (flight.routeType === "Direct") {
      departureCity ??= flight.leg.departure.scheduled.city;
      arrivalCity ??= flight.leg.arrival.scheduled.city;
    } else if (flight.routeType === "MultiLeg" && flight.legs.length > 0) {
      const firstLeg = flight.legs[0];
      const lastLeg = flight.legs[flight.legs.length - 1];
      if (firstLeg) departureCity ??= firstLeg.departure.scheduled.city;
      if (lastLeg) arrivalCity ??= lastLeg.arrival.scheduled.city;
    }
  }

  const routeCities =
    departureCity && arrivalCity ? `${departureCity}-${arrivalCity}` : undefined;

  const title = routeCities
    ? t("SEO.BOARD.FLIGHT-DETAILS.TITLE", { flightNumber: flightDisplay, routeCities })
    : t("SEO.BOARD.FLIGHT-DETAILS.TITLE-NO-ROUTE", { flightNumber: flightDisplay });

  const description = t("SEO.BOARD.FLIGHT-DETAILS.DESCRIPTION", {
    flightNumber: flightDisplay,
    date: dateForDesc,
  });

  const detailsParams: OnlineBoardParams = suffix
    ? { type: "details", carrier, flightNumber, suffix, date }
    : { type: "details", carrier, flightNumber, date };
  const canonical = buildCanonical(canonicalOrigin, locale, detailsParams);
  const hreflangPath = buildPathWithoutLocale(detailsParams);

  return {
    title,
    description,
    canonical,
    ...buildCommonSeoProps({
      title,
      description,
      canonical,
      hreflangPath,
      canonicalOrigin,
      locale,
      ogType: "article",
    }),
  };
}
