import { didFromUri, rkeyFromUri } from "#lib/api/uri.ts";
import type { NetworkVouchItem, VouchKind } from "#lib/api/graph.ts";
import type { DirectVouch } from "#lib/components/profile/types.ts";
export interface VouchRelationship {
viewer: string;
actor: string;
vouches: readonly NetworkVouchItem[];
}
export type VouchBadgeState =
"direct-vouch" | "direct-denounce" | "mixed" | "indirect-vouch" | "indirect-denounce";
const incoming = ({ actor, vouches }: VouchRelationship) =>
vouches.filter((vouch) => rkeyFromUri(vouch.uri) === actor);
const hasKind = (vouches: readonly NetworkVouchItem[], kind: VouchKind) =>
vouches.some((vouch) => vouch.value.kind === kind);
export const isDirectVouch = (relationship: VouchRelationship): boolean =>
incoming(relationship).some(
(vouch) => didFromUri(vouch.uri) === relationship.viewer && vouch.value.kind === "vouch"
);
export const isDirectDenounce = (relationship: VouchRelationship): boolean =>
incoming(relationship).some(
(vouch) => didFromUri(vouch.uri) === relationship.viewer && vouch.value.kind === "denounce"
);
export const indirectVouches = (relationship: VouchRelationship): NetworkVouchItem[] =>
incoming(relationship).filter((vouch) => didFromUri(vouch.uri) !== relationship.viewer);
export const isMixed = (relationship: VouchRelationship): boolean => {
if (isDirectVouch(relationship) || isDirectDenounce(relationship)) return false;
const vouches = indirectVouches(relationship);
return hasKind(vouches, "vouch") && hasKind(vouches, "denounce");
};
export const isIndirectVouch = (relationship: VouchRelationship): boolean =>
!isDirectVouch(relationship) &&
!isDirectDenounce(relationship) &&
hasKind(indirectVouches(relationship), "vouch");
export const isIndirectDenounce = (relationship: VouchRelationship): boolean =>
!isDirectVouch(relationship) &&
!isDirectDenounce(relationship) &&
hasKind(indirectVouches(relationship), "denounce");
export const vouchStrength = (relationship: VouchRelationship): number =>
indirectVouches(relationship).filter((vouch) => vouch.value.kind === "vouch").length;
export const denounceStrength = (relationship: VouchRelationship): number =>
indirectVouches(relationship).filter((vouch) => vouch.value.kind === "denounce").length;
export const directVouch = (relationship: VouchRelationship): DirectVouch | null => {
const own = incoming(relationship).find(
(vouch) => didFromUri(vouch.uri) === relationship.viewer
);
return own
? { kind: own.value.kind === "denounce" ? "denounce" : "vouch", reason: own.value.reason }
: null;
};
export const vouchBadgeState = (relationship: VouchRelationship): VouchBadgeState | null => {
if (isDirectVouch(relationship)) return "direct-vouch";
if (isDirectDenounce(relationship)) return "direct-denounce";
if (isMixed(relationship)) return "mixed";
if (isIndirectVouch(relationship)) return "indirect-vouch";
if (isIndirectDenounce(relationship)) return "indirect-denounce";
return null;
};