import React, { useState } from "react";
import { MultiSelect, Icon } from "@komi-app/components";
import When from "@komi-app/when";
import { RuleClause as RuleClauseOld } from "../RuleClause/index.old";
import { RuleClause as RuleClauseNew } from "../RuleClause/index.new";
import { SelectRuleBlock } from "../../Segment/RuleBlocks";

import { segmentPropertyAttributes as defaultSegmentPropertyAttributes } from "../../constants/segments/attributes";
import { operatorOptions } from "../../constants/segments/operators";

import {
  SegmentExpressionOperator,
  SegmentExpressionType,
  SegmentAttribute,
  SegmentAttributeType,
  SegmentExpression,
  SegmentPropertyAttribute,
} from "@komi-app/fans-sdk";

import { noop } from "../../utils/fns";
import { createDefaultExpression } from "../../utils/segments";
import {
  getAttributeByName,
  segmentAttributesToOptions,
} from "../../utils/attributes";

import classnames from "classnames";
import "./SegmentPropRule.scss";
import { FLAGS, useFeatureIsOn } from "@komi-app/flags-sdk";

export interface SegmentPropRuleProps extends React.HTMLProps<HTMLDivElement> {
  // should not be optional once feat-cac-99-geo-segmentation is turned on
  segmentPropertyAttributes?: SegmentPropertyAttribute[];
  expressions: SegmentExpression[];
  onExpressionsChange?: (expressions: SegmentExpression[]) => void;
}

export const SegmentPropRule: React.FC<SegmentPropRuleProps> = ({
  // remove default once feat-cac-99-geo-segmentation is turned on
  segmentPropertyAttributes = defaultSegmentPropertyAttributes,
  expressions = [],
  onExpressionsChange = noop,
  ...props
}) => {
  const segmentAttributePropertyOptions = segmentAttributesToOptions(
    segmentPropertyAttributes,
    "Audience Properties",
  );
  const [firstExpression] = expressions;

  // Get the selected expressions for disabling
  const selectedExpressions = expressions.map(({ attributeName }) =>
    getAttributeByName(attributeName, segmentPropertyAttributes),
  );

  // Operators are toggled at the rule level, and stored at the expression level, so
  // we handle them here and set on each expression
  const [expressionOperator, setExpressionOperator] =
    useState<SegmentExpressionOperator>(
      firstExpression
        ? firstExpression.expressionOperator
        : SegmentExpressionOperator.And,
    );

  const clauses = expressions.filter(
    ({ expressionType, attributeType }) =>
      expressionType === SegmentExpressionType.Clause &&
      attributeType === SegmentAttributeType.Property,
  );

  const handleClauseAppendOptionClick = ([
    clauseAttribute,
  ]: SegmentAttribute[]): void => {
    // Create new clause
    const ruleOrder = expressions.length;
    const newClause = createDefaultExpression(SegmentAttributeType.Property, {
      ruleOrder,
      expressionOrder: 0,
      attributeName: clauseAttribute.name,
      attributeValues: clauseAttribute.defaultValues,
    });

    const updatedExpressions = [...expressions, newClause];
    onExpressionsChange(updatedExpressions);
  };

  const handleClauseChange =
    (clauseIndex: number) =>
    (clause: SegmentExpression): void => {
      const updatedExpressions = [
        ...expressions.slice(0, clauseIndex),
        clause,
        ...expressions.slice(clauseIndex + 1),
      ];
      onExpressionsChange(updatedExpressions);
    };
  const handleClauseDeleteClick = (clauseIndex: number) => {
    const updatedExpressions = [
      ...expressions.slice(0, clauseIndex),
      ...expressions.slice(clauseIndex + 1),
    ];
    onExpressionsChange(updatedExpressions);
  };

  const handleExpressionOperatorChange = ([
    operator,
  ]: SegmentExpressionOperator[]): void => {
    const updatedExpressions = expressions.map((expression) => ({
      ...expression,
      expressionOperator: operator,
    }));

    onExpressionsChange(updatedExpressions);
    setExpressionOperator(operator);
  };

  const classNames = classnames("segment-prop-rule", props.className);
  const clausesClassName = classnames("segment-prop-rule__clauses", {
    "segment-prop-rule__clauses-empty": clauses.length === 0,
  });

  return (
    <div {...props} className={classNames}>
      <div className={clausesClassName}>
        {clauses.map((expression, index) => (
          <div key={index} className="segment-prop-rule__controlled-clause">
            {index === 0 ? (
              <p className="segment-rule__label segment-prop-rule__label">
                where
              </p>
            ) : (
              <SelectRuleBlock
                className="segment-rule__clause-operator segment-prop-rule__clause-operator"
                selectedValues={expressionOperator}
                onValueSelectionChange={handleExpressionOperatorChange}
                options={operatorOptions}
              />
            )}

            <RuleClauseNew
              key={index}
              className="segment-prop-rule__clause"
              expression={expression}
              selectedExpressions={selectedExpressions}
              properties={segmentPropertyAttributes}
              onExpressionChange={handleClauseChange(index)}
              segmentPropertyAttributes={segmentPropertyAttributes}
            />

            <Icon
              className="segment-rule__trash"
              name="trash"
              fill="#FF3C45"
              onClick={() => handleClauseDeleteClick(index)}
              dataTestId="remove-icon"
            />
          </div>
        ))}
      </div>

      <MultiSelect
        optionsClassName="segment-rule__statement-append-menu"
        disabledValues={selectedExpressions}
        isMultiselection={false}
        options={segmentAttributePropertyOptions}
        onOptionValueSelectionChange={handleClauseAppendOptionClick}
      >
        <MultiSelect.Toggle>
          {({ toggleIsMenuVisible }) => (
            <div
              className="segment-rule__statement-append-button"
              onClick={toggleIsMenuVisible}
            >
              <div className="segment-rule__statement-append-button-icon">
                <Icon name="addFilled" fill="#0F69E6" />
              </div>
              <p className="segment-rule__statement-append-button-label">
                Add Property
              </p>
            </div>
          )}
        </MultiSelect.Toggle>
      </MultiSelect>
    </div>
  );
};
