import { FC, HTMLAttributes } from "react";
import { useDispatch } from "react-redux";

import {
  characterActions,
  ChoiceUtils,
} from "@dndbeyond/character-rules-engine";

import { useCharacterEngine } from "~/hooks/useCharacterEngine";
import { DetailChoice } from "~/tools/js/Shared/containers/DetailChoice";
import { CharClass, Choice, ClassDefinitionContract, Feat } from "~/types";

export interface FeatureChoiceProps extends HTMLAttributes<HTMLDivElement> {
  choice: Choice;
  charClass?: CharClass;
  featsData: Feat[];
  subclassData?: ClassDefinitionContract[];
  onChoiceChange: (
    choiceId: string,
    type: number,
    value: any,
    parentChoiceId: string | null
  ) => void;
  collapseDescription?: boolean;
}

/**
 * Component for rendering a features choice(s) - for species traits and class features - using DetailChoice for the choices and mapping over any feat sub choices if the choice from a species trait or class feature is a feat.
 * It is used in both the builder and character sheet sidebar panes.
 */
export const FeatureChoice: FC<FeatureChoiceProps> = ({
  charClass,
  choice,
  featsData,
  subclassData,
  onChoiceChange,
  className,
  collapseDescription,
  ...props
}) => {
  const dispatch = useDispatch();
  const {
    classUtils,
    featLookup,
    preferences,
    prerequisiteData,
    choiceInfo,
    ruleData,
    entityRestrictionData,
  } = useCharacterEngine();

  const handleChoiceChange = (
    id: string,
    type: number,
    value: any,
    parentChoiceId: string | null
  ): void => {
    onChoiceChange(id, type, value, parentChoiceId);
  };

  const handleFeatChoiceChange = (
    featId: number,
    id: string | null,
    type: number,
    value: any
  ): void => {
    if (id !== null) {
      dispatch(characterActions.featChoiceSetRequest(featId, type, id, value));
    }
  };

  const { description, options, featSubChoices } =
    ChoiceUtils.getSortedChoiceOptionsForFeaturesInfo(
      choice,
      featsData,
      featLookup,
      charClass || null,
      subclassData || [],
      preferences,
      prerequisiteData,
      ruleData,
      entityRestrictionData
    );

  return (
    <div className={className} {...props}>
      <DetailChoice
        {...choice}
        choice={choice}
        options={options}
        onChange={handleChoiceChange}
        description={description || ""}
        choiceInfo={choiceInfo}
        classId={charClass && classUtils.getId(charClass)}
        showBackgroundProficiencyOptions={true}
        collapseDescription={collapseDescription}
      />
      {featSubChoices &&
        featSubChoices.map((subChoice) => {
          const id = ChoiceUtils.getId(subChoice.choice);
          return (
            <DetailChoice
              {...subChoice.choice}
              label={subChoice.choice.label}
              choice={subChoice.choice}
              key={id !== null ? id : ""}
              options={subChoice.options}
              onChange={(id, type, value) =>
                handleFeatChoiceChange(subChoice.featId, id, type, value)
              }
              choiceInfo={choiceInfo}
              showBackgroundProficiencyOptions={true}
              description={subChoice.description}
            />
          );
        })}
    </div>
  );
};
