import { isLeadMember } from '@shared/utils/leadDetection';
import { getStableTeamOwnerId } from '@shared/utils/teamStableOwnerId';

import type { GraphOwnerSlotAssignment } from '@claude-teams/agent-graph';

export interface TeamGraphDefaultLayoutMemberInput {
  name: string;
  agentId?: string | null;
  removedAt?: number | null;
}

export interface TeamGraphDefaultLayoutSeed {
  orderedVisibleOwnerIds: string[];
  signature: string | null;
  assignments: Record<string, GraphOwnerSlotAssignment>;
}

const SMALL_TEAM_CARDINAL_SLOT_PRESETS: readonly (readonly GraphOwnerSlotAssignment[])[] = [
  [],
  [{ ringIndex: 0, sectorIndex: 0 }],
  [
    { ringIndex: 0, sectorIndex: 0 },
    { ringIndex: 0, sectorIndex: 1 },
  ],
  [
    { ringIndex: 0, sectorIndex: 0 },
    { ringIndex: 0, sectorIndex: 1 },
    { ringIndex: 0, sectorIndex: 2 },
  ],
  [
    { ringIndex: 0, sectorIndex: 0 },
    { ringIndex: 0, sectorIndex: 1 },
    { ringIndex: 0, sectorIndex: 2 },
    { ringIndex: 0, sectorIndex: 3 },
  ],
];

export function buildOrderedVisibleTeamGraphOwnerIds(
  members: readonly TeamGraphDefaultLayoutMemberInput[],
  configMembers: readonly TeamGraphDefaultLayoutMemberInput[] = []
): string[] {
  const visibleMembers = members.filter((member) => !member.removedAt && !isLeadMember(member));
  if (visibleMembers.length === 0) {
    return [];
  }

  const visibleMemberByStableOwnerId = new Map(
    visibleMembers.map((member) => [getStableTeamOwnerId(member), member] as const)
  );
  const orderedVisibleOwnerIds: string[] = [];
  const seenVisibleOwnerIds = new Set<string>();

  for (const configMember of configMembers) {
    if (configMember.removedAt || isLeadMember(configMember)) {
      continue;
    }
    const stableOwnerId = getStableTeamOwnerId(configMember);
    if (
      !visibleMemberByStableOwnerId.has(stableOwnerId) ||
      seenVisibleOwnerIds.has(stableOwnerId)
    ) {
      continue;
    }
    orderedVisibleOwnerIds.push(stableOwnerId);
    seenVisibleOwnerIds.add(stableOwnerId);
  }

  const remainingVisibleOwnerIds = visibleMembers
    .map((member) => getStableTeamOwnerId(member))
    .filter((stableOwnerId) => !seenVisibleOwnerIds.has(stableOwnerId))
    .toSorted((left, right) => left.localeCompare(right));

  orderedVisibleOwnerIds.push(...remainingVisibleOwnerIds);
  return orderedVisibleOwnerIds;
}

export function buildTeamGraphDefaultLayoutSeed(
  members: readonly TeamGraphDefaultLayoutMemberInput[],
  configMembers: readonly TeamGraphDefaultLayoutMemberInput[] = []
): TeamGraphDefaultLayoutSeed {
  const orderedVisibleOwnerIds = buildOrderedVisibleTeamGraphOwnerIds(members, configMembers);
  const signature = orderedVisibleOwnerIds.length > 0 ? orderedVisibleOwnerIds.join('|') : null;
  const preset = SMALL_TEAM_CARDINAL_SLOT_PRESETS[orderedVisibleOwnerIds.length];
  const assignments: Record<string, GraphOwnerSlotAssignment> = {};

  if (preset?.length === orderedVisibleOwnerIds.length) {
    orderedVisibleOwnerIds.forEach((stableOwnerId, index) => {
      assignments[stableOwnerId] = preset[index]!;
    });
  }

  return {
    orderedVisibleOwnerIds,
    signature,
    assignments,
  };
}
