import { Unassigned } from "@bitwarden/common/admin-console/models/collections";
import { CipherType } from "@bitwarden/common/vault/enums";
import {
  CipherViewLike,
  CipherViewLikeUtils,
} from "@bitwarden/common/vault/utils/cipher-view-like-utils";

import { All, RoutedVaultFilterModel } from "./routed-vault-filter.model";

export type FilterFunction = (cipher: CipherViewLike) => boolean;

export function createFilterFunction(filter: RoutedVaultFilterModel): FilterFunction {
  return (cipher) => {
    const type = CipherViewLikeUtils.getType(cipher);
    const isDeleted = CipherViewLikeUtils.isDeleted(cipher);

    if (filter.type === "favorites" && !cipher.favorite) {
      return false;
    }
    if (filter.type === "card" && type !== CipherType.Card) {
      return false;
    }
    if (filter.type === "driversLicense" && type !== CipherType.DriversLicense) {
      return false;
    }
    if (filter.type === "identity" && type !== CipherType.Identity) {
      return false;
    }
    if (filter.type === "login" && type !== CipherType.Login) {
      return false;
    }
    if (filter.type === "note" && type !== CipherType.SecureNote) {
      return false;
    }
    if (filter.type === "sshKey" && type !== CipherType.SshKey) {
      return false;
    }
    if (filter.type === "bankAccount" && type !== CipherType.BankAccount) {
      return false;
    }
    if (filter.type === "passport" && type !== CipherType.Passport) {
      return false;
    }
    if (filter.type === "trash" && !isDeleted) {
      return false;
    }
    // Hide trash unless explicitly selected
    if (filter.type !== "trash" && isDeleted) {
      return false;
    }
    if (filter.type === "archive" && !CipherViewLikeUtils.isArchived(cipher)) {
      return false;
    }
    if (
      filter.type !== "archive" &&
      filter.type !== "trash" &&
      CipherViewLikeUtils.isArchived(cipher)
    ) {
      return false;
    }
    const isNoFolderFilter = filter.folderId === Unassigned || filter.folderId === "";
    const cipherHasFolder = cipher.folderId != null && cipher.folderId !== "";

    // No folder
    if (isNoFolderFilter && cipherHasFolder) {
      return false;
    }
    // Folder
    if (
      filter.folderId !== undefined &&
      filter.folderId !== All &&
      filter.folderId !== Unassigned &&
      filter.folderId !== "" &&
      cipher.folderId !== filter.folderId
    ) {
      return false;
    }
    // All collections (top level)
    if (filter.collectionId === All) {
      return false;
    }
    // Unassigned
    if (
      filter.collectionId === Unassigned &&
      (cipher.organizationId == null ||
        (cipher.collectionIds != null && cipher.collectionIds.length > 0))
    ) {
      return false;
    }
    // Collection
    if (
      filter.collectionId !== undefined &&
      filter.collectionId !== All &&
      filter.collectionId !== Unassigned &&
      (cipher.collectionIds == null || !cipher.collectionIds.includes(filter.collectionId as any))
    ) {
      return false;
    }
    // My Vault
    if (filter.organizationId === Unassigned && cipher.organizationId != null) {
      return false;
    }
    // Organization
    else if (
      filter.organizationId !== undefined &&
      filter.organizationId !== Unassigned &&
      cipher.organizationId !== filter.organizationId
    ) {
      return false;
    }

    return true;
  };
}
