/**
 * _source tag for federation fan-out results.
 *
 * Source of truth: docs/federation/PRD.md §9.3 and MILESTONES.md §M3 acceptance test #8.
 *
 * When source: "all" is requested, the gateway fans out to local + all active
 * federated peers, merges results, and tags each item with _source so the
 * caller knows the provenance.
 *
 * Pure — no NestJS, no DB, no Node-only APIs. Safe for browser/edge.
 */

import { z } from 'zod';

// ---------------------------------------------------------------------------
// Source tag schema
// ---------------------------------------------------------------------------

/**
 * `_source` is either:
 * - `"local"` — the item came from this gateway's own storage.
 * - a peer common name (e.g. `"mosaic.uscllc.com"`) — the item came from
 *   that federated peer.
 */
export const SourceTagSchema = z.object({
  _source: z.string().min(1, { message: '_source must not be empty' }),
});

export type SourceTag = z.infer<typeof SourceTagSchema>;

/**
 * Literal union for the well-known local source value.
 * Peers are identified by hostname strings, so there is no closed enum.
 */
export const SOURCE_LOCAL = 'local' as const;

// ---------------------------------------------------------------------------
// Helper: tagWithSource
// ---------------------------------------------------------------------------

/**
 * Stamps each item in `items` with `{ _source: source }`.
 *
 * The return type merges the item type with SourceTag so callers get full
 * type-safety on both the original fields and `_source`.
 *
 * @param items  - Array of items to tag.
 * @param source - Either `"local"` or a peer hostname (common name from the
 *                 client cert's CN or O field).
 *
 * @example
 * ```ts
 * const local = tagWithSource([{ id: '1', title: 'Task' }], 'local');
 * // => [{ id: '1', title: 'Task', _source: 'local' }]
 *
 * const remote = tagWithSource(peerItems, 'mosaic.uscllc.com');
 * ```
 */
export function tagWithSource<T extends object>(items: T[], source: string): Array<T & SourceTag> {
  return items.map((item) => ({ ...item, _source: source }));
}
