/**
 * Flow publish helpers — pure functions used by the marketplace publish
 * flow (PublishItemModal) and the marketplace install flow (MarketplacePage)
 * to package and unpack flow definitions cleanly.
 *
 * Lives under `src/utilities/` (server-side path, plain ESM) so the
 * server-side unit jest project can run tests for it. The web-ui
 * imports it via a relative path — vite handles arbitrary paths.
 */

/**
 * Compute a small metadata summary from a flow definition. Used by the
 * marketplace `metadata` field — keeps the publish payload light while
 * giving the marketplace card enough to render search results.
 *
 * @param {Object} flow - Flow definition (saved canvas + edges)
 * @returns {Object} Metadata: schemaVersion, nodeCount, agentNodeCount,
 *   edgeCount, models[], hasPauseNode, hasTriggerNode, goal.
 */
export function computeFlowPublishMetadata(flow) {
  const nodes = Array.isArray(flow?.nodes) ? flow.nodes : [];
  const edges = Array.isArray(flow?.edges) ? flow.edges : [];
  const agentNodes = nodes.filter(n => n.type === 'agent');
  // Distinct models referenced by the flow's agent nodes (best-effort —
  // template flows ship with empty agentIds so models live on data.model
  // when the user wired them; we collect whatever's there for searchability).
  const models = Array.from(new Set(
    agentNodes.map(n => n.data?.model || n.data?.preferredModel).filter(Boolean)
  ));
  // Specialty node types the marketplace card might want to call out.
  const hasPauseNode   = nodes.some(n => n.type === 'pause' || n.type === 'human-input');
  const hasTriggerNode = nodes.some(n => n.type === 'trigger' || !!n.data?.cron);
  return {
    schemaVersion:  flow?.schemaVersion ?? 1,
    nodeCount:      nodes.length,
    agentNodeCount: agentNodes.length,
    edgeCount:      edges.length,
    models,
    hasPauseNode,
    hasTriggerNode,
    // Flow goal preserved verbatim — useful for marketplace listing copy.
    goal: typeof flow?.description === 'string' ? flow.description.slice(0, 280) : '',
  };
}

/**
 * Strip per-installation identifiers from a flow before publishing. Local
 * agentIds aren't portable — they're per-installation. The user re-wires
 * after install. Same convention the in-app starter templates already
 * use (they ship with `agentId: ''`).
 *
 * Pure function — does not mutate the input.
 *
 * @param {Object} flow - Flow definition
 * @returns {Object} Sanitized clone safe to publish.
 */
export function sanitizeFlowForPublish(flow) {
  if (!flow || typeof flow !== 'object') return flow;
  const cleanNodes = (flow.nodes || []).map(n => {
    if (n.type !== 'agent') return n;
    return {
      ...n,
      data: {
        ...(n.data || {}),
        // Wipe local identity — the importer wires their own agent.
        agentId: '',
        // Keep the human label and instructions; they're the value.
      },
    };
  });
  return { ...flow, nodes: cleanNodes };
}
