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";

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 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)})`;
    } 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)})`;
    } 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)}
              </span>
            )}
          </div>
        </div>
      </div>
    </>
  );
};

export default OptionItem;
