import { book, validateVoucher } from "@qite/tide-client";
import {
  BookingPackageRequest,
  BookingPackageVoucherRequest,
} from "@qite/tide-client/build/types";
import { Link, navigate, useLocation } from "@reach/router";
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 "../../components/icon";
import SettingsContext from "../../settings-context";
import { useAppDispatch } from "../../store";
import { SummaryCheckbox } from "../../types";
import {
  setBookingNumber,
  setBookingRemarks,
  setCurrentStep,
  setVoucherCodes,
} from "../booking/booking-slice";
import {
  CONFIRMATION_STEP,
  ERROR_STEP,
  TRAVELERS_FORM_STEP,
} from "../booking/constants";
import {
  selectActiveOption,
  selectAgentAdressId,
  selectApiSettings,
  selectBookingPackageBookRequest,
  selectBookingQueryString,
  selectLanguageCode,
  selectOfficeId,
  selectPackageDetails,
  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";

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

interface SummaryProps {}

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

  const settings = useContext(SettingsContext);

  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);

  if (!travelerFormValues) {
    if (settings.skipRouter) {
      dispatch(setCurrentStep(TRAVELERS_FORM_STEP));
    } else {
      navigate(`${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();
    setIsSubmitting(true);

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

    const tideClientConfig = buildTideClientConfig(apiSettings);

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

    if (bookRequest.payload.returnPaymentUrl) {
      const location = useLocation();
      bookRequest.payload.redirectUrl = `${location.protocol}//${location.host}${settings.basePath}`;
    }

    try {
      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.basePath}${settings.confirmation.pathSuffix}?${bookingQueryString}`
          );
        }
      }
    } catch (error) {
      if (settings.skipRouter) {
        dispatch(setCurrentStep(ERROR_STEP));
      } else {
        navigate(
          `${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}
      {!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">
                  <div className="form__group">
                    <div className="form__region-header">
                      <h5 className="form__region-heading">
                        {translations.SHARED.ROOM} {rIndex + 1}
                      </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 && (
                            <>
                              <li className="list__item">{`${
                                travelerFormValues?.street
                              } ${compact([
                                travelerFormValues?.houseNumber,
                                travelerFormValues?.box,
                              ]).join(" ")}, ${travelerFormValues?.zipCode} ${
                                travelerFormValues?.place
                              }`}</li>
                              <li className="list__item">
                                {travelerFormValues?.phone}
                              </li>
                              <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">
                    <li>
                      <h6>{activeOption?.name}</h6>
                      <ul>
                        {activeOption?.rooms.map((r, ri) => {
                          const roomOption = r.options.find(
                            (x) => x.isSelected
                          );
                          return (
                            <li key={ri} className="list__item">
                              {roomOption?.accommodationName}
                              {!isNil(roomOption?.regimeName) && ", "}
                              {roomOption?.regimeName}
                            </li>
                          );
                        })}
                      </ul>
                      <p>
                        ({getDateText(activeOption?.fromDate)} &gt;{" "}
                        {getDateText(activeOption?.toDate)})
                      </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) => (
                        <SummaryBookingOptionUnit unit={x} />
                      ))}
                    {!isEmpty(activeOption?.optionPax) &&
                      activeOption?.optionPax.map((x) => (
                        <SummaryBookingOptionPax pax={x} />
                      ))}
                    {packageDetails?.outwardFlights &&
                      packageDetails.outwardFlights
                        .filter((x) => x.isSelected)
                        .map((flight, i) => (
                          <SummaryFlight
                            key={i}
                            flight={flight}
                            header={translations.SIDEBAR.DEPARTURE_FLIGHT}
                          />
                        ))}
                    {packageDetails?.returnFlights &&
                      packageDetails.returnFlights
                        .filter((x) => x.isSelected)
                        .map((flight, i) => (
                          <SummaryFlight
                            key={i}
                            flight={flight}
                            header={translations.SIDEBAR.ARRIVAL_FLIGHT}
                          />
                        ))}
                  </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) => (
                        <li>
                          <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>
                      <p>
                        {settings.isOffer
                          ? translations.SUMMARY.VALIDATE_TEXT_OFFER
                          : translations.SUMMARY.VALIDATE_TEXT_BOOKING}
                      </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.basePath}${settings.travellers.pathSuffix}?${bookingQueryString}`}
                title={translations.STEPS.PREVIOUS}
                className="cta cta--secondary"
              >
                {translations.STEPS.PREVIOUS}
              </Link>
            )}
            <button
              title={
                settings.isOffer
                  ? translations.STEPS.SUBMIT_OFFER
                  : translations.STEPS.SUBMIT_BOOKING
              }
              className={buildClassName([
                "cta",
                !userValidated && "cta--disabled",
              ])}
              disabled={!userValidated}
            >
              {settings.isOffer
                ? translations.STEPS.SUBMIT_OFFER
                : translations.STEPS.SUBMIT_BOOKING}
            </button>
          </div>
        </form>
      )}
    </>
  );
};

export default Summary;
