import { ApplicationHandleResult } from "@openim/wasm-client-sdk";
import {
  FriendApplicationItem,
  GroupApplicationItem,
} from "@openim/wasm-client-sdk/lib/types/entity";
import { Button, Spin } from "antd";
import { t } from "i18next";
import { memo, useCallback, useState } from "react";

import OIMAvatar from "@/components/OIMAvatar";
import { IMSDK } from "@/layout/MainContentWrap";
import { emit } from "@/utils/events";

type ApplicationItemSource = FriendApplicationItem & GroupApplicationItem;

export type AccessFunction = (
  source: Partial<ApplicationItemSource>,
  isRecv: boolean,
) => Promise<void>;

const ApplicationItem = ({
  currentUserID,
  source,
  onAccept,
  onReject,
}: {
  source: Partial<ApplicationItemSource>;
  currentUserID: string;
  onAccept: AccessFunction;
  onReject: AccessFunction;
}) => {
  const [loading, setLoading] = useState(false);
  const isRecv = source.userID !== currentUserID && source.fromUserID !== currentUserID;
  const isGroup = Boolean(source.groupID);
  const showActionBtn = source.handleResult === 0 && isRecv;

  const getApplicationDesc = () => {
    if (isGroup) {
      return t("application.applyToJoin");
    }
    return isRecv ? t("application.applyToFriend") : t("application.applyToAdd");
  };

  const getTitle = () => {
    if (isGroup) {
      return isRecv ? source.nickname : source.groupName;
    }
    return isRecv ? source.fromNickname : source.toNickname;
  };

  const getStatusStr = () => {
    if (source.handleResult === ApplicationHandleResult.Agree) {
      return t("application.agreed");
    }
    if (source.handleResult === ApplicationHandleResult.Reject) {
      return t("application.refused");
    }
    return isRecv ? t("application.waitingHandle") : t("application.pending");
  };

  const getAvatarUrl = () => {
    if (isGroup) {
      return isRecv ? source.userFaceURL : source.groupFaceURL;
    }
    return isRecv ? source.fromFaceURL : source.toFaceURL;
  };

  const loadingWrap = async (isAgree: boolean) => {
    setLoading(true);
    await (isAgree ? onAccept(source, isRecv) : onReject(source, isRecv));
    setLoading(false);
  };

  const tryShowCard = useCallback(async () => {
    if (isGroup) {
      const { data } = await IMSDK.getSpecifiedGroupsInfo([source.groupID!]);
      emit("OPEN_GROUP_CARD", data[0]);
      return;
    }
    window.userClick(isRecv ? source.fromUserID : source.toUserID);
  }, []);

  const btnStyle = {
    height: 32,
    flex: 1,
    borderRadius: 8,
  };

  return (
    <Spin spinning={loading}>
      <div className="flex min-h-[72px] flex-row items-center justify-between px-4 py-3 transition-colors duration-100 ease-out hover:bg-[var(--chat-bg)]">
        <div className="mr-3 flex min-w-0 flex-1 flex-row">
          <OIMAvatar
            size={48}
            src={getAvatarUrl()}
            text={getTitle()}
            isgroup={isGroup && !isRecv}
            onClick={tryShowCard}
          />
          <div className="ml-3 min-w-0 flex-1">
            <p className="truncate text-base text-[var(--base-black)]">{getTitle()}</p>
            <p className="truncate pt-1 text-xs text-[var(--sub-text)]">
              {getApplicationDesc()}
              {(isGroup || (!isGroup && !isRecv)) && (
                <span className="ml-1 text-xs text-[var(--primary)]">
                  {source.groupName || source.toNickname}
                </span>
              )}
            </p>
            {source.reqMsg && (
              <p className="truncate text-xs text-[var(--sub-text)]">{source.reqMsg}</p>
            )}
          </div>
        </div>

        {showActionBtn && (
          <div className="flex w-[132px] shrink-0 flex-row gap-2">
            <Button size="small" onClick={() => loadingWrap(false)} style={btnStyle}>
              {t("application.refuse")}
            </Button>
            <Button
              size="small"
              type="primary"
              style={{ ...btnStyle, backgroundColor: "var(--primary)" }}
              onClick={() => loadingWrap(true)}
            >
              {t("application.agree")}
            </Button>
          </div>
        )}

        {!showActionBtn && (
          <div className="flex shrink-0 flex-row items-center">
            <p className="text-sm text-[var(--sub-text)]">{getStatusStr()}</p>
          </div>
        )}
      </div>
    </Spin>
  );
};

export default memo(ApplicationItem);
