import clsx from "clsx";
import { FC, useCallback, useContext, useEffect, useState } from "react";

import {
  GameLogContext,
  isMessage,
  useAwaitMessageBroker,
} from "@dndbeyond/game-log-components";
import type { AnyMessage } from "@dndbeyond/message-broker-lib";
import { Rollable } from "@dndbeyond/pocket-dimension-dice/components/Rollable";
import type { RollableProps } from "@dndbeyond/pocket-dimension-dice/components/Rollable";
import "@dndbeyond/pocket-dimension-dice/components/Rollable/index.css";
import { RollDicePayload } from "@dndbeyond/pocket-dimension-dice/types";

export interface DigitalDiceWrapperProps
  extends Omit<RollableProps, "dmId" | "gameId"> {
  rollCallback?: (rollData: RollDicePayload["data"]) => void;
  isDiceEnabled?: boolean;
}

export const DigitalDiceWrapper: FC<DigitalDiceWrapperProps> = ({
  isContextMenuEnabled = true,
  rollType,
  children,
  diceNotation,
  isDiceEnabled = true,
  action,
  rollKind,
  entityId,
  entityType,
  name,
  rollCallback,
}) => {
  const [{ activeCampaign }] = useContext(GameLogContext);
  const [rollData, setRollData] = useState<RollDicePayload["data"]>();
  const mb = useAwaitMessageBroker();
  const handleMessage = useCallback(
    (message: AnyMessage) => {
      if (
        isMessage(message) &&
        message.eventType === "dice/roll/fulfilled" &&
        message.data.rollId === rollData?.rollId
      ) {
        rollCallback?.(rollData!);
        setRollData(undefined);
      }
    },
    [rollCallback, rollData]
  );

  // Only subscribe when there's a pending roll to listen for
  useEffect(() => {
    if (!mb || !rollCallback || !rollData) {
      return;
    }

    return mb.subscribe(handleMessage);
  }, [mb, rollCallback, rollData, handleMessage]);

  return (
    <Rollable
      className={clsx(isDiceEnabled && "integrated-dice__container")}
      diceNotation={String(diceNotation)}
      action={action}
      entityId={entityId}
      entityType={entityType}
      name={name}
      dmId={activeCampaign ? String(activeCampaign.dmId) : undefined}
      gameId={activeCampaign ? String(activeCampaign.id) : undefined}
      rollKind={rollKind}
      rollType={rollType}
      isContextMenuEnabled={isContextMenuEnabled}
      isDiceEnabled={isDiceEnabled}
      setRollData={setRollData}
    >
      {children}
    </Rollable>
  );
};
