const lower = (value) => String(value ?? "").toLowerCase();

const byDateDesc = (field) => (left, right) => {
  const leftTime = left[field] ? new Date(left[field]).getTime() : 0;
  const rightTime = right[field] ? new Date(right[field]).getTime() : 0;
  return rightTime - leftTime;
};

export const filterLibraryItems = (items, query) => {
  let next = [...items];

  if (!query.includeHidden) {
    next = next.filter((item) => !item.hidden);
  }

  if (query.category === "games") {
    next = next.filter((item) => item.type === "game");
  }

  if (query.category === "software") {
    next = next.filter((item) => item.type !== "game");
  }

  if (query.genre === "Latest Installed") {
    next = next.filter((item) => item.installedAt);
  } else if (query.genre === "Recently Played") {
    next = next.filter((item) => item.lastPlayed);
  } else if (query.genre !== "All Genres") {
    next = next.filter((item) => item.genre.some((genre) => lower(genre) === lower(query.genre)));
  }

  if (query.platform !== "all") {
    next = next.filter((item) => item.source === query.platform);
  }

  if (query.installedOnly) {
    next = next.filter((item) => item.installed);
  }

  if (query.playState === "played") {
    next = next.filter((item) => item.playtimeMinutes > 0 || item.lastPlayed);
  }

  if (query.playState === "unplayed") {
    next = next.filter((item) => item.playtimeMinutes === 0 && !item.lastPlayed);
  }

  if (query.coOpOnly) {
    next = next.filter((item) => item.coOp);
  }

  if (query.achievementsOnly) {
    next = next.filter((item) => item.achievementsSupported);
  }

  return sortLibraryItems(next, query.sortBy, query.genre);
};

export const sortLibraryItems = (items, sortBy, genre) => {
  const sorted = [...items];
  const resolvedSort =
    genre === "Latest Installed" ? "recentlyInstalled" : genre === "Recently Played" ? "recentlyPlayed" : sortBy;

  if (resolvedSort === "recentlyPlayed") {
    return sorted.sort(byDateDesc("lastPlayed"));
  }

  if (resolvedSort === "recentlyInstalled") {
    return sorted.sort(byDateDesc("installedAt"));
  }

  if (resolvedSort === "playtime") {
    return sorted.sort((left, right) => right.playtimeMinutes - left.playtimeMinutes);
  }

  if (resolvedSort === "platform") {
    return sorted.sort(
      (left, right) => left.source.localeCompare(right.source) || left.title.localeCompare(right.title),
    );
  }

  return sorted.sort((left, right) => left.title.localeCompare(right.title));
};
