import React, { useContext, useEffect, useRef } from 'react';
import Icon from '../icon';
import { useFlightSearch } from '../../../search-results/components/flight/flight-search-context';
import { useDispatch, useSelector } from 'react-redux';
import {
  resetFilters,
  setBookPackagingEntry,
  setFilters,
  setFlyInType,
  setSelectedFlight,
  setSelectedFlightDetails,
  setSelectedSearchResult,
  setSortType
} from '../../../search-results/store/search-results-slice';
import FlightsFlyIn from './flights-flyin';
import AccommodationFlyIn from './accommodation-flyin';
import { PortalQsmType } from '@qite/tide-client';
import GroupTourFlyIn from './group-tour-flyin';
import { FlyInType, SearchSeed, SortByType } from '../../../search-results/types';
import HotelAccommodationResults from '../../../search-results/components/hotel/hotel-accommodation-results';
import PackageingFlightsFlyIn from './packaging-flights-flyin';
import SearchResultsConfigurationContext from '../../../search-results/search-results-configuration-context';
import { findSortByType, getSortingName, getTranslations } from '../../utils/localization-util';
import Filters from '../../../search-results/components/filters/filters';
import { SearchResultsRootState } from '../../../search-results/store/search-results-store';
import ItemPicker from '../../../search-results/components/item-picker';
import ExcursionResults from '../../../search-results/components/excursions/excursion-results';
import ExcursionDetails from '../../../search-results/components/excursions/excursion-details';

type FlyInProps = {
  srpType: PortalQsmType;
  isOpen: boolean;
  setIsOpen: (open: boolean) => void;
  className?: string;
  onPanelRef?: (el: HTMLDivElement | null) => void;
  detailsLoading: boolean;
  handleConfirm?: () => void;
  flyInType?: FlyInType | null;
  isPackageEditFlow?: boolean;
  sortByTypes?: SortByType[];
  activeSearchSeed?: SearchSeed | null;
  toggleFilters?: () => void;
  filtersOpen: boolean;
};

const FlyIn: React.FC<FlyInProps> = ({
  srpType,
  isOpen,
  setIsOpen,
  className = '',
  onPanelRef,
  detailsLoading,
  flyInType,
  isPackageEditFlow,
  handleConfirm,
  sortByTypes,
  activeSearchSeed,
  toggleFilters,
  filtersOpen
}) => {
  const dispatch = useDispatch();
  const context = useContext(SearchResultsConfigurationContext);
  const language = context?.languageCode ?? 'en-GB';
  const translations = getTranslations(language);

  const { isLoading, initialFilters, filters, filteredPackagingAccoResults, selectedSortType } = useSelector(
    (state: SearchResultsRootState) => state.searchResults
  );

  const { onCancelSearch } = useFlightSearch();
  const panelRef = useRef<HTMLDivElement>(null);

  // expose DOM node if needed
  useEffect(() => {
    onPanelRef?.(panelRef.current);
    return () => onPanelRef?.(null);
  }, [onPanelRef]);

  useEffect(() => {
    // click outside detection
    const handleClickOutside = (event: MouseEvent) => {
      if (isOpen && panelRef.current && !panelRef.current.contains(event.target as Node)) {
        handleClose();
      }
    };

    document.addEventListener('mousedown', handleClickOutside);
    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, [isOpen, setIsOpen]);

  // body scroll lock
  useEffect(() => {
    document.body.style.overflow = isOpen ? 'hidden' : '';
    return () => {
      document.body.style.overflow = '';
    };
  }, [isOpen]);

  const handleClose = () => {
    if (isOpen && panelRef.current) {
      if (srpType === PortalQsmType.Flight) {
        dispatch(setSelectedFlight(null));
        dispatch(setSelectedFlightDetails(null));
        onCancelSearch();
      } else {
        dispatch(setSelectedSearchResult(null));
      }
      dispatch(setFlyInType('acco-details'));
      setIsOpen(false);
    }
  };

  const handleGoBack = () => {
    if (flyInType === 'acco-details') {
      dispatch(setFlyInType('acco-results'));
    } else if (flyInType === 'excursion-details') {
      dispatch(setFlyInType('excursion-results'));
    }
  };

  const handleSortChange = (newSortKey: string, direction?: string) => {
    if (sortByTypes === undefined) return;
    const newSortByType = findSortByType(sortByTypes, newSortKey, direction ?? 'asc');
    if (newSortByType) {
      dispatch(setSortType(newSortByType));
    }
  };

  const onHandleConfirm = () => {
    if (context?.packagingEntry || srpType === PortalQsmType.AccommodationAndFlight) {
      handleConfirm?.();
    } else {
      dispatch(setBookPackagingEntry(true));
    }
  };

  return (
    <div
      className={`flyin ${isOpen ? 'flyin--active' : ''} ${className} ${isPackageEditFlow || flyInType === 'acco-results' ? 'flyin--large' : ''} ${
        flyInType === 'excursion-results' || flyInType === 'excursion-details' ? 'flyin--medium' : ''
      }
      ${flyInType === 'flight-outward-results' || flyInType === 'flight-return-results' ? 'flyin--flight' : ''}`}>
      <div className={`flyin__panel ${isOpen ? 'flyin__panel--active' : ''}`} ref={panelRef}>
        <div className="flyin__content">
          <div className="flyin__content-title-row">
            <h3 className="flyin__content-title">
              {srpType === PortalQsmType.Flight && 'Select your fare'}
              {srpType === PortalQsmType.Accommodation ||
                (srpType === PortalQsmType.AccommodationAndFlight &&
                  (flyInType === 'acco-results' || flyInType === 'acco-details') &&
                  `${translations.SRP.SELECT} ${translations.SRP.ACCOMMODATION}`)}
              {srpType === PortalQsmType.AccommodationAndFlight &&
                flyInType === 'flight-outward-results' &&
                `${translations.SRP.SELECT} ${translations.FLIGHTS_FORM.OUTWARD_FLIGHT}`}
              {srpType === PortalQsmType.AccommodationAndFlight &&
                flyInType === 'flight-return-results' &&
                `${translations.SRP.SELECT} ${translations.FLIGHTS_FORM.RETURN_FLIGHT}`}
              {srpType === PortalQsmType.AccommodationAndFlight && flyInType === 'flight-details' && 'Select your fare'}
              {flyInType === 'excursion-results' || (flyInType === 'excursion-details' && 'Select excursion')}
            </h3>
            <span className="flyin__close" onClick={() => handleClose()}>
              <Icon name="ui-close" width={30} height={30} aria-hidden="true" />
            </span>
          </div>
          {((isPackageEditFlow && flyInType === 'acco-details') || flyInType === 'excursion-details') && (
            <div className="flyin__content-title-row">
              <div onClick={handleGoBack} className="flyin__content-title__back">
                <Icon name="ui-chevron" width={14} height={14} aria-hidden="true" />
                Go Back
              </div>
            </div>
          )}
        </div>
        {srpType === PortalQsmType.Flight && <FlightsFlyIn isOpen={isOpen} setIsOpen={setIsOpen} />}

        {(srpType === PortalQsmType.Accommodation || srpType === PortalQsmType.AccommodationAndFlight) && flyInType === 'acco-results' && (
          <div className="flyin__content flyin__content--columns">
            <Filters
              initialFilters={initialFilters}
              filters={filters}
              isOpen={filtersOpen}
              handleSetIsOpen={() => toggleFilters && toggleFilters()}
              // handleApplyFilters={() => setSearchTrigger((prev) => prev + 1)}
              isLoading={isLoading}
              setFilters={(filters) => dispatch(setFilters(filters))}
              resetFilters={(filters) => dispatch(resetFilters(filters))}
            />
            <div className="search__results__wrapper">
              <div className="search__result-row">
                <div className="cta cta--filter" onClick={() => toggleFilters && toggleFilters()}>
                  <Icon name="ui-filter" className="mobile-filters-button__icon" height={16} />
                  {translations.SRP.FILTERS}
                </div>
                <span className="search__result-row-text">
                  {!isLoading && (
                    <>
                      {filteredPackagingAccoResults?.length && filteredPackagingAccoResults.length}
                      &nbsp;{translations.SRP.TOTAL_RESULTS_LABEL}
                    </>
                  )}
                </span>
                {sortByTypes && sortByTypes.length > 0 && (
                  <div className="search__result-row-filter">
                    <ItemPicker
                      items={sortByTypes}
                      selection={selectedSortType?.label || undefined}
                      selectedSortByType={selectedSortType}
                      label={translations.SRP.SORTBY}
                      placeholder={translations.SRP.SORTBY}
                      classModifier="travel-class-picker__items"
                      valueFormatter={(value, direction) => getSortingName(translations, findSortByType(sortByTypes, value, direction ?? 'asc'))}
                      onPick={(newSortKey, direction) => handleSortChange(newSortKey, direction)}
                    />
                  </div>
                )}
              </div>
              <HotelAccommodationResults isLoading={detailsLoading} isFlyIn={true} />
            </div>
          </div>
        )}

        {(srpType === PortalQsmType.Accommodation || srpType === PortalQsmType.AccommodationAndFlight) && flyInType === 'acco-details' && (
          <AccommodationFlyIn isLoading={detailsLoading} handleConfirm={onHandleConfirm} />
        )}

        {srpType === PortalQsmType.AccommodationAndFlight && (flyInType === 'flight-outward-results' || flyInType === 'flight-return-results') && (
          <PackageingFlightsFlyIn isOpen={isOpen} setIsOpen={setIsOpen} toggleFilters={toggleFilters} filtersOpen={filtersOpen} />
        )}

        {srpType === PortalQsmType.AccommodationAndFlight && flyInType === 'excursion-results' && (
          <ExcursionResults isFlyIn={true} activeSearchSeed={activeSearchSeed} />
        )}
        {srpType === PortalQsmType.AccommodationAndFlight && flyInType === 'excursion-details' && <ExcursionDetails />}

        {srpType === PortalQsmType.GroupTour && <GroupTourFlyIn isLoading={detailsLoading} isOpen={isOpen} setIsOpen={setIsOpen} />}
      </div>
    </div>
  );
};

export default FlyIn;
