import { BookingPackageLine, PerPackageOption } from '@qite/tide-client/build/types';
import { compact, first, isEmpty, sortBy, uniqBy } from 'lodash';
import React from 'react';
import { buildClassName } from '../../../shared/utils/class-util';
import { getPriceDifferenceText } from '../../../shared/utils/localization-util';
import { getDateText } from '../sidebar/sidebar-util';
import { useSelector } from 'react-redux';
import { selectCurrencyCode } from '../booking/selectors';

interface OptionItemProps {
  option: PerPackageOption;
  parentId: string;
  index: number;
  selectedPrice: number;
  onOptionChange?: (option: PerPackageOption, index: number) => void;
}

const OptionItem: React.FC<OptionItemProps> = ({ option, parentId, index, selectedPrice, onOptionChange }) => {
  const currencyCode = useSelector(selectCurrencyCode);

  const priceDifference =
    option.requirementType === 1
      ? option.isSelected
        ? -option.line.price
        : option.line.price
      : option.requirementType === 2 || option.requirementType === 3
      ? option.line.price - selectedPrice
      : 0;

  const accommodations = uniqBy(
    compact(
      [option.line, ...option.alternatives].map((option) => {
        if (!option.accommodationCode) {
          return undefined;
        }

        return {
          accommodationCode: option.accommodationCode,
          accommodationName: option.accommodationName
        };
      })
    ),
    'accommodationCode'
  );

  const regimes = uniqBy(
    compact(
      [option.line, ...option.alternatives]
        .filter((x) => x.accommodationCode === option.line.accommodationCode)
        .map((option) => {
          return {
            regimeCode: option.regimeCode,
            regimeName: option.regimeName
          };
        })
    ),
    'regimeCode'
  );

  const handleAccommodationChange: React.FormEventHandler<HTMLSelectElement> = (e) => {
    const accommodationCode = e.currentTarget.value;

    var accommodationAlternatives = option.alternatives.filter((x) => x.accommodationCode == accommodationCode);

    if (accommodationAlternatives) {
      const alternative = accommodationAlternatives.find((x) => x.regimeCode == option.line.regimeCode) ?? accommodationAlternatives[0];

      updateOption(alternative);
    }

    e.preventDefault();
  };

  const handleRegimeChange: React.FormEventHandler<HTMLSelectElement> = (e) => {
    const regimeCode = e.currentTarget.value;
    const alternative = option.alternatives.find((x) => x.accommodationCode === option.line.accommodationCode && x.regimeCode == regimeCode);

    updateOption(alternative);

    e.preventDefault();
  };

  const handleSelectionChange: React.FormEventHandler<HTMLInputElement> = (e) => {
    const updatedOption = {
      ...option,
      isSelected: e.currentTarget.checked
    };

    // Bubble up option changes
    if (onOptionChange) onOptionChange(updatedOption, index);
  };

  const updateOption = (alternative?: BookingPackageLine) => {
    if (alternative) {
      const updatedAlternatives = [option.line, ...option.alternatives].filter((x) => x != alternative).sort((x, y) => x.price - y.price);

      const updatedOption = {
        ...option,
        line: alternative,
        alternatives: updatedAlternatives
      };

      // Bubble up option changes
      if (onOptionChange) onOptionChange(updatedOption, index);
    }
  };

  const getAccommodationPriceDifference = (accommodation: { accommodationCode: string; accommodationName: string }) => {
    if (option.line.accommodationCode === accommodation.accommodationCode) return '';

    var currentPrice = option.line.price;
    var accommodationPrice = first(
      sortBy(
        option.alternatives.filter((x) => x.accommodationCode === accommodation.accommodationCode),
        (x) => x.price
      )
    )?.price;

    const priceDifference = (accommodationPrice ?? 0) - currentPrice;
    if (priceDifference !== 0) {
      return `(${getPriceDifferenceText(priceDifference, currencyCode)})`;
    } else {
      return '';
    }
  };

  const getRegimePriceDifference = (regime: { regimeCode: string; regimeName: string }) => {
    if (option.line.regimeCode === regime.regimeCode) return '';

    var currentPrice = option.line.price;
    var regimePrice = option.alternatives.find((x) => x.accommodationCode === option.line.accommodationCode && x.regimeCode === regime.regimeCode)?.price;

    const priceDifference = (regimePrice ?? 0) - currentPrice;
    if (priceDifference !== 0) {
      return `(${getPriceDifferenceText(priceDifference, currencyCode)})`;
    } else {
      return '';
    }
  };

  return (
    <>
      {option.requirementType === 0 && (
        <input
          type="checkbox"
          id={`${parentId}_${index}`}
          className={buildClassName(['checkbox__input', 'checkbox__input--parent'])}
          defaultChecked={true}
          disabled={true}></input>
      )}
      {option.requirementType === 1 && (
        <input
          type="checkbox"
          id={`${parentId}_${index}`}
          className={buildClassName(['checkbox__input', 'checkbox__input--parent'])}
          defaultChecked={option.isSelected}
          onChange={handleSelectionChange}></input>
      )}
      {(option.requirementType === 2 || option.requirementType === 3) && (
        <input
          type="radio"
          value={index}
          id={`${parentId}_${index}`}
          name={parentId}
          className={buildClassName(['radiobutton__input', 'radiobutton__input--parent'])}
          defaultChecked={option.isSelected}
          onChange={handleSelectionChange}></input>
      )}
      <span className="radiobutton__label-text">
        <div className="date-list">
          <span className="date-list__item">{getDateText(option.line.startDate, true)}</span>
          <span className="date-list__item">{getDateText(option.line.endDate, true)}</span>
        </div>
      </span>
      <div className="tree__columns-actions">
        <div className="tree__columns">
          <div className="tree__column">
            <div className="tree__product-name">{option.line.productName}</div>
          </div>
          {isEmpty(option.alternatives) && (
            <>
              <div className="tree__column">
                <span className="tree__product-name">{option.line.accommodationName}</span>
              </div>
              <div className="tree__column">
                <span className="tree__product-name">{option.line.regimeName}</span>
              </div>
            </>
          )}
          {!isEmpty(option.alternatives) && (
            <>
              <div className="tree__column">
                <div className="select-wrapper">
                  <div className="select-wrapper__select">
                    <select onChange={handleAccommodationChange}>
                      {accommodations.map((accommodation) => (
                        <option defaultValue={option.line.accommodationCode} key={accommodation.accommodationCode} value={accommodation.accommodationCode}>
                          {accommodation.accommodationName} {getAccommodationPriceDifference(accommodation)}
                        </option>
                      ))}
                    </select>
                  </div>
                </div>
              </div>
              <div className="tree__column">
                <div className="select-wrapper">
                  {regimes?.length > 1 && (
                    <div className="select-wrapper__select">
                      <select defaultValue={option.line.regimeCode} onChange={handleRegimeChange}>
                        {regimes.map((regime) => (
                          <option key={regime.regimeCode} value={regime.regimeCode}>
                            {regime.regimeName} {getRegimePriceDifference(regime)}
                          </option>
                        ))}
                      </select>
                    </div>
                  )}
                  {regimes.length === 1 && <>{regimes.find((x) => x.regimeCode == option.line.regimeCode)?.regimeName}</>}
                </div>
              </div>
            </>
          )}
          <div className={buildClassName(['tree__column', 'tree__column--price'])}>
            {!option.isSelected && (
              <span className={buildClassName(['price', priceDifference > 0 && 'price--increase', priceDifference < 0 && 'price--decrease'])}>
                {getPriceDifferenceText(priceDifference, currencyCode)}
              </span>
            )}
          </div>
        </div>
      </div>
    </>
  );
};

export default OptionItem;
