/**
 * Flights Map filter panel.
 *
 * Provides departure/arrival inputs, connections toggle, domestic/international
 * filter toggles, and date picker. Calls back to the parent via onChange.
 *
 * @module
 */

import { type FC, useCallback, useEffect, useMemo, type FormEvent } from "react";
import { Calendar } from "primereact/calendar";
import { useParams } from "@modern-js/runtime/router";
import { useTranslation } from "@/i18n/provider.js";
import { CityAutocomplete } from "@/ui/city-autocomplete/index.js";
import { useDictionaries, findCityByCoord } from "@/shared/dictionaries/index.js";
import {
  getMinDate,
  getMaxDate,
  buildDisabledDates,
  findNextEnabledDate,
} from "../calendarRange.js";
import type { IFlightsMapFilterState } from "../types.js";

export interface FlightsMapFilterProps {
  value: IFlightsMapFilterState;
  availableDays?: string[];
  onChange: (state: IFlightsMapFilterState) => void;
}

function yyyymmddToDate(value: string): Date | null {
  if (value.length !== 8) return null;
  const y = Number(value.slice(0, 4));
  const m = Number(value.slice(4, 6)) - 1;
  const d = Number(value.slice(6, 8));
  return new Date(y, m, d);
}

function dateToYyyymmdd(value: Date): string {
  const y = value.getFullYear().toString();
  const m = (value.getMonth() + 1).toString().padStart(2, "0");
  const d = value.getDate().toString().padStart(2, "0");
  return `${y}${m}${d}`;
}

/**
 * Filter component for the flights map. Controls departure, arrival,
 * connections, domestic/international toggles, and date selection.
 */
export const FlightsMapFilter: FC<FlightsMapFilterProps> = ({
  value,
  availableDays,
  onChange,
}) => {
  const { t } = useTranslation();
  const { lang } = useParams<{ lang: string }>();
  const { dictionaries } = useDictionaries(lang ?? "ru");

  const handleLocate = useCallback(async () => {
    if (!dictionaries || typeof navigator === "undefined" || !navigator.geolocation) return;
    navigator.geolocation.getCurrentPosition(
      (pos) => {
        const city = findCityByCoord(
          dictionaries,
          pos.coords.latitude,
          pos.coords.longitude,
        );
        if (city) {
          onChange({ ...value, departure: city.code });
        }
      },
      () => {
        // silent
      },
      { enableHighAccuracy: false, timeout: 5000 },
    );
  }, [dictionaries, onChange, value]);

  const minDate = useMemo(() => getMinDate(), []);
  const maxDate = useMemo(() => getMaxDate(), []);

  const disabledDates = useMemo(
    () => buildDisabledDates(minDate, maxDate, availableDays ?? []),
    [minDate, maxDate, availableDays],
  );

  useEffect(() => {
    if (!value.date) return;
    const current = yyyymmddToDate(value.date);
    if (!current) return;

    const snapped = findNextEnabledDate(current, disabledDates, minDate, maxDate);
    const snappedYyyymmdd = snapped ? dateToYyyymmdd(snapped) : undefined;

    if (snappedYyyymmdd !== value.date) {
      onChange({ ...value, date: snappedYyyymmdd });
    }
  }, [disabledDates, minDate, maxDate, value, onChange]);

  const handleExchange = useCallback(() => {
    const newDep = value.arrival ?? "";
    const newArr = value.departure ?? "";
    onChange({
      ...value,
      departure: newDep || undefined,
      arrival: newArr || undefined,
    });
  }, [value, onChange]);

  const handleConnectionsChange = useCallback(
    (e: FormEvent<HTMLInputElement>) => {
      onChange({ ...value, connections: (e.target as HTMLInputElement).checked });
    },
    [value, onChange],
  );

  const handleDomesticChange = useCallback(
    (e: FormEvent<HTMLInputElement>) => {
      const checked = (e.target as HTMLInputElement).checked;
      onChange({
        ...value,
        domestic: checked,
        international: checked ? false : value.international,
      });
    },
    [value, onChange],
  );

  const handleInternationalChange = useCallback(
    (e: FormEvent<HTMLInputElement>) => {
      const checked = (e.target as HTMLInputElement).checked;
      onChange({
        ...value,
        international: checked,
        domestic: checked ? false : value.domestic,
      });
    },
    [value, onChange],
  );

  const handleDateChange = useCallback(
    (newDate: Date | null) => {
      onChange({ ...value, date: newDate ? dateToYyyymmdd(newDate) : undefined });
    },
    [value, onChange],
  );

  return (
    <div className="flights-map-filter" data-testid="flights-map-filter">
      <CityAutocomplete
        label={t("SHARED.DEPARTURE_CITY")}
        placeholder={t("FLIGHTS-MAP.FILTER_DEPARTURE_PLACEHOLDER")}
        value={value.departure ?? ""}
        onChange={(code) => {
          onChange({
            ...value,
            departure: code || undefined,
            arrival: undefined,
          });
        }}
        dictionaries={dictionaries}
        onLocate={handleLocate}
        testIdPrefix="fm-departure"
      />

      <button
        type="button"
        className="flights-map-filter__exchange"
        onClick={handleExchange}
        aria-label={t("SHARED.CITY_CHANGE")}
        data-testid="fm-exchange-btn"
      >
        &#8646;
      </button>

      <CityAutocomplete
        label={t("SHARED.ARRIVAL_CITY")}
        placeholder={t("FLIGHTS-MAP.FILTER_ARRIVAL_PLACEHOLDER")}
        value={value.arrival ?? ""}
        onChange={(code) => {
          onChange({ ...value, arrival: code || undefined });
        }}
        dictionaries={dictionaries}
        testIdPrefix="fm-arrival"
      />

      <div className="flights-map-filter__field">
        <label htmlFor="fm-date">{t("SHARED.FLIGHT_DATE")}</label>
        <Calendar
          value={value.date ? yyyymmddToDate(value.date) : null}
          onChange={(e) => handleDateChange(e.value as Date | null)}
          minDate={minDate}
          maxDate={maxDate}
          disabledDates={disabledDates}
          dateFormat="dd.mm.yy"
          showIcon
          className="input--filter"
          inputId="fm-date"
          data-testid="fm-date-input"
        />
      </div>

      <div className="flights-map-filter__info">
        <p>{t("FLIGHTS-MAP.FILTER_INFO")}</p>
      </div>

      <div className="flights-map-filter__toggles">
        <label className={!value.departure ? "flights-map-filter__toggle--disabled" : ""}>
          <input
            type="checkbox"
            checked={value.domestic}
            onChange={handleDomesticChange}
            disabled={!value.departure}
            data-testid="fm-domestic-toggle"
          />
          {t("FLIGHTS-MAP.DOMESTIC_FLIGHTS")}
        </label>

        <label className={!value.departure ? "flights-map-filter__toggle--disabled" : ""}>
          <input
            type="checkbox"
            checked={value.international}
            onChange={handleInternationalChange}
            disabled={!value.departure}
            data-testid="fm-international-toggle"
          />
          {t("FLIGHTS-MAP.INTERNATIONAL_FLIGHTS")}
        </label>

        <label className={!(value.departure && value.arrival) ? "flights-map-filter__toggle--disabled" : ""}>
          <input
            type="checkbox"
            checked={value.connections}
            onChange={handleConnectionsChange}
            disabled={!(value.departure && value.arrival)}
            data-testid="fm-connections-toggle"
          />
          {t("FLIGHTS-MAP.CONNECTING_FLIGHTS")}
        </label>
      </div>
    </div>
  );
};
