import isEmpty from 'lodash/isEmpty';
import DOMPurify from 'dompurify';
import { Link, toTextList, getLink as getLinkUtil } from '@abtnode/util/lib/notification-preview/highlight';
import { isSameAddr } from '@abtnode/util/lib/notification-preview/func';
import { client } from '../libs/client';

/**
 * 通知对象的活动目标接口
 */
interface ActivityTarget {
  type?: string;
  id?: string;
}

/**
 * 通知对象的活动元数据接口
 */
interface ActivityMeta {
  id?: string;
}

/**
 * 活动对象接口
 */
interface Activity {
  type?: string;
  actor?: string;
  target?: ActivityTarget;
  meta?: ActivityMeta;
}

/**
 * 通知对象接口
 */
interface Notification {
  activity?: Activity;
  actorInfo?: any;
  severity?: string;
  title?: string;
  description?: string;
  items?: Notification[];
}

/**
 * 合并相邻的通知数据
 * 合并条件:
 * 1. 数据必须是相邻的
 * 2. activity.type 必须相同且不为 null 或 undefined
 * 3. 如果存在target对象，activity.target.type和activity.target.id都必须相同
 * 4. 如果相邻数据的 activity.type 相同但没有 activity.target 对象，则需要合并
 *
 * @param {Notification[]} notifications - 需要处理的通知数据
 * @returns {Notification[]} - 合并后的通知数组
 */
export const mergeAdjacentNotifications = (notifications: Notification[]): Notification[] => {
  if (!notifications || !notifications.length) {
    return [];
  }

  const result: Notification[] = [];
  let currentGroup: Notification | null = null;
  let groupItems: Notification[] = [];

  notifications.forEach((notification: Notification) => {
    // 如果没有activity或activity.type为null/undefined或者这是第一条记录
    if (!notification.activity || !notification.activity.type || !currentGroup) {
      // 处理前一个分组（如果存在）
      if (currentGroup) {
        // 如果只有一个通知，直接添加原通知
        if (groupItems.length === 1) {
          result.push(groupItems[0]);
        } else {
          // 将items添加到第一个通知对象，并将其添加到结果中
          currentGroup.items = groupItems;
          result.push(currentGroup);
        }
      }

      // 处理当前通知
      if (notification.activity && notification.activity.type) {
        // 将第一个通知对象作为组的基础，不创建新对象
        currentGroup = notification;
        groupItems = [notification];
      } else {
        // 无activity或activity.type的记录直接添加到结果中
        result.push(notification);
        // 重置当前组
        currentGroup = null;
        groupItems = [];
      }
      return;
    }

    // 获取当前组和当前通知的activity信息
    const currentActivity = groupItems[0].activity;
    const currentType = currentActivity?.type;
    const currentTargetType = currentActivity?.target?.type;
    const currentTargetId = currentActivity?.target?.id;

    const newType = notification.activity.type;
    const newTargetType = notification.activity.target?.type;
    const newTargetId = notification.activity.target?.id;

    // 判断是否需要合并
    const shouldMerge =
      // activity.type 必须相同且不为null或undefined
      currentType &&
      newType &&
      currentType === newType &&
      // 如果都没有target，可以合并
      ((!currentActivity?.target && !notification.activity.target) ||
        // 如果都有target，则target.type和target.id都必须相同
        (currentActivity?.target &&
          notification.activity.target &&
          currentTargetType === newTargetType &&
          currentTargetId === newTargetId));

    if (shouldMerge) {
      // 合并到当前组
      groupItems.push(notification);
    } else {
      // 不满足合并条件，处理当前组
      // 如果只有一个通知，直接添加原通知
      if (groupItems.length === 1) {
        result.push(groupItems[0]);
      } else {
        // 将items添加到第一个通知对象，并将其添加到结果中
        // 使用Object.assign创建浅拷贝，避免修改原对象
        const groupToAdd = Object.assign({}, currentGroup, { items: groupItems });
        result.push(groupToAdd);
      }

      // 开始新的分组
      currentGroup = notification;
      groupItems = [notification];
    }
  });

  // 处理最后一个分组（如果有）
  if (currentGroup) {
    // 如果只有一个通知，直接添加原通知
    if (groupItems.length === 1) {
      result.push(groupItems[0]);
    } else {
      // 将items添加到第一个通知对象，并将其添加到结果中
      // 使用Object.assign创建浅拷贝，避免修改原对象
      const groupToAdd = Object.assign({}, currentGroup, { items: groupItems });
      result.push(groupToAdd);
    }
  }

  return result;
};

/**
 * 判断通知是否包含activity
 * @param {Notification} notification - 通知对象
 * @returns {boolean} - 是否包含activity
 */
export const isIncludeActivity = (notification: Notification): boolean => {
  return !isEmpty(notification.activity) && !!notification.activity?.type && !!notification.activity?.actor;
};

/**
 * 是否可以自动已读
 */
export const canAutoRead = (notification: Notification | null | undefined): boolean => {
  const { severity } = notification || {};
  return !!severity && ['normal', 'success', 'info'].includes(severity);
};

/**
 * 获取 activity 的链接
 * 链接的来源有两种
 * 1. activity.meta.id
 * 2. activity.target.id
 * @param {Activity} activity - 活动对象
 * @returns {Object | null} - 活动的链接
 */
export const getActivityLink = (
  activity: Activity | null | undefined
): { metaLink?: string | null; targetLink?: string | null } | null => {
  if (!activity) {
    return null;
  }
  const { meta, target } = activity;
  return {
    metaLink: meta?.id,
    targetLink: target?.id,
  };
};

const getUserProfileUrl = async (did: string, locale: string) => {
  try {
    const profileUrl = await client.user.getProfileUrl({ did, locale });
    return profileUrl;
  } catch (error) {
    console.error(error);
    return undefined;
  }
};

const getLink = async (item: any, locale: string) => {
  const { type, did } = item;
  if (isSameAddr(type, 'did')) {
    const profileUrl = await getUserProfileUrl(did, locale);
    return profileUrl || getLinkUtil(item);
  }
  return getLinkUtil(item);
};

export const toClickableSpan = async (str: string, locale: string, isHighLight = true) => {
  const textList = toTextList(str);
  const result = await Promise.all(
    textList.map(async (item: any) => {
      if (item instanceof Link) {
        if (isHighLight) {
          const url = await getLink(item, locale);
          const { type, chainId, did } = item;

          // HACK: 邮件中无法支持 dapp 的展示，缺少 dapp 链接，只能作为加粗展示
          if (isSameAddr(type, 'dapp')) {
            return `<em class="dapp" data-type="${type}" data-chain-id="${chainId}" data-did="${did}">${item.text}</em>`;
          }
          if (url) {
            return `<a target="_blank" rel="noopener noreferrer" class="link" href="${url}">${item.text}</a>`;
          }

          // 默认展示为加粗
          return `<em class="common" data-type="${type}" data-chain-id="${chainId}" data-did="${did}">${item.text}</em>`;
        }
        return item.text;
      }

      return item;
    })
  ).then((results) => results.join(''));
  return result;
};

export const sanitize = (innerHtml: string) => {
  return DOMPurify.sanitize(innerHtml, {
    ALLOWED_ATTR: ['href', 'target', 'rel', 'class', 'id', 'style'],
  });
};
