/**
 * saas-admin blueprint · wiring seam for `@platform-modules/jobs`.
 *
 * Adapter-minimalism (CLAUDE.md §4): build a registry with one async-cleanup handler + an in-memory
 * idempotency store. A real host backs idempotency with KV/a table and dispatches from a Queue
 * consumer; the blueprint proves the seam — register a typed handler, dispatch validates the payload
 * and runs it at-most-once per idempotency key. The cleanup env records what ran so the composition
 * test can assert the handler actually fired (not merely that dispatch returned).
 */
import { createJobRegistry, type IdempotencyStore, type JobRegistry } from '@platform-modules/jobs'

/** Env threaded into job handlers — here a sink the test asserts against. */
export type CleanupEnv = { cleaned: string[] }

export type CleanupPayload = { tenantId: string; userId: string }

export const CLEANUP_JOB = 'member.suspend.cleanup'

/**
 * Minimal Standard Schema (pass-through). Structurally satisfies StandardSchemaV1<unknown, T>, so no
 * `@standard-schema/spec` import is needed — a real host passes a zod/valibot schema here instead.
 */
function passthroughSchema<T>() {
  return {
    '~standard': {
      version: 1 as const,
      vendor: 'saas-admin-blueprint',
      validate: (value: unknown) => ({ value: value as T }),
    },
  }
}

export function createCleanupJobs(): JobRegistry<CleanupEnv> {
  const registry = createJobRegistry<CleanupEnv>()
  registry.register(CLEANUP_JOB, passthroughSchema<CleanupPayload>(), async (env, payload) => {
    env.cleaned.push(payload.userId)
  })
  return registry
}

export function createMemoryIdempotencyStore(): IdempotencyStore {
  const marks = new Set<string>()
  return {
    async seen(key) {
      return marks.has(key)
    },
    async mark(key) {
      marks.add(key)
    },
  }
}
