/**
 * Swift shadowing precedence for the `mergeBindings` hook.
 *
 * Tier ranking (lower wins in shadowing):
 *
 *   - 0: `local` — a type member, method, local var, or parameter
 *        declared in this scope.
 *   - 1: `import` / `namespace` / `reexport` — names brought in by an
 *        `import ModuleName` (whole-module, including `@testable`).
 *   - 2: `wildcard` — reserved; Swift's whole-module import already
 *        behaves like a namespace tier, so this is rarely populated.
 *
 * Swift resolves an ambiguity between two imported modules by requiring
 * an explicit `Module.Symbol` qualifier; for receiver-typed dispatch we
 * treat all imports as one tier. Locals always shadow imports.
 *
 * Within a surviving tier we de-dup by `DefId`, last-write-wins.
 */

import type { BindingRef } from 'gitnexus-shared';

const TIER_LOCAL = 0;
const TIER_IMPORT = 1;
const TIER_WILDCARD = 2;
const TIER_UNKNOWN = 3;

function tierOf(b: BindingRef): number {
  switch (b.origin) {
    case 'local':
      return TIER_LOCAL;
    case 'reexport':
    case 'import':
    case 'namespace':
      return TIER_IMPORT;
    case 'wildcard':
      return TIER_WILDCARD;
    default:
      return TIER_UNKNOWN;
  }
}

export function swiftMergeBindings(bindings: readonly BindingRef[]): readonly BindingRef[] {
  if (bindings.length === 0) return bindings;

  let bestTier = Number.POSITIVE_INFINITY;
  for (const b of bindings) bestTier = Math.min(bestTier, tierOf(b));
  const survivors = bindings.filter((b) => tierOf(b) === bestTier);

  const seen = new Map<string, BindingRef>();
  for (const b of survivors) seen.set(b.def.nodeId, b);
  return [...seen.values()];
}
