/**
 * Subscription Router — SSE event streams
 */

import { z } from 'zod';
import type { ProcedureBuilder } from '../trpc.js';
import {
  eventBusIterable,
  ALL_EVENT_TYPES,
  AGENT_EVENT_TYPES,
  TASK_EVENT_TYPES,
  PAGE_EVENT_TYPES,
  PREVIEW_EVENT_TYPES,
  CONVERSATION_EVENT_TYPES,
} from '../subscriptions.js';

export function subscriptionProcedures(publicProcedure: ProcedureBuilder) {
  return {
    onEvent: publicProcedure
      .input(z.object({ lastEventId: z.string().nullish() }).optional())
      .subscription(async function* (opts) {
        const signal = opts.signal ?? new AbortController().signal;
        yield* eventBusIterable(opts.ctx.eventBus, ALL_EVENT_TYPES, signal);
      }),

    onAgentUpdate: publicProcedure
      .input(z.object({ lastEventId: z.string().nullish() }).optional())
      .subscription(async function* (opts) {
        const signal = opts.signal ?? new AbortController().signal;
        yield* eventBusIterable(opts.ctx.eventBus, AGENT_EVENT_TYPES, signal);
      }),

    onTaskUpdate: publicProcedure
      .input(z.object({ lastEventId: z.string().nullish() }).optional())
      .subscription(async function* (opts) {
        const signal = opts.signal ?? new AbortController().signal;
        yield* eventBusIterable(opts.ctx.eventBus, TASK_EVENT_TYPES, signal);
      }),

    onPageUpdate: publicProcedure
      .input(z.object({ lastEventId: z.string().nullish() }).optional())
      .subscription(async function* (opts) {
        const signal = opts.signal ?? new AbortController().signal;
        yield* eventBusIterable(opts.ctx.eventBus, PAGE_EVENT_TYPES, signal);
      }),

    onPreviewUpdate: publicProcedure
      .input(z.object({ lastEventId: z.string().nullish() }).optional())
      .subscription(async function* (opts) {
        const signal = opts.signal ?? new AbortController().signal;
        yield* eventBusIterable(opts.ctx.eventBus, PREVIEW_EVENT_TYPES, signal);
      }),

    onConversationUpdate: publicProcedure
      .input(z.object({ lastEventId: z.string().nullish() }).optional())
      .subscription(async function* (opts) {
        const signal = opts.signal ?? new AbortController().signal;
        yield* eventBusIterable(opts.ctx.eventBus, CONVERSATION_EVENT_TYPES, signal);
      }),
  };
}
