import { useNuxtApp } from "#imports";

async function getBulk(type, ids, apiVersion = 2) {
  if (ids.length === 0) {
    return [];
  }

  const url = `${type}?ids=${encodeURIComponent(JSON.stringify([...new Set(ids)]))}`;
  return await useBaseFetch(url, { apiVersion });
}

export async function fetchExtraNotificationData(notifications) {
  const bulk = {
    projects: [],
    reports: [],
    threads: [],
    users: [],
    versions: [],
    organizations: [],
  };

  for (const notification of notifications) {
    if (notification.body) {
      if (notification.body.project_id) {
        bulk.projects.push(notification.body.project_id);
      }
      if (notification.body.version_id) {
        bulk.versions.push(notification.body.version_id);
      }
      if (notification.body.report_id) {
        bulk.reports.push(notification.body.report_id);
      }
      if (notification.body.thread_id) {
        bulk.threads.push(notification.body.thread_id);
      }
      if (notification.body.invited_by) {
        bulk.users.push(notification.body.invited_by);
      }
      if (notification.body.organization_id) {
        bulk.organizations.push(notification.body.organization_id);
      }
    }
  }

  const reports = await getBulk("reports", bulk.reports);
  for (const report of reports) {
    if (report.item_type === "project") {
      bulk.projects.push(report.item_id);
    } else if (report.item_type === "user") {
      bulk.users.push(report.item_id);
    } else if (report.item_type === "version") {
      bulk.versions.push(report.item_id);
    }
  }
  const versions = await getBulk("versions", bulk.versions);
  for (const version of versions) {
    bulk.projects.push(version.project_id);
  }
  const [projects, threads, users, organizations] = await Promise.all([
    getBulk("projects", bulk.projects),
    getBulk("threads", bulk.threads),
    getBulk("users", bulk.users),
    getBulk("organizations", bulk.organizations, 3),
  ]);
  for (const notification of notifications) {
    notification.extra_data = {};
    if (notification.body) {
      if (notification.body.project_id) {
        notification.extra_data.project = projects.find(
          (x) => x.id === notification.body.project_id,
        );
      }
      if (notification.body.organization_id) {
        notification.extra_data.organization = organizations.find(
          (x) => x.id === notification.body.organization_id,
        );
      }
      if (notification.body.report_id) {
        notification.extra_data.report = reports.find((x) => x.id === notification.body.report_id);

        const type = notification.extra_data.report.item_type;
        if (type === "project") {
          notification.extra_data.project = projects.find(
            (x) => x.id === notification.extra_data.report.item_id,
          );
        } else if (type === "user") {
          notification.extra_data.user = users.find(
            (x) => x.id === notification.extra_data.report.item_id,
          );
        } else if (type === "version") {
          notification.extra_data.version = versions.find(
            (x) => x.id === notification.extra_data.report.item_id,
          );
          notification.extra_data.project = projects.find(
            (x) => x.id === notification.extra_data.version.project_id,
          );
        }
      }
      if (notification.body.thread_id) {
        notification.extra_data.thread = threads.find((x) => x.id === notification.body.thread_id);
      }
      if (notification.body.invited_by) {
        notification.extra_data.invited_by = users.find(
          (x) => x.id === notification.body.invited_by,
        );
      }
      if (notification.body.version_id) {
        notification.extra_data.version = versions.find(
          (x) => x.id === notification.body.version_id,
        );
      }
    }
  }
  return notifications;
}

export function groupNotifications(notifications) {
  const grouped = [];

  for (let i = 0; i < notifications.length; i++) {
    const current = notifications[i];
    const next = notifications[i + 1];
    if (current.body && i < notifications.length - 1 && isSimilar(current, next)) {
      current.grouped_notifs = [next];

      let j = i + 2;
      while (j < notifications.length && isSimilar(current, notifications[j])) {
        current.grouped_notifs.push(notifications[j]);
        j++;
      }

      grouped.push(current);
      i = j - 1; // skip i to the last ungrouped
    } else {
      grouped.push(current);
    }
  }

  return grouped;
}

function isSimilar(notifA, notifB) {
  return !!notifA.body.project_id && notifA.body.project_id === notifB.body.project_id;
}

export async function markAsRead(ids) {
  try {
    await useBaseFetch(`notifications?ids=${JSON.stringify([...new Set(ids)])}`, {
      method: "PATCH",
    });
    return (notifications) => {
      const newNotifs = notifications;
      newNotifs.forEach((notif) => {
        if (ids.includes(notif.id)) {
          notif.read = true;
        }
      });
      return newNotifs;
    };
  } catch (err) {
    const app = useNuxtApp();
    app.$notify({
      group: "main",
      title: "Error marking notification as read",
      text: err.data ? err.data.description : err,
      type: "error",
    });
    return () => {};
  }
}
