import {
  forwardRef,
  useImperativeHandle,
  useRef,
  useState,
} from 'react';

import { BsReply, BsTrash3 } from 'react-icons/bs';
import { LuCopy, LuPin } from 'react-icons/lu';

import { rpc } from '../../../api/request';
import {
  ShmChannelMessageType,
  TypeACFHLPSWEnum,
} from '../../../api/types';
import { toast } from '../../../components/ToastRoot';
import store from '../../../stores/store';
import { Menu, MenuItem } from '../../../ui/Menu';
import Popover from '../../../ui/Popover';
import { reactionsTypes } from './MessageItem';

type MessagePopoverOpenParams = {
  onReply?: (msg: ShmChannelMessageType) => void;
  onPinned?: () => void;
  onDelete?: () => void;
  msg: ShmChannelMessageType;
  onChange?: () => void;
};

export type MessagePopoverRefProps = {
  open: (params: MessagePopoverOpenParams) => void;
};

const copyToClipboard = (text?: string) => {
  if (!text) return;
  navigator.clipboard.writeText(text);
  toast('Скопировано');
};

const MessagePopover = forwardRef<MessagePopoverRefProps>((_, ref) => {
  const [msg, setMsg] = useState<ShmChannelMessageType | null>(null);
  const [open, setOpen] = useState(false);
  const [target, setTarget] = useState<HTMLElement | null>(null);
  const openParamsRef = useRef<MessagePopoverOpenParams | null>(null);

  useImperativeHandle(ref, () => ({
    open: (params) => {
      setMsg(params.msg);
      setTarget(document.getElementById(`msg-${params.msg._id}`));
      setOpen(true);
      openParamsRef.current = params;
    },
  }));

  const onClose = () => {
    setOpen(false);
    setTarget(null);
  };

  const sendReaction = (reaction: TypeACFHLPSWEnum) => {
    onClose();
    rpc
      .channelReaction({
        channel: msg?.channel,
        message: msg?._id,
        reaction,
      })
      .then(() => openParamsRef.current?.onChange?.());
  };

  if (!open || !msg?._id) return null;

  const canDelete = msg.owner == store.userID;
  const selectReaction = msg.reactions?.find((r) => r.user == store.userID);

  return (
    <Popover opened={open} onClose={onClose} target={target} width={260}>
      <div className="flex gap-1 px-2 pt-2 pb-1">
        {reactionsTypes.slice(0, 6).map((reaction) => {
          const active = selectReaction?.type === reaction.value;
          return (
            <button
              type="button"
              key={reaction.value}
              onClick={() => sendReaction(reaction.value)}
              className={`
                w-9 h-9 inline-flex items-center justify-center rounded-full
                text-[22px] tg-press
                ${active ? 'bg-[var(--tg-accent-soft)]' : 'hover:bg-[var(--tg-bg-secondary)]'}
              `}
            >
              {reaction.name}
            </button>
          );
        })}
      </div>

      <div className="mx-2 h-px bg-[var(--tg-divider)] my-1" />

      <Menu>
        <MenuItem
          icon={<BsReply />}
          title="Ответить"
          onClick={() => {
            if (!msg) return;
            openParamsRef.current?.onReply?.(msg);
            onClose();
          }}
        />
        {!!msg.text && (
          <MenuItem
            icon={<LuCopy />}
            title="Копировать текст"
            onClick={() => {
              copyToClipboard(msg.text);
              onClose();
            }}
          />
        )}
        <MenuItem
          icon={<LuPin />}
          title={msg.pinned?.enabled ? 'Открепить' : 'Закрепить'}
          onClick={() => {
            openParamsRef.current?.onPinned?.();
            onClose();
          }}
        />
        {canDelete && (
          <MenuItem
            icon={<BsTrash3 />}
            title="Удалить"
            danger
            onClick={() => {
              openParamsRef.current?.onDelete?.();
              onClose();
            }}
          />
        )}
      </Menu>
    </Popover>
  );
});

MessagePopover.displayName = 'MessagePopover';

export default MessagePopover;
