import { IntegrationId } from "@bitwarden/common/tools/integration";

import { EmailAlgorithms, PasswordAlgorithms, UsernameAlgorithms } from "../data/generator-types";

/** A type of password that may be generated by the credential generator. */
export type PasswordAlgorithm = (typeof PasswordAlgorithms)[number];

/** A type of username that may be generated by the credential generator. */
export type UsernameAlgorithm = (typeof UsernameAlgorithms)[number];

/** A type of email address that may be generated by the credential generator. */
export type EmailAlgorithm = (typeof EmailAlgorithms)[number];

export type ForwarderIntegration = { forwarder: IntegrationId };

/** Returns true when the input algorithm is a forwarder integration. */
export function isForwarderIntegration(
  algorithm: CredentialAlgorithm,
): algorithm is ForwarderIntegration {
  return algorithm && typeof algorithm === "object" && "forwarder" in algorithm;
}

export function isSameAlgorithm(lhs: CredentialAlgorithm, rhs: CredentialAlgorithm) {
  if (lhs === rhs) {
    return true;
  } else if (isForwarderIntegration(lhs) && isForwarderIntegration(rhs)) {
    return lhs.forwarder === rhs.forwarder;
  } else {
    return false;
  }
}

/** A type of credential that may be generated by the credential generator. */
export type CredentialAlgorithm =
  | PasswordAlgorithm
  | UsernameAlgorithm
  | EmailAlgorithm
  | ForwarderIntegration;

/** Compound credential types supported by the credential generator. */
export const CredentialCategories = Object.freeze({
  /** Lists algorithms in the "password" credential category */
  password: PasswordAlgorithms as Readonly<PasswordAlgorithm[]>,

  /** Lists algorithms in the "username" credential category */
  username: UsernameAlgorithms as Readonly<UsernameAlgorithm[]>,

  /** Lists algorithms in the "email" credential category */
  email: EmailAlgorithms as Readonly<(EmailAlgorithm | ForwarderIntegration)[]>,
});

/** Returns true when the input algorithm is a password algorithm. */
export function isPasswordAlgorithm(
  algorithm: CredentialAlgorithm,
): algorithm is PasswordAlgorithm {
  return PasswordAlgorithms.includes(algorithm as any);
}

/** Returns true when the input algorithm is a username algorithm. */
export function isUsernameAlgorithm(
  algorithm: CredentialAlgorithm,
): algorithm is UsernameAlgorithm {
  return UsernameAlgorithms.includes(algorithm as any);
}

/** Returns true when the input algorithm is an email algorithm. */
export function isEmailAlgorithm(algorithm: CredentialAlgorithm): algorithm is EmailAlgorithm {
  return EmailAlgorithms.includes(algorithm as any) || isForwarderIntegration(algorithm);
}

/** A type of compound credential that may be generated by the credential generator. */
export type CredentialCategory = keyof typeof CredentialCategories;

/** The kind of credential to generate using a compound configuration. */
// FIXME: extend the preferences to include a preferred forwarder
export type CredentialPreference = {
  [Key in CredentialCategory]: {
    algorithm: (typeof CredentialCategories)[Key][number];
    updated: Date;
  };
};
