import test from 'node:test'
import assert from 'node:assert/strict'

import {
  CloudTransportError,
  createHttpSseCloudTransportAdapter,
  isCloudTransportError,
  type CloudTransportEventSource,
  type CloudTransportFetch,
} from '../apps/desktop/src/main/cloud/transport-adapter.ts'
import { CLOUD_SESSION_EVENT_TYPES } from '../packages/shared/dist/cloud-session-projection.js'

function jsonResponse(body: unknown, status = 200, headers: Record<string, string> = {}) {
  return {
    ok: status >= 200 && status < 300,
    status,
    headers: {
      get(name: string) {
        return headers[name] || headers[name.toLowerCase()] || null
      },
    },
    async text() {
      return JSON.stringify(body)
    },
  }
}

function textResponse(text: string, status = 200, headers: Record<string, string> = {}) {
  return {
    ok: status >= 200 && status < 300,
    status,
    headers: {
      get(name: string) {
        return headers[name] || headers[name.toLowerCase()] || null
      },
    },
    async text() {
      return text
    },
  }
}

function projectionFence(commandId: string, sessionId = 'session-1') {
  return {
    version: 1,
    scope: 'session',
    tenantId: 'tenant-1',
    sessionId,
    commandId,
    issuedAt: '2026-05-27T10:00:00.000Z',
  }
}

test('cloud transport adapter maps session and channel commands to HTTP routes with CSRF', async () => {
  const requests: Array<{ url: string, init?: Parameters<CloudTransportFetch>[1] }> = []
  const fetcher: CloudTransportFetch = async (url, init) => {
    requests.push({ url, init })
    if (url.endsWith('/api/config')) {
      return jsonResponse({
        role: 'web',
        profileName: 'full',
        features: { chat: true },
        allowedAgents: null,
        allowedTools: null,
        allowedMcps: null,
      })
    }
    if (url.endsWith('/api/sessions')) {
      if (init?.method === 'POST') {
        return jsonResponse({ session: { sessionId: 'session-1' }, projection: null }, 201)
      }
      return jsonResponse({ sessions: [{ sessionId: 'session-1' }] })
    }
    if (url.includes('/api/sessions?')) {
      return jsonResponse({
        sessions: [{ sessionId: 'session-2' }],
        nextCursor: 'cursor-2',
        totalEstimate: 2,
      })
    }
    if (url.endsWith('/api/import/sessions')) {
      return jsonResponse({
        session: { sessionId: 'session-imported' },
        projection: {
          messages: [{ id: 'm1', role: 'user', content: 'imported', createdAt: '2026-05-27T10:00:00.000Z' }],
          origin: {
            kind: 'local-session-import',
            sourceFingerprint: 'sha256:import',
            importedAt: '2026-05-27T10:00:00.000Z',
            itemCounts: { messages: 1, artifacts: 0, attachments: 0, projectSource: 0, excluded: 1 },
          },
        },
      }, 201)
    }
    if (url.endsWith('/api/sessions/session-1/prompt')) {
      return jsonResponse({
        command: { commandId: 'cmd-1' },
        processed: 0,
        view: { session: {}, projection: null },
        projectionFence: projectionFence('cmd-1'),
      }, 202)
    }
    if (url.endsWith('/api/sessions/session-1/question-reply')) {
      return jsonResponse({
        command: { commandId: 'cmd-2' },
        processed: 0,
        projectionFence: projectionFence('cmd-2'),
      }, 202)
    }
    if (url.endsWith('/api/sessions/session-1/question-reject')) {
      return jsonResponse({
        command: { commandId: 'cmd-3' },
        processed: 0,
        projectionFence: projectionFence('cmd-3'),
      }, 202)
    }
    if (url.endsWith('/api/sessions/session-1/permission-respond')) {
      return jsonResponse({
        command: { commandId: 'cmd-4' },
        processed: 0,
        projectionFence: projectionFence('cmd-4'),
      }, 202)
    }
    if (url.endsWith('/api/channels/sessions/prompt')) {
      return jsonResponse({
        binding: { bindingId: 'binding-1' },
        command: { commandId: 'cmd-channel-prompt' },
        processed: 0,
        projectionFence: projectionFence('cmd-channel-prompt'),
      }, 202)
    }
    if (url.endsWith('/api/channels/interactions/resolve')) {
      return jsonResponse({
        interaction: { interactionId: 'interaction-1' },
        command: { commandId: 'cmd-channel-interaction' },
        processed: 0,
        projectionFence: projectionFence('cmd-channel-interaction'),
      }, 202)
    }
    if (url.endsWith('/api/sessions/session-1/artifacts')) {
      if (init?.method === 'POST') {
        return jsonResponse({
          artifact: {
            artifactId: 'artifact-2',
            sessionId: 'session-1',
            filename: 'upload.txt',
            contentType: 'text/plain',
            size: 5,
            createdAt: '2026-05-27T10:02:00.000Z',
            updatedAt: '2026-05-27T10:02:00.000Z',
            kind: 'document',
            status: 'draft',
            projectId: 'project-1',
            taskId: 'task-1',
          },
        }, 201)
      }
      return jsonResponse({
        artifacts: [{
          artifactId: 'artifact-1',
          sessionId: 'session-1',
          filename: 'result.txt',
          contentType: 'text/plain',
          size: 5,
          createdAt: '2026-05-27T10:01:00.000Z',
          updatedAt: '2026-05-27T10:01:00.000Z',
          kind: 'document',
          status: 'draft',
          projectId: 'project-1',
          taskId: 'task-1',
        }],
      })
    }
    if (url.includes('/api/artifacts?')) {
      return jsonResponse({
        artifacts: [{
          artifactId: 'artifact-1',
          sessionId: 'session-1',
          sessionTitle: 'Cloud thread',
          filename: 'result.txt',
          contentType: 'text/plain',
          size: 5,
          createdAt: '2026-05-27T10:01:00.000Z',
          updatedAt: '2026-05-27T10:01:00.000Z',
          kind: 'document',
          status: 'draft',
          projectId: 'project-1',
          taskId: 'task-1',
        }],
        total: 1,
      })
    }
    if (url.endsWith('/api/sessions/session-1/artifacts/artifact-1/status')) {
      return jsonResponse({
        artifact: {
          artifactId: 'artifact-1',
          sessionId: 'session-1',
          filename: 'result.txt',
          contentType: 'text/plain',
          size: 5,
          createdAt: '2026-05-27T10:01:00.000Z',
          updatedAt: '2026-05-27T10:03:00.000Z',
          kind: 'document',
          status: 'in-review',
          projectId: 'project-1',
          taskId: 'task-1',
          statusUpdatedBy: 'reviewer-1',
          statusUpdatedAt: '2026-05-27T10:03:00.000Z',
        },
      })
    }
    if (url.endsWith('/api/sessions/session-1/artifacts/artifact-1')) {
      return jsonResponse({
        artifact: {
          artifactId: 'artifact-1',
          sessionId: 'session-1',
          filename: 'result.txt',
          contentType: 'text/plain',
          size: 5,
          key: 'tenant/session/artifact-1/result.txt',
          createdAt: '2026-05-27T10:01:00.000Z',
          dataBase64: Buffer.from('hello').toString('base64'),
        },
      })
    }
    if (url.endsWith('/api/workflows')) {
      return jsonResponse({ workflows: [{ id: 'workflow-1' }], runs: [] })
    }
    if (url.endsWith('/api/workflows/workflow-1')) {
      return jsonResponse({ workflow: { id: 'workflow-1', status: 'active' } })
    }
    if (url.endsWith('/api/workflows/workflow-1/run')) {
      return jsonResponse({ run: { id: 'run-1', workflowId: 'workflow-1', status: 'running' } }, 202)
    }
    if (url.endsWith('/api/workflows/workflow-1/pause')) {
      return jsonResponse({ workflow: { id: 'workflow-1', status: 'paused' } })
    }
    if (url.includes('/api/threads?')) {
      return jsonResponse({
        threads: [{
          sessionId: 'session-1',
          title: 'Cloud thread',
          profileName: 'default',
          status: 'running',
          createdAt: '2026-05-27T10:00:00.000Z',
          updatedAt: '2026-05-27T10:01:00.000Z',
          tags: [{
            tagId: 'tag-1',
            name: 'Important',
            color: '#123456',
            createdAt: '2026-05-27T10:00:00.000Z',
            updatedAt: '2026-05-27T10:00:00.000Z',
          }],
        }],
      })
    }
    if (url.endsWith('/api/threads/tags')) {
      if (init?.method === 'POST') {
        return jsonResponse({ tag: { tagId: 'tag-2', name: 'New', color: '#abcdef' } }, 201)
      }
      return jsonResponse({ tags: [{ tagId: 'tag-1', name: 'Important', color: '#123456' }] })
    }
    if (url.endsWith('/api/threads/tags/tag-1')) {
      if (init?.method === 'DELETE') return jsonResponse({ deleted: true })
      return jsonResponse({ tag: { tagId: 'tag-1', name: 'Renamed', color: '#654321' } })
    }
    if (url.endsWith('/api/threads/tags/tag-1/apply') || url.endsWith('/api/threads/tags/tag-1/remove')) {
      return jsonResponse({ ok: true })
    }
    if (url.endsWith('/api/threads/smart-filters')) {
      if (init?.method === 'POST') {
        return jsonResponse({ filter: { filterId: 'filter-2', name: 'New filter', query: {}, createdAt: '2026-05-27T10:00:00.000Z', updatedAt: '2026-05-27T10:00:00.000Z' } }, 201)
      }
      return jsonResponse({ filters: [{ filterId: 'filter-1', name: 'Mine', query: {}, createdAt: '2026-05-27T10:00:00.000Z', updatedAt: '2026-05-27T10:00:00.000Z' }] })
    }
    if (url.endsWith('/api/threads/smart-filters/filter-1')) {
      if (init?.method === 'DELETE') return jsonResponse({ deleted: true })
      return jsonResponse({ filter: { filterId: 'filter-1', name: 'Updated', query: {}, createdAt: '2026-05-27T10:00:00.000Z', updatedAt: '2026-05-27T10:00:00.000Z' } })
    }
    if (url.endsWith('/api/runtime/status')) {
      return jsonResponse({
        role: 'web',
        profileName: 'full',
        canExecute: false,
        commandProcessing: 'delegated',
        checkpoints: false,
        heartbeats: [],
      })
    }
    if (url.endsWith('/api/capabilities/tools')) {
      return jsonResponse({
        tools: [{
          id: 'read',
          name: 'Read',
          description: 'Read files',
          kind: 'built-in',
          source: 'builtin',
          patterns: ['read'],
          agentNames: ['build'],
        }],
      })
    }
    if (url.endsWith('/api/capabilities/tools/read')) {
      return jsonResponse({
        tool: {
          id: 'read',
          name: 'Read',
          description: 'Read files',
          kind: 'built-in',
          source: 'builtin',
          patterns: ['read'],
          agentNames: ['build'],
        },
      })
    }
    if (url.endsWith('/api/capabilities/skills')) {
      return jsonResponse({
        skills: [{
          name: 'analysis',
          label: 'Analysis',
          description: 'Analyze data',
          source: 'builtin',
          toolIds: ['read'],
          agentNames: ['data-analyst'],
        }],
      })
    }
    if (url.endsWith('/api/capabilities/skills/analysis/bundle')) {
      return jsonResponse({
        bundle: {
          name: 'analysis',
          source: 'builtin',
          content: '# Analysis',
          files: [{ path: 'examples/report.md', content: 'report example' }],
        },
      })
    }
    if (url.endsWith('/api/settings')) {
      return jsonResponse({
        settings: [{
          key: 'portable-settings',
          value: { selectedProviderId: 'anthropic' },
          updatedAt: '2026-05-27T10:00:00.000Z',
        }],
      })
    }
    if (url.endsWith('/api/settings/portable-settings')) {
      if (init?.method === 'PUT') {
        return jsonResponse({
          setting: {
            key: 'portable-settings',
            value: JSON.parse(init.body || '{}').value,
            updatedAt: '2026-05-27T10:01:00.000Z',
          },
        })
      }
      return jsonResponse({
        setting: {
          key: 'portable-settings',
          value: { selectedProviderId: 'anthropic' },
          updatedAt: '2026-05-27T10:00:00.000Z',
        },
      })
    }
    return jsonResponse({ error: 'not found' }, 404)
  }
  const transport = createHttpSseCloudTransportAdapter({
    baseUrl: 'https://cloud.example.test/',
    fetch: fetcher,
    csrfToken: 'csrf-token',
    credentials: 'include',
  })

  assert.equal((await transport.getConfig()).profileName, 'full')
  assert.equal((await transport.getRuntimeStatus()).commandProcessing, 'delegated')
  assert.deepEqual((await transport.listSessions()).map((session) => session.sessionId), ['session-1'])
  assert.deepEqual(await transport.listSessionsPage?.({
    limit: 25,
    cursor: 'cursor-1',
    status: 'running',
    profileName: 'full',
    query: 'revenue',
  }), {
    sessions: [{ sessionId: 'session-2' }],
    nextCursor: 'cursor-2',
    totalEstimate: 2,
  })
  assert.equal((await transport.createSession()).session.sessionId, 'session-1')
  assert.equal((await transport.importSession({
    source: { kind: 'local-session', fingerprint: 'sha256:import', title: 'Imported' },
    title: 'Imported',
    selection: { includeMessages: true },
    itemCounts: { messages: 1, artifacts: 0, attachments: 0, projectSource: 0, excluded: 1 },
    messages: [{ id: 'm1', role: 'user', content: 'imported', order: 1 }],
  })).session.sessionId, 'session-imported')
  const prompt = await transport.promptSession('session-1', { text: 'hello' })
  assert.equal(prompt.processed, 0)
  assert.equal(prompt.projectionFence?.commandId, 'cmd-1')
  const questionReply = await transport.replyToQuestion('session-1', { requestId: 'q1', answers: ['A'] })
  assert.equal(questionReply.processed, 0)
  assert.equal(questionReply.projectionFence?.commandId, 'cmd-2')
  const questionReject = await transport.rejectQuestion('session-1', { requestId: 'q2' })
  assert.equal(questionReject.processed, 0)
  assert.equal(questionReject.projectionFence?.commandId, 'cmd-3')
  const permissionResponse = await transport.respondToPermission('session-1', { permissionId: 'p1', response: { allowed: true } })
  assert.equal(permissionResponse.processed, 0)
  assert.equal(permissionResponse.projectionFence?.commandId, 'cmd-4')
  const channelPrompt = await transport.promptChannelSession?.({ identityId: 'identity-1', bindingId: 'binding-1', text: 'hello channel' })
  assert.equal(channelPrompt?.processed, 0)
  assert.equal(channelPrompt?.projectionFence?.commandId, 'cmd-channel-prompt')
  const channelInteraction = await transport.resolveChannelInteraction?.({ identityId: 'identity-1', token: 'token-1', response: { allowed: true } })
  assert.equal(channelInteraction?.processed, 0)
  assert.equal(channelInteraction?.projectionFence?.commandId, 'cmd-channel-interaction')
  assert.equal((await transport.listWorkflows?.())?.workflows[0]?.id, 'workflow-1')
  assert.equal((await transport.getWorkflow?.('workflow-1'))?.id, 'workflow-1')
  assert.equal((await transport.runWorkflow?.('workflow-1'))?.id, 'run-1')
  assert.equal((await transport.pauseWorkflow?.('workflow-1'))?.status, 'paused')
  assert.equal((await transport.searchThreads?.({ tagIds: ['tag-1'], limit: 10 }))?.threads[0]?.tags[0]?.id, 'tag-1')
  assert.equal((await transport.threadFacets?.({ tagIds: ['tag-1'] }))?.tags[0]?.value, 'tag-1')
  assert.equal((await transport.listThreadTags?.())?.[0]?.id, 'tag-1')
  assert.equal((await transport.createThreadTag?.({ name: 'New' }))?.id, 'tag-2')
  assert.equal((await transport.updateThreadTag?.('tag-1', { name: 'Renamed', color: '#654321' }))?.name, 'Renamed')
  assert.equal(await transport.applyThreadTags?.(['session-1'], ['tag-1']), true)
  assert.equal(await transport.removeThreadTags?.(['session-1'], ['tag-1']), true)
  assert.equal(await transport.deleteThreadTag?.('tag-1'), true)
  assert.equal((await transport.listThreadSmartFilters?.())?.[0]?.id, 'filter-1')
  assert.equal((await transport.createThreadSmartFilter?.({ name: 'New filter', query: {} }))?.id, 'filter-2')
  assert.equal((await transport.updateThreadSmartFilter?.('filter-1', { name: 'Updated', query: {} }))?.name, 'Updated')
  assert.equal(await transport.deleteThreadSmartFilter?.('filter-1'), true)
  const artifact = (await transport.listArtifacts?.('session-1'))?.[0]
  assert.equal(artifact?.cloudArtifactId, 'artifact-1')
  assert.equal(artifact?.filePath, 'cloud-artifact://artifact-1/result.txt')
  assert.equal(artifact?.status, 'draft')
  assert.equal(artifact?.projectId, 'project-1')
  const artifactIndex = await transport.indexArtifacts?.({ projectId: 'project-1', status: 'draft', kind: 'document', limit: 25 })
  assert.equal(artifactIndex?.artifacts[0]?.sessionId, 'session-1')
  assert.equal(artifactIndex?.artifacts[0]?.sessionTitle, 'Cloud thread')
  assert.equal(artifactIndex?.artifacts[0]?.status, 'draft')
  const reviewedArtifact = await transport.updateArtifactStatus?.({
    sessionId: 'session-1',
    artifactId: 'artifact-1',
    status: 'in-review',
    updatedBy: 'reviewer-1',
  })
  assert.equal(reviewedArtifact?.status, 'in-review')
  assert.equal(reviewedArtifact?.statusUpdatedBy, 'reviewer-1')
  assert.equal((await transport.uploadArtifact?.('session-1', {
    filename: 'upload.txt',
    contentType: 'text/plain',
    dataBase64: Buffer.from('hello').toString('base64'),
    projectId: 'project-1',
    taskId: 'task-1',
  }))?.cloudArtifactId, 'artifact-2')
  const attachment = await transport.readArtifactAttachment?.('session-1', artifact?.filePath || 'artifact-1')
  assert.equal(attachment?.mime, 'text/plain')
  assert.equal(attachment?.filename, 'result.txt')
  assert.equal(attachment?.url, `data:text/plain;base64,${Buffer.from('hello').toString('base64')}`)
  assert.equal((await transport.listCapabilityTools?.())?.[0]?.id, 'read')
  assert.equal((await transport.getCapabilityTool?.('read'))?.name, 'Read')
  assert.equal((await transport.listCapabilitySkills?.())?.[0]?.name, 'analysis')
  assert.equal((await transport.getCapabilitySkillBundle?.('analysis'))?.name, 'analysis')
  assert.equal(await transport.readCapabilitySkillBundleFile?.('analysis', 'examples/report.md'), 'report example')
  assert.equal((await transport.listSettings?.())?.[0]?.key, 'portable-settings')
  assert.equal((await transport.getSetting?.('portable-settings'))?.value.selectedProviderId, 'anthropic')
  assert.equal((await transport.setSetting?.('portable-settings', { selectedProviderId: 'openai' }))?.value.selectedProviderId, 'openai')

  const mutating = requests.filter((request) => request.init?.method === 'POST')
  const putRequests = requests.filter((request) => request.init?.method === 'PUT')
  assert.equal(mutating.every((request) => request.init?.headers?.['x-csrf-token'] === 'csrf-token'), true)
  assert.equal(mutating.every((request) => request.init?.credentials === 'include'), true)
  assert.equal(putRequests.every((request) => request.init?.headers?.['x-csrf-token'] === 'csrf-token'), true)
  assert.deepEqual(
    mutating.map((request) => new URL(request.url).pathname),
    [
      '/api/sessions',
      '/api/import/sessions',
      '/api/sessions/session-1/prompt',
      '/api/sessions/session-1/question-reply',
      '/api/sessions/session-1/question-reject',
      '/api/sessions/session-1/permission-respond',
      '/api/channels/sessions/prompt',
      '/api/channels/interactions/resolve',
      '/api/workflows/workflow-1/run',
      '/api/workflows/workflow-1/pause',
      '/api/threads/tags',
      '/api/threads/tags/tag-1/apply',
      '/api/threads/tags/tag-1/remove',
      '/api/threads/smart-filters',
      '/api/sessions/session-1/artifacts/artifact-1/status',
      '/api/sessions/session-1/artifacts',
    ],
  )
})

test('cloud transport adapter builds Last-Event-ID compatible SSE URLs and subscriptions', () => {
  const instances: Array<{
    url: string
    init?: { withCredentials?: boolean }
    listeners: Map<string, (event: { data: string }) => void>
    onmessage: ((event: { data: string }) => void) | null
    onerror: ((event: unknown) => void) | null
    closed: boolean
  }> = []
  const EventSourceImpl: CloudTransportEventSource = class {
    readonly url: string
    readonly init?: { withCredentials?: boolean }
    readonly listeners = new Map<string, (event: { data: string }) => void>()
    onmessage: ((event: { data: string }) => void) | null = null
    onerror: ((event: unknown) => void) | null = null
    closed = false

    constructor(
      url: string,
      init?: { withCredentials?: boolean },
    ) {
      this.url = url
      this.init = init
      instances.push(this)
    }

    addEventListener(type: string, listener: (event: { data: string }) => void) {
      this.listeners.set(type, listener)
    }

    close() {
      this.closed = true
    }
  }
  const transport = createHttpSseCloudTransportAdapter({
    baseUrl: 'https://cloud.example.test',
    eventSource: EventSourceImpl,
    credentials: 'include',
  })
  const events: unknown[] = []
  const subscription = transport.subscribeSessionEvents('session 1', {
    afterSequence: 42,
    onEvent: (event) => events.push(event),
  })

  assert.equal(
    transport.sessionEventsUrl('session 1', 42),
    'https://cloud.example.test/api/sessions/session%201/events?after=42',
  )
  assert.equal(
    transport.workspaceEventsUrl(42),
    'https://cloud.example.test/api/events?after=42',
  )
  assert.equal(instances[0]?.url, 'https://cloud.example.test/api/sessions/session%201/events?after=42')
  assert.equal(instances[0]?.init?.withCredentials, true)
  assert.deepEqual([...instances[0]!.listeners.keys()].sort(), [...CLOUD_SESSION_EVENT_TYPES].sort())
  instances[0]?.listeners.get('assistant.message')?.({
    data: JSON.stringify({
      sequence: 43,
      eventId: 'event-43',
      type: 'assistant.message',
      payload: { content: 'hello' },
    }),
  })
  assert.deepEqual(events, [{
    sequence: 43,
    eventId: 'event-43',
    type: 'assistant.message',
    payload: { content: 'hello' },
  }])
  subscription.close()
  assert.equal(instances[0]?.closed, true)

  const workspaceEvents: unknown[] = []
  const workspaceSubscription = transport.subscribeWorkspaceEvents({
    afterSequence: 44,
    onEvent: (event) => workspaceEvents.push(event),
  })
  assert.equal(instances[1]?.url, 'https://cloud.example.test/api/events?after=44')
  assert.deepEqual([...instances[1]!.listeners.keys()].sort(), [...CLOUD_SESSION_EVENT_TYPES].sort())
  instances[1]?.listeners.get('session.created')?.({
    data: JSON.stringify({
      sequence: 45,
      eventId: 'event-45',
      sessionId: 'session-2',
      type: 'session.created',
      payload: { title: 'New cloud session' },
    }),
  })
  assert.deepEqual(workspaceEvents, [{
    sequence: 45,
    eventId: 'event-45',
    sessionId: 'session-2',
    type: 'session.created',
    payload: { title: 'New cloud session' },
  }])
  workspaceSubscription.close()
  assert.equal(instances[1]?.closed, true)
})

test('cloud transport adapter authenticates SSE subscriptions with bearer headers', async () => {
  const requests: Array<{ url: string, init?: Parameters<CloudTransportFetch>[1] }> = []
  const fetcher: CloudTransportFetch = async (url, init) => {
    requests.push({ url, init })
    return {
      ok: true,
      status: 200,
      async text() {
        return ''
      },
      body: new ReadableStream<Uint8Array>({
        start(controller) {
          controller.enqueue(new TextEncoder().encode([
            'event: assistant.message',
            'data: {"sequence":7,"eventId":"event-7","type":"assistant.message","payload":{"content":"hello"}}',
            '',
            '',
          ].join('\n')))
          controller.close()
        },
      }),
    }
  }
  const EventSourceImpl: CloudTransportEventSource = class {
    constructor() {
      throw new Error('EventSource should not be used when bearer headers are configured.')
    }
    close() {}
    addEventListener() {}
    onmessage = null
    onerror = null
  }
  const transport = createHttpSseCloudTransportAdapter({
    baseUrl: 'https://cloud.example.test',
    fetch: fetcher,
    eventSource: EventSourceImpl,
    credentials: 'include',
    headers: {
      authorization: 'Bearer cloud-token',
    },
  })
  const delivered = new Promise<unknown>((resolve, reject) => {
    const subscription = transport.subscribeSessionEvents('session-1', {
      onEvent: (event) => {
        subscription.close()
        resolve(event)
      },
      onError: reject,
    })
  })

  assert.deepEqual(await delivered, {
    sequence: 7,
    eventId: 'event-7',
    type: 'assistant.message',
    payload: { content: 'hello' },
  })
  assert.equal(requests[0]?.url, 'https://cloud.example.test/api/sessions/session-1/events')
  assert.equal(requests[0]?.init?.headers?.authorization, 'Bearer cloud-token')
  assert.equal(requests[0]?.init?.headers?.accept, 'text/event-stream')
  assert.equal(requests[0]?.init?.credentials, 'include')
})

test('cloud transport adapter exposes typed HTTP error taxonomy', async () => {
  const cases: Array<{ status: number, kind: CloudTransportError['kind'] }> = [
    { status: 401, kind: 'unauthorized' },
    { status: 403, kind: 'forbidden' },
    { status: 402, kind: 'payment_required' },
    { status: 404, kind: 'not_found' },
    { status: 409, kind: 'conflict' },
    { status: 429, kind: 'rate_limited' },
    { status: 500, kind: 'server' },
  ]

  for (const testCase of cases) {
    const transport = createHttpSseCloudTransportAdapter({
      baseUrl: 'https://cloud.example.test',
      fetch: async () => jsonResponse(
        { error: `status ${testCase.status}`, code: `E_${testCase.status}` },
        testCase.status,
        { 'retry-after': '60' },
      ),
    })

    await assert.rejects(
      transport.getConfig(),
      (error) => {
        assert.equal(isCloudTransportError(error), true)
        const transportError = error as CloudTransportError
        assert.equal(transportError.kind, testCase.kind)
        assert.equal(transportError.status, testCase.status)
        assert.equal(transportError.code, `E_${testCase.status}`)
        assert.equal(transportError.retryAfter, '60')
        assert.match(transportError.url || '', /^https:\/\/cloud\.example\.test\/api\/config$/)
        return true
      },
    )
  }
})

test('cloud transport adapter exposes typed parse and network errors', async () => {
  const parseTransport = createHttpSseCloudTransportAdapter({
    baseUrl: 'https://cloud.example.test',
    fetch: async () => textResponse('{not-json', 200),
  })
  await assert.rejects(
    parseTransport.getConfig(),
    (error) => {
      assert.equal(isCloudTransportError(error), true)
      assert.equal((error as CloudTransportError).kind, 'parse')
      assert.equal((error as CloudTransportError).status, 200)
      assert.equal((error as CloudTransportError).body, '{not-json')
      return true
    },
  )

  const networkTransport = createHttpSseCloudTransportAdapter({
    baseUrl: 'https://cloud.example.test',
    fetch: async () => {
      throw new Error('socket closed')
    },
  })
  await assert.rejects(
    networkTransport.getConfig(),
    (error) => {
      assert.equal(isCloudTransportError(error), true)
      assert.equal((error as CloudTransportError).kind, 'network')
      assert.match((error as CloudTransportError).message, /network request failed/)
      return true
    },
  )
})

test('cloud transport adapter reports typed fetch SSE failures', async () => {
  const httpErrors: unknown[] = []
  const failedTransport = createHttpSseCloudTransportAdapter({
    baseUrl: 'https://cloud.example.test',
    headers: { authorization: 'Bearer cloud-token' },
    fetch: async () => jsonResponse({ error: 'expired token', code: 'TOKEN_EXPIRED' }, 401),
  })
  failedTransport.subscribeWorkspaceEvents({
    onEvent() {},
    onError(error) {
      httpErrors.push(error)
    },
  })
  await new Promise((resolve) => setTimeout(resolve, 0))

  assert.equal(httpErrors.length, 1)
  assert.equal(isCloudTransportError(httpErrors[0]), true)
  assert.equal((httpErrors[0] as CloudTransportError).kind, 'unauthorized')
  assert.equal((httpErrors[0] as CloudTransportError).code, 'TOKEN_EXPIRED')

  const parseErrors: unknown[] = []
  const parseTransport = createHttpSseCloudTransportAdapter({
    baseUrl: 'https://cloud.example.test',
    headers: { authorization: 'Bearer cloud-token' },
    fetch: async () => ({
      ok: true,
      status: 200,
      async text() {
        return ''
      },
      body: new ReadableStream<Uint8Array>({
        start(controller) {
          controller.enqueue(new TextEncoder().encode('data: {not-json\n\n'))
          controller.close()
        },
      }),
    }),
  })
  parseTransport.subscribeSessionEvents('session-1', {
    onEvent() {},
    onError(error) {
      parseErrors.push(error)
    },
  })
  await new Promise((resolve) => setTimeout(resolve, 0))

  assert.equal(parseErrors.length, 1)
  assert.equal(isCloudTransportError(parseErrors[0]), true)
  assert.equal((parseErrors[0] as CloudTransportError).kind, 'parse')
})

test('cloud transport adapter surfaces channel delivery SSE error payloads', async () => {
  const deliveries: unknown[] = []
  const errors: unknown[] = []
  const transport = createHttpSseCloudTransportAdapter({
    baseUrl: 'https://cloud.example.test',
    headers: { authorization: 'Bearer cloud-token' },
    fetch: async () => ({
      ok: true,
      status: 200,
      headers: { get: () => null },
      async text() {
        return ''
      },
      body: new ReadableStream<Uint8Array>({
        start(controller) {
          controller.enqueue(new TextEncoder().encode('event: error\ndata: {"error":"Gateway API token is not authorized for one or more requested channel bindings."}\n\n'))
          controller.close()
        },
      }),
    }),
  })

  transport.subscribeChannelDeliveries?.({
    claimedBy: 'gateway:test',
    channelBindingIds: ['binding-2'],
    onDelivery(delivery) {
      deliveries.push(delivery)
    },
    onError(error) {
      errors.push(error)
    },
  })
  await new Promise((resolve) => setTimeout(resolve, 0))

  assert.deepEqual(deliveries, [])
  assert.equal(errors.length, 1)
  assert.match(errors[0] instanceof Error ? errors[0].message : String(errors[0]), /not authorized/)
})

test('cloud transport adapter applies request timeout and caller cancellation signals', async () => {
  const timeoutTransport = createHttpSseCloudTransportAdapter({
    baseUrl: 'https://cloud.example.test',
    requestTimeoutMs: 10,
    fetch: (_url, init) => new Promise((resolve, reject) => {
      init?.signal?.addEventListener('abort', () => reject(new Error('request aborted by timeout')), { once: true })
      setTimeout(() => resolve(jsonResponse({ role: 'web' })), 100)
    }),
  })

  await assert.rejects(
    timeoutTransport.getConfig(),
    (error) => {
      assert.equal(error instanceof CloudTransportError, true)
      assert.equal((error as CloudTransportError).kind, 'timeout')
      assert.match((error as CloudTransportError).message, /timed out/)
      return true
    },
  )

  const controller = new AbortController()
  const cancelledTransport = createHttpSseCloudTransportAdapter({
    baseUrl: 'https://cloud.example.test',
    signal: controller.signal,
    fetch: (_url, init) => new Promise((resolve, reject) => {
      init?.signal?.addEventListener('abort', () => reject(new Error('request aborted by caller')), { once: true })
      setTimeout(() => resolve(jsonResponse({ role: 'web' })), 100)
    }),
  })
  const request = cancelledTransport.getConfig()
  controller.abort()
  await assert.rejects(
    request,
    (error) => {
      assert.equal(error instanceof CloudTransportError, true)
      assert.equal((error as CloudTransportError).kind, 'abort')
      return true
    },
  )
})

test('cloud transport adapter closes EventSource SSE subscriptions on caller cancellation', () => {
  const controller = new AbortController()
  const errors: unknown[] = []
  const instances: Array<{
    closed: boolean
    onerror: ((event: unknown) => void) | null
  }> = []
  const EventSourceImpl: CloudTransportEventSource = class {
    closed = false
    onmessage = null
    onerror: ((event: unknown) => void) | null = null
    constructor() {
      instances.push(this)
    }
    close() {
      this.closed = true
    }
    addEventListener() {}
  }
  const transport = createHttpSseCloudTransportAdapter({
    baseUrl: 'https://cloud.example.test',
    eventSource: EventSourceImpl,
    signal: controller.signal,
  })

  transport.subscribeSessionEvents('session-1', {
    onEvent() {},
    onError(error) {
      errors.push(error)
    },
  })
  controller.abort()
  instances[0]?.onerror?.(new Error('closed stream'))

  assert.equal(instances[0]?.closed, true)
  assert.deepEqual(errors, [])
})

test('cloud transport adapter aborts fetch SSE subscriptions on caller cancellation without surfacing errors', async () => {
  const controller = new AbortController()
  const errors: unknown[] = []
  const aborts: string[] = []
  const fetcher: CloudTransportFetch = async (_url, init) => new Promise((resolve, reject) => {
    init?.signal?.addEventListener('abort', () => {
      aborts.push('aborted')
      reject(new Error('fetch SSE aborted'))
    }, { once: true })
    setTimeout(() => resolve({
      ok: true,
      status: 200,
      async text() {
        return ''
      },
      body: new ReadableStream<Uint8Array>(),
    }), 100)
  })
  const transport = createHttpSseCloudTransportAdapter({
    baseUrl: 'https://cloud.example.test',
    fetch: fetcher,
    signal: controller.signal,
    headers: { authorization: 'Bearer cloud-token' },
  })

  transport.subscribeWorkspaceEvents({
    onEvent() {},
    onError(error) {
      errors.push(error)
    },
  })
  controller.abort()
  await new Promise((resolve) => setTimeout(resolve, 0))

  assert.deepEqual(aborts, ['aborted'])
  assert.deepEqual(errors, [])
})
