import { book, validateVoucher, EntryStatus } from '@qite/tide-client';
import { BookingPackageRequest, BookingPackageVoucherRequest, ServiceType } from '@qite/tide-client';
import { Link, useNavigate } from 'react-router-dom';
import { compact, findIndex, isEmpty, isNil, uniqBy } from 'lodash';
import React, { useContext, useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import { buildClassName } from '../../../shared/utils/class-util';
import { buildTideClientConfig } from '../../../shared/utils/tide-api-utils';
import Icon from '../../../shared/components/icon';
import SettingsContext from '../../settings-context';
import { useAppDispatch } from '../../store';
import { SummaryCheckbox } from '../../types';
import { setBookingNumber, setBookingRemarks, setCurrentStep, setIsOption, setVoucherCodes } from '../booking/booking-slice';
import { CONFIRMATION_STEP, ERROR_STEP, TRAVELERS_FORM_STEP } from '../booking/constants';
import {
  selectActiveOption,
  selectAgentAdressId,
  selectApiSettings,
  selectBookingPackageBookRequest,
  selectBookingQueryString,
  selectDepartureFlight,
  selectLanguageCode,
  selectOfficeId,
  selectPackageDetails,
  selectReturnFlight,
  selectRoomOptionDepartureFlightsMetaData,
  selectRoomOptionReturnFlightsMetaData,
  selectTranslations
} from '../booking/selectors';
import { fetchPriceDetails, selectNotifications, setNotifications } from '../price-details/price-details-slice';
import { getDateText } from '../sidebar/sidebar-util';
import { selectRooms, selectTravelersFormValues } from '../travelers-form/travelers-form-slice';
import SummaryBookingOptionPax from './summary-booking-option-pax';
import SummaryBookingOptionUnit from './summary-booking-option-unit';
import SummaryFlight from './summary-flight';
import SummaryBookingOption from './summary-per-booking-option-group';
import { selectUserValidated, setUserValidated } from './summary-slice';
import Loader from '../../../shared/components/loader';

interface VoucherProps {
  code?: string;
  isValidated?: boolean;
  isValid?: boolean;
}

interface SummaryProps {}

const Summary: React.FC<SummaryProps> = () => {
  const dispatch = useAppDispatch();

  const settings = useContext(SettingsContext);
  const navigate = settings.skipRouter ? () => {} : useNavigate();

  const [isSubmitting, setIsSubmitting] = useState(false);
  const [checkboxes, setCheckboxes] = useState<SummaryCheckbox[] | undefined | null>(settings.summary?.checkboxes);
  const [remarks, setRemarks] = useState<string>('');

  const [voucher, setVoucher] = useState<VoucherProps>({});

  const bookingQueryString = useSelector(selectBookingQueryString);
  const travelerFormValues = useSelector(selectTravelersFormValues);
  const packageDetails = useSelector(selectPackageDetails);
  const activeOption = useSelector(selectActiveOption);
  const apiSettings = useSelector(selectApiSettings);
  const languageCode = useSelector(selectLanguageCode);
  const officeId = useSelector(selectOfficeId);
  const agentId = useSelector(selectAgentAdressId);
  const departureFlight = useSelector(selectDepartureFlight);
  const departureFlightMetaData = departureFlight?.flightMetaData ?? useSelector(selectRoomOptionDepartureFlightsMetaData)?.[0];
  const returnFlight = useSelector(selectReturnFlight);
  const returnFlightMetaData = returnFlight?.flightMetaData ?? useSelector(selectRoomOptionReturnFlightsMetaData)?.[0];

  if (!travelerFormValues) {
    if (settings.skipRouter) {
      dispatch(setCurrentStep(TRAVELERS_FORM_STEP));
    } else {
      navigate(`${!settings.skipBasePathInRouting ? settings.basePath : ''}?${bookingQueryString}`);
    }
  }

  const rooms = useSelector(selectRooms);

  const userValidated = useSelector(selectUserValidated);
  const notifications = useSelector(selectNotifications);

  const bookRequest = useSelector(selectBookingPackageBookRequest);

  useEffect(() => {
    // Every checkbox should be checked, or no checkboxes
    const checkboxesValidated = !isNil(checkboxes) ? checkboxes.every((checkbox) => checkbox.isSelected) : true;

    const notificationsValidated = !isNil(notifications) ? notifications.filter((x) => x.hasToBeConfirmed).every((checkbox) => checkbox.isConfirmed) : true;

    dispatch(setUserValidated(checkboxesValidated && notificationsValidated));
  }, [checkboxes, notifications]);

  const handleSubmit: React.FormEventHandler<HTMLFormElement> = async (e) => {
    e.preventDefault();
    const submitter = (e.nativeEvent as any).submitter?.name;
    setIsSubmitting(true);

    if (typeof window !== 'undefined') {
      window.scrollTo(0, 0);
    }

    const tideClientConfig = buildTideClientConfig(apiSettings);

    if (!bookRequest || !tideClientConfig) {
      return;
    }

    if (bookRequest.payload.returnPaymentUrl) {
      if (typeof window !== 'undefined') {
        const location = window.location;
        window.scrollTo(0, 0);
        bookRequest.payload.redirectUrl = `${location.protocol}//${location.host}${settings.basePath}?${bookingQueryString}`;
      }
    }

    try {
      if (submitter === 'option') {
        bookRequest.payload.status = EntryStatus.option;
        bookRequest.payload.customStatusId = settings.customOptionStatus;

        dispatch(setIsOption(true));
      }

      const bookingResponse = await book(tideClientConfig, bookRequest, undefined, languageCode);

      // Booking successfull
      dispatch(setBookingNumber(bookingResponse.number));

      if (bookingResponse.paymentUrl) {
        window.location.href = bookingResponse.paymentUrl;
      } else {
        if (settings.skipRouter) {
          dispatch(setCurrentStep(CONFIRMATION_STEP));
        } else {
          navigate(`${!settings.skipBasePathInRouting ? settings.basePath : ''}${settings.confirmation.pathSuffix}?${bookingQueryString}`);
        }
      }
    } catch (error) {
      if (settings.skipRouter) {
        dispatch(setCurrentStep(ERROR_STEP));
      } else {
        navigate(`${!settings.skipBasePathInRouting ? settings.basePath : ''}${settings.error.pathSuffix}?${bookingQueryString}`);
      }
    } finally {
      setIsSubmitting(false);
    }
  };

  const handleNotificationChange = (id: number, checked: boolean) => {
    const updatedNotifications = notifications.map((notification) => (notification.id === id ? { ...notification, isConfirmed: checked } : notification));

    dispatch(setNotifications(updatedNotifications));
  };

  const handleCheckboxChange = (id: string, checked: boolean) => {
    if (isNil(checkboxes)) {
      return;
    }

    const newCheckboxes = [...checkboxes];

    const index = findIndex(checkboxes, (checkbox) => checkbox.id === id);
    newCheckboxes[index].isSelected = !newCheckboxes[index].isSelected;

    setCheckboxes(newCheckboxes);
  };

  const handleRemarksChange = (text: string) => {
    dispatch(setBookingRemarks(text));

    setRemarks(text);
  };

  const handleValidateVoucher = async () => {
    if (!voucher?.code) return;

    const request = {
      officeId: officeId,
      agentId: agentId,
      payload: {
        code: voucher.code,
        otherCodes: bookRequest?.payload.voucherCodes ?? []
      }
    } as BookingPackageRequest<BookingPackageVoucherRequest>;

    const tideClientConfig = buildTideClientConfig(apiSettings);
    if (!tideClientConfig) return;

    const result = await validateVoucher(tideClientConfig, request);

    if (result) {
      setVoucher({
        ...voucher,
        isValidated: true,
        isValid: result.isValid
      });
    }
  };

  const handleAddVoucher: React.MouseEventHandler<HTMLButtonElement> = (event) => {
    if (!voucher.isValid) return;

    dispatch(setVoucherCodes([...(bookRequest?.payload.voucherCodes ?? []), voucher.code ?? ''].filter((x) => x !== '')));

    dispatch(fetchPriceDetails());

    setVoucher({});
  };

  const handleRemoveVoucher = (code: string) => {
    dispatch(setVoucherCodes(bookRequest?.payload.voucherCodes?.filter((x) => x !== code) ?? []));

    dispatch(fetchPriceDetails());
  };

  const goPrevious = () => {
    dispatch(setCurrentStep(TRAVELERS_FORM_STEP));
  };

  const translations = useSelector(selectTranslations);

  return (
    <>
      {isSubmitting && (settings.loaderComponent || <Loader />)}
      {!isSubmitting && (
        <form className="form" name="booking--summary" id="booking--summary" onSubmit={handleSubmit}>
          <div className="form__booking--summary">
            <div className="form__region">
              <div className="form__row">
                <div className="form__group">
                  <div className="form__region-header">
                    <h5 className="form__region-heading">{translations.SUMMARY.PERSONAL_DETAILS}</h5>
                  </div>
                </div>
              </div>
              {rooms.map((r, rIndex) => (
                <div className="form__row" key={rIndex}>
                  <div className="form__group">
                    <div className="form__region-header">
                      <h5 className="form__region-heading">
                        {rooms.length > 1 ? `${translations.SHARED.ROOM} ${rIndex + 1}` : translations.ROOM_OPTIONS_FORM.TRAVELER_GROUP}
                      </h5>
                      <p className="form__region-label">
                        {`${r.adults.length + r.children.length} ${
                          r.adults.length + r.children.length === 1 ? translations.SUMMARY.TRAVELER : translations.SUMMARY.TRAVELERS
                        }: ${compact([
                          r.adults.length,
                          r.adults.length === 1 && ` ${translations.SUMMARY.ADULT}`,
                          r.adults.length > 1 && ` ${translations.SUMMARY.ADULTS}`,
                          r.adults && r.adults.length && r.children && r.children.length && ', ',
                          r.children.length,
                          r.children.length === 1 && ` ${translations.SUMMARY.CHILD}`,
                          r.children.length > 1 && ` ${translations.SUMMARY.CHILDREN}`
                        ]).join('')}`}
                      </p>
                    </div>
                  </div>
                  {[...r.adults, ...r.children].map((traveler) => {
                    const isMainBooker = traveler.id === travelerFormValues?.mainBookerId;
                    return (
                      <div className="form__group form__group--sm-50" key={traveler.id}>
                        <ul className="list list--plain">
                          <li className="list__item">
                            <strong>
                              {traveler.firstName} {traveler.lastName}
                            </strong>{' '}
                            {isMainBooker && <em>({translations.SUMMARY.MAIN_BOOKER})</em>}
                          </li>
                          <li className="list__item">{traveler.birthDate.split('-').reverse().join('/')}</li>
                          {isMainBooker && (
                            <>
                              {travelerFormValues?.street && (
                                <>
                                  <li className="list__item">{`${travelerFormValues?.street} ${compact([
                                    travelerFormValues?.houseNumber,
                                    travelerFormValues?.box
                                  ]).join(' ')}, ${travelerFormValues?.zipCode} ${travelerFormValues?.place}`}</li>
                                </>
                              )}
                              {travelerFormValues?.phone && <li className="list__item">{travelerFormValues?.phone}</li>}
                              {travelerFormValues?.email && <li className="list__item">{travelerFormValues?.email}</li>}
                            </>
                          )}
                        </ul>
                      </div>
                    );
                  })}
                </div>
              ))}
            </div>

            <div className="form__region">
              <div className="form__row">
                <div className="form__group">
                  <div className="form__region-header">
                    <h5 className="form__region-heading">{translations.SUMMARY.OPTIONS}</h5>
                  </div>
                </div>
              </div>
              <div className="form__row">
                <div className="form__group">
                  <ul className="list list--booking-summary">
                    {activeOption?.serviceType == ServiceType.flight ? (
                      <>
                        {departureFlightMetaData && <SummaryFlight flightMetaData={departureFlightMetaData} header={translations.SIDEBAR.DEPARTURE_FLIGHT} />}
                        {returnFlightMetaData && <SummaryFlight flightMetaData={returnFlightMetaData} header={translations.SIDEBAR.ARRIVAL_FLIGHT} />}
                      </>
                    ) : (
                      <>
                        {activeOption?.rooms
                          .flatMap((r) => r.options)
                          .filter((x) => x.isSelected)
                          .map((roomOption, roomOptionIndex) => (
                            <React.Fragment key={roomOptionIndex}>
                              <li>
                                <h6>{roomOption?.productName}</h6>
                                <ul>
                                  <li className="list__item">
                                    {roomOption?.accommodationName}
                                    {!isNil(roomOption?.regimeName) && ', '}
                                    {roomOption?.regimeName}
                                  </li>
                                </ul>
                                <p>
                                  (
                                  {roomOption?.from === roomOption?.to ? (
                                    getDateText(roomOption?.from)
                                  ) : (
                                    <>
                                      {getDateText(roomOption?.from)} &gt; {getDateText(roomOption?.to)}
                                    </>
                                  )}
                                  )
                                </p>
                              </li>
                              {!isEmpty(activeOption?.groups) &&
                                activeOption?.groups.map((x, i) => {
                                  if (!x.options.some((y) => y.isSelected)) return;

                                  return <SummaryBookingOption key={i} group={x} />;
                                })}
                              {!isEmpty(activeOption?.optionUnits) && activeOption?.optionUnits.map((x, i) => <SummaryBookingOptionUnit key={i} unit={x} />)}
                              {!isEmpty(activeOption?.optionPax) && activeOption?.optionPax.map((x, i) => <SummaryBookingOptionPax key={i} pax={x} />)}
                              {packageDetails?.outwardFlights &&
                                packageDetails.outwardFlights
                                  .filter((x) => x.isSelected)
                                  .map((flight, i) => (
                                    <SummaryFlight key={i} flightMetaData={flight.flightMetaData} header={translations.SIDEBAR.DEPARTURE_FLIGHT} />
                                  ))}
                              {packageDetails?.returnFlights &&
                                packageDetails.returnFlights
                                  .filter((x) => x.isSelected)
                                  .map((flight, i) => (
                                    <SummaryFlight key={i} flightMetaData={flight.flightMetaData} header={translations.SIDEBAR.ARRIVAL_FLIGHT} />
                                  ))}
                            </React.Fragment>
                          ))}
                      </>
                    )}
                  </ul>
                </div>
              </div>
            </div>

            {settings.enableVoucher && (
              <div className="form__region">
                <div className="form__row">
                  <div className="form__group">
                    <div className="form__region-header">
                      <h5 className="form__region-heading">{translations.SUMMARY.VOUCHERS}</h5>
                    </div>
                  </div>
                </div>
                <div className="form__row">
                  <div className="form__group">
                    <input
                      type="text"
                      className="form__input info-message__voucher__input"
                      defaultValue={voucher.code}
                      onChange={(e) => setVoucher({ code: e.target.value })}
                    />
                    <button type="button" className={buildClassName(['cta', !voucher.code && 'cta--disabled'])} onClick={(e) => handleValidateVoucher()}>
                      {translations.SUMMARY.VOUCHER_VALIDATE}
                    </button>
                  </div>
                </div>
                <div className="form__row">
                  <div className="form__group info-message__voucher">
                    {voucher.isValid && voucher.isValidated && (
                      <div className="info-message info-message__voucher__valid">
                        <span>{translations.SUMMARY.VOUCHER_VALID}</span>
                        <button type="button" className="cta cta--secondary" onClick={handleAddVoucher}>
                          {translations.SUMMARY.ADD_VOUCHER}
                        </button>
                      </div>
                    )}
                    {!voucher.isValid && voucher.isValidated && <div className="info-message--error">{translations.SUMMARY.VOUCHER_INVALID}</div>}
                  </div>
                </div>
                <div className="form__row">
                  <ul className="info-message__voucher">
                    {!isEmpty(bookRequest?.payload.voucherCodes) &&
                      bookRequest?.payload.voucherCodes?.map((y, i) => (
                        <li key={i}>
                          <div className="info-message__voucher__list">
                            {y}{' '}
                            <button type="button" className="cta--add-remove" onClick={(e) => handleRemoveVoucher(y)}>
                              <Icon height={16} name="ui-trashcan" />
                            </button>
                          </div>
                        </li>
                      ))}
                  </ul>
                </div>
              </div>
            )}

            {!isEmpty(notifications) && (
              <div className="form__region">
                <div className="form__row">
                  <div className="form__group">
                    <div className="info-message">
                      <Icon name="ui-tooltip" className="icon--secondary-color" />
                      <div className="info-message__copy">
                        <h5>{translations.SUMMARY.NOTIFICATIONS_TITLE}</h5>
                        <>
                          {uniqBy(
                            notifications.filter((x) => !x.hasToBeConfirmed),
                            'id'
                          ).map((notification) => (
                            <span key={notification.id} className="checkbox__label-text">
                              <strong className="checkbox__label-text--title">{notification.title}</strong>
                              <span className="checkbox__label-text--description">{notification.description}</span>
                            </span>
                          ))}
                          {uniqBy(
                            notifications.filter((x) => x.hasToBeConfirmed),
                            'id'
                          ).map((notification) => (
                            <div className="checkbox" key={notification.id}>
                              <label className="checkbox__label">
                                <input
                                  type="checkbox"
                                  className="checkbox__input"
                                  checked={notification.isConfirmed}
                                  onChange={(e) => handleNotificationChange(notification.id, e.target.checked)}
                                />
                                <span className="checkbox__label-text">
                                  <strong className="checkbox__label-text--title">{notification.title}</strong>
                                  <span className="checkbox__label-text--description">{notification.description}</span>
                                </span>
                              </label>
                            </div>
                          ))}
                        </>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            )}

            <div className="form__region">
              <div className="form__row">
                <div className="form__group">
                  <div className="form__region-header">
                    <h5 className="form__region-heading">{translations.SUMMARY.REMARKS}</h5>
                  </div>
                </div>
              </div>
              <div className="form__row">
                <div className="form__group">
                  <textarea className="form__input" defaultValue={remarks} onChange={(e) => handleRemarksChange(e.target.value)}></textarea>
                </div>
              </div>
            </div>

            <div className="form__region">
              <div className="form__row">
                <div className="form__group">
                  <div className="info-message">
                    <Icon name="ui-tooltip" className="icon--secondary-color" />
                    <div className="info-message__copy">
                      <h5>{translations.SUMMARY.VALIDATE_TITLE}</h5>
                      {settings.customValidateText ? (
                        <div
                          dangerouslySetInnerHTML={{
                            __html: settings.customValidateText
                          }}></div>
                      ) : (
                        <>
                          <p>{settings.isOffer ? translations.SUMMARY.VALIDATE_TEXT_OFFER : translations.SUMMARY.VALIDATE_TEXT_BOOKING}</p>
                          {settings.allowOption && <p>{translations.SUMMARY.VALIDATE_TEXT_OPTION}</p>}
                        </>
                      )}
                      {checkboxes &&
                        checkboxes.map((checkbox) => (
                          <div className="checkbox" key={checkbox.id}>
                            <label className="checkbox__label">
                              <input
                                type="checkbox"
                                className="checkbox__input"
                                checked={checkbox.isSelected}
                                onChange={(e) => handleCheckboxChange(checkbox.id, e.target.checked)}
                              />
                              <span
                                className="checkbox__label-text"
                                dangerouslySetInnerHTML={{
                                  __html: checkbox.text
                                }}
                              />
                            </label>
                          </div>
                        ))}
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>

          <div className="booking__navigator">
            {settings.skipRouter ? (
              <button type="button" title={translations.STEPS.PREVIOUS} onClick={() => goPrevious()} className="cta cta--secondary">
                {translations.STEPS.PREVIOUS}
              </button>
            ) : (
              <Link
                to={`${!settings.skipBasePathInRouting ? settings.basePath : ''}${settings.travellers.pathSuffix}?${bookingQueryString}`}
                title={translations.STEPS.PREVIOUS}
                className="cta cta--secondary">
                {translations.STEPS.PREVIOUS}
              </Link>
            )}
            {settings.allowOption && (
              <button
                title={translations.STEPS.SUBMIT_OPTION}
                className={buildClassName(['cta', !userValidated && 'cta--disabled'])}
                disabled={!userValidated}
                name="option">
                {translations.STEPS.SUBMIT_OPTION}
              </button>
            )}
            <button
              title={settings.isOffer ? translations.STEPS.SUBMIT_OFFER : translations.STEPS.SUBMIT_BOOKING}
              className={buildClassName(['cta', !userValidated && 'cta--disabled'])}
              disabled={!userValidated}
              name="default">
              {settings.isOffer ? translations.STEPS.SUBMIT_OFFER : translations.STEPS.SUBMIT_BOOKING}
            </button>
          </div>
        </form>
      )}
    </>
  );
};

export default Summary;
