import { useMemo } from 'react'; import { canParticipateInResourceMatching } from '@/schemas/organizationSubtype.ts'; import type { Organization } from '@/types.ts'; import { useDirectSymbiosis as useDirectSymbiosisAPI } from '@/hooks/api/useDirectSymbiosisAPI.ts'; import { useOrganizations } from '@/hooks/useOrganizations.ts'; interface Match { partner: Organization; resource: string; } /** * Get direct symbiosis matches for an organization * Uses backend API to get matches based on ResourceFlows * Only commercial organizations participate in resource matching */ export const useDirectSymbiosis = ( organization: Organization | null ): { providers: Match[]; consumers: Match[]; isLoading: boolean; error: Error | null } => { const { organizations: allOrganizations } = useOrganizations(); // Only fetch matches if organization is commercial const canMatch = organization ? canParticipateInResourceMatching(organization.Subtype) : false; const { data, isLoading, error } = useDirectSymbiosisAPI(canMatch ? organization?.ID : undefined); // Memoize organization map for O(1) lookup instead of O(n) find const orgMap = useMemo(() => { if (!allOrganizations || !Array.isArray(allOrganizations)) return new Map(); return new Map(allOrganizations.map((org) => [org.ID, org])); }, [allOrganizations]); // Map backend response to frontend format // Filter to only include commercial organizations // Memoize to prevent recalculation on every render const providers: Match[] = useMemo(() => { if (!data?.providers || !Array.isArray(data.providers)) return []; return data.providers .map((match) => { const partner = orgMap.get(match.partner_id); if (!partner || !canParticipateInResourceMatching(partner.Subtype)) { return null; } return { partner, resource: match.resource, }; }) .filter((match): match is Match => match !== null); }, [data, orgMap]); const consumers: Match[] = useMemo(() => { if (!data?.consumers || !Array.isArray(data.consumers)) return []; return data.consumers .map((match) => { const partner = orgMap.get(match.partner_id); if (!partner || !canParticipateInResourceMatching(partner.Subtype)) { return null; } return { partner, resource: match.resource, }; }) .filter((match): match is Match => match !== null); }, [data, orgMap]); return { providers, consumers, isLoading, error: error instanceof Error ? error : null, }; };