import clsx from "clsx";
import { FC, HTMLAttributes, MouseEvent } from "react";

import {
  AccessUtils,
  CampaignUtils,
  FormatUtils,
  Infusion,
  InfusionUtils,
  RuleDataUtils,
  Constants,
} from "@dndbeyond/character-rules-engine/es";

import { MarketplaceCta } from "~/components/MarketplaceCta";
import { useCharacterEngine } from "~/hooks/useCharacterEngine";

import Snippet from "../../tools/js/smartComponents/Snippet";
import styles from "./styles.module.css";

interface Props extends Omit<HTMLAttributes<HTMLDivElement>, "onClick"> {
  infusion: Infusion;
  onClick?: (infusion: Infusion) => void;
}
export const InfusionPreview: FC<Props> = ({
  infusion,
  onClick,
  className,
  ...props
}) => {
  const { ruleData, snippetData, proficiencyBonus, partyInfo } =
    useCharacterEngine();

  const itemMappingId = InfusionUtils.getInventoryMappingId(infusion);
  const partyRestrictions = partyInfo
    ? CampaignUtils.getPartyInventoryRestrictions(partyInfo)
    : [];

  const isInfusedItemInParty = partyRestrictions.some(
    (restriction) =>
      restriction.type === Constants.PartyRestrictionTypeEnum.INFUSION &&
      restriction.inventoryMappingId === itemMappingId
  );

  const handleClick = (evt: MouseEvent): void => {
    if (onClick) {
      evt.stopPropagation();
      evt.nativeEvent.stopImmediatePropagation();
      onClick(infusion);
    }
  };

  //if you have access to the infusion via entitlments or the infused item is in the party - you can see the details, othwise show marketplace cta
  const isAccessible =
    AccessUtils.isAccessible(InfusionUtils.getAccessType(infusion)) ||
    isInfusedItemInParty;

  const getSourceNames = (): string | null => {
    const sources = InfusionUtils.getSources(infusion);
    let sourceNames: Array<string> = [];
    if (sources.length > 0) {
      sources.forEach((source) => {
        let sourceInfo = RuleDataUtils.getSourceDataInfo(
          source.sourceId,
          ruleData
        );

        if (sourceInfo !== null && sourceInfo.description !== null) {
          sourceNames.push(sourceInfo.description);
        }
      });
    }

    return sourceNames.length > 0
      ? FormatUtils.renderNonOxfordCommaList(sourceNames)
      : null;
  };

  return (
    <div
      className={clsx([onClick && styles.isInteractive, className])}
      onClick={handleClick}
      {...props}
    >
      <div className={styles.name}>
        Infusion: {InfusionUtils.getName(infusion)}
      </div>
      <div className={styles.snippet}>
        {isAccessible ? (
          <Snippet
            snippetData={snippetData}
            classLevel={
              InfusionUtils.getSelectedModifierData(infusion)?.value ?? null
            }
            proficiencyBonus={proficiencyBonus}
          >
            {InfusionUtils.getSnippet(infusion)}
          </Snippet>
        ) : (
          <MarketplaceCta
            sourceName={getSourceNames()}
            description="To unlock this infusion, check out the Marketplace to view purchase options."
          />
        )}
      </div>
    </div>
  );
};
