// @vitest-environment node

import crypto from 'node:crypto'
import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
import { spawn, type ChildProcessByStdio } from 'node:child_process'
import { createServer, type Server } from 'node:http'
import { once } from 'node:events'
import { networkInterfaces } from 'node:os'
import path from 'node:path'
import os from 'node:os'
import { fileURLToPath } from 'node:url'
import type { Readable } from 'node:stream'
import { afterEach, describe, expect, it } from 'vitest'
import { createSignedTestSessionValue } from '../test-session'

const tempRoots: string[] = []
type SpawnedServerProcess = ChildProcessByStdio<null, Readable, Readable>

const childProcesses = new Set<SpawnedServerProcess>()
const servers = new Set<Server>()
const currentDirectory = path.dirname(fileURLToPath(import.meta.url))

function makeTempRoot() {
  const root = mkdtempSync(path.join(os.tmpdir(), 'hypertwist-server-bootstrap-'))
  tempRoots.push(root)
  return root
}

function createDistBundle(root: string) {
  const distPath = path.join(root, 'dist')
  mkdirSync(path.join(distPath, 'assets'), { recursive: true })
  writeFileSync(
    path.join(distPath, 'index.html'),
    '<!doctype html><html><body><div id="app">HyperTwist bootstrap shell</div></body></html>',
    'utf8',
  )
  writeFileSync(path.join(distPath, 'assets', 'app.js'), 'console.log("bootstrap");', 'utf8')
  return distPath
}

function getNonLoopbackIpv4() {
  const interfaces = networkInterfaces()
  for (const entries of Object.values(interfaces)) {
    for (const entry of entries || []) {
      if (entry && entry.family === 'IPv4' && !entry.internal) {
        return entry.address
      }
    }
  }
  return null
}

async function getFreePort(host = '127.0.0.1') {
  const server = createServer()
  servers.add(server)
  server.listen(0, host)
  await once(server, 'listening')
  const address = server.address()
  if (!address || typeof address === 'string') {
    throw new Error('Failed to resolve a free port')
  }
  const port = address.port
  server.close()
  servers.delete(server)
  return port
}

async function startFakeCoreServer(host: string) {
  const server = createServer((req, res) => {
    if ((req.url || '').startsWith('/apiversion')) {
      res.writeHead(200, { 'content-type': 'application/json' })
      res.end(JSON.stringify({ versions: ['5.0'] }))
      return
    }

    res.writeHead(404, { 'content-type': 'application/json' })
    res.end(JSON.stringify({ ok: false, path: req.url || '' }))
  })

  servers.add(server)
  server.listen(0, host)
  await once(server, 'listening')

  const address = server.address()
  if (!address || typeof address === 'string') {
    throw new Error('Failed to bind fake SuperTokens core server')
  }

  return {
    server,
    connectionUri: `http://${host}:${address.port}`,
  }
}

function readStreamText(value: unknown) {
  return Buffer.isBuffer(value) ? value.toString('utf8') : String(value || '')
}

function buildPaddleSignatureHeader(rawBody: string, secretKey: string, timestamp: string) {
  const signature = crypto
    .createHmac('sha256', secretKey)
    .update(`${timestamp}:${rawBody}`)
    .digest('hex')

  return `ts=${timestamp};h1=${signature}`
}

function spawnAuthServer(env: NodeJS.ProcessEnv) {
  const serverRoot = path.resolve(currentDirectory, '../..')
  const tsxCliPath = path.join(serverRoot, 'node_modules', 'tsx', 'dist', 'cli.mjs')
  const child = spawn(process.execPath, [tsxCliPath, 'src/index.ts'], {
    cwd: serverRoot,
    env,
    stdio: ['ignore', 'pipe', 'pipe'],
  })

  childProcesses.add(child)

  const logs = {
    stdout: '',
    stderr: '',
  }

  child.stdout.on('data', (chunk) => {
    logs.stdout += readStreamText(chunk)
  })
  child.stderr.on('data', (chunk) => {
    logs.stderr += readStreamText(chunk)
  })

  return { child, logs }
}

async function waitForHttpReady(baseUrl: string, child: SpawnedServerProcess, logs: { stdout: string; stderr: string }) {
  const startedAt = Date.now()

  while (Date.now() - startedAt < 15_000) {
    if (child.exitCode !== null) {
      throw new Error(
        `Auth server exited before becoming ready (code ${child.exitCode}).\nSTDOUT:\n${logs.stdout}\nSTDERR:\n${logs.stderr}`,
      )
    }

    try {
      const response = await fetch(`${baseUrl}/health`)
      if (response.ok) {
        return
      }
    } catch {
      // keep polling until ready or timeout
    }

    await new Promise((resolve) => setTimeout(resolve, 150))
  }

  throw new Error(`Timed out waiting for auth server readiness.\nSTDOUT:\n${logs.stdout}\nSTDERR:\n${logs.stderr}`)
}

async function stopChildProcess(child: SpawnedServerProcess) {
  if (child.exitCode !== null) {
    childProcesses.delete(child)
    return
  }

  child.kill('SIGTERM')
  const exitResult = await Promise.race([
    once(child, 'exit'),
    new Promise<'timeout'>((resolve) => setTimeout(() => resolve('timeout'), 5_000)),
  ])

  if (exitResult === 'timeout' && child.exitCode === null) {
    child.kill('SIGKILL')
    await once(child, 'exit')
  }

  childProcesses.delete(child)
}

afterEach(async () => {
  const children = Array.from(childProcesses)
  childProcesses.clear()
  await Promise.all(children.map((child) => stopChildProcess(child)))

  for (const server of Array.from(servers)) {
    if (server.listening) {
      await new Promise<void>((resolve, reject) => {
        server.close((error) => {
          if (error) {
            reject(error)
            return
          }
          resolve()
        })
      })
    }
    servers.delete(server)
  }

  while (tempRoots.length > 0) {
    const root = tempRoots.pop()
    if (root) {
      rmSync(root, { recursive: true, force: true })
    }
  }
})

describe('website/server bootstrap', { timeout: 15_000 }, () => {
  it('boots with production-shaped same-origin config and serves live health plus the built website shell', async () => {
    const coreHost = getNonLoopbackIpv4()
    if (!coreHost) {
      throw new Error('A non-loopback IPv4 interface is required for public-posture bootstrap proof.')
    }

    const root = makeTempRoot()
    const distPath = createDistBundle(root)
    const billingStatePath = path.join(root, 'billing-state.json')
    const fakeCore = await startFakeCoreServer(coreHost)
    const serverPort = await getFreePort('127.0.0.1')
    const baseUrl = `http://127.0.0.1:${serverPort}`

    const { child, logs } = spawnAuthServer({
      ...process.env,
      PORT: String(serverPort),
      SUPERTOKENS_CORE_URI: fakeCore.connectionUri,
      API_DOMAIN: 'https://hypertwist.app',
      WEBSITE_DOMAIN: 'https://hypertwist.app',
      API_BASE_PATH: '/auth',
      WEBSITE_BASE_PATH: '/auth',
      COOKIE_SECURE: 'true',
      SERVE_STATIC_WEBSITE: 'true',
      WEBSITE_DIST_PATH: distPath,
      DEFAULT_PLAN: 'free',
      DEFAULT_ROLE: 'operator',
      SUPERTOKENS_HEALTH_TIMEOUT_MS: '1500',
      DESKTOP_LINK_RATE_LIMIT_MAX: '5',
      DESKTOP_LINK_RATE_LIMIT_WINDOW_MS: '900000',
      PADDLE_WEBHOOK_SECRET: 'real-secret-value',
      BILLING_STATE_PATH: billingStatePath,
      PADDLE_PRODUCT_PLAN_MAP: '{"prod_operator":"operator","prod_studio":"studio"}',
      PADDLE_PRICE_PLAN_MAP: '{"pri_operator":"operator","pri_studio":"studio"}',
      SUPPORT_EMAIL: 'ops@hypertwist.app',
      PUBLIC_DOCS_URL: 'https://docs.hypertwist.app',
      RELEASE_NOTES_URL: 'https://notes.hypertwist.app',
      MPL_SOURCE_URL: 'https://hypertwist.app/open-source/source.zip',
      OPEN_SOURCE_REPO_URL: 'https://git.scriptoriumai.io/scriptoriumadmin/hypertwist',
      VITE_PADDLE_CHECKOUT_URL_OPERATOR: 'https://buy.paddle.com/operator-live',
      VITE_PADDLE_CHECKOUT_URL_STUDIO: 'https://buy.paddle.com/studio-live',
      VITE_PLAN_PRICE_OPERATOR: '$19 / month',
      VITE_PLAN_PRICE_STUDIO: '$99 / month',
      RELEASE_MANIFEST_VERSION: '1.0.0',
      RELEASE_MANIFEST_CHANNEL: 'candidate',
      WINDOWS_DOWNLOAD_URL: 'https://downloads.hypertwist.app/windows.exe',
      WINDOWS_RELEASE_BUILD_ID: 'win64-1000',
      WINDOWS_RELEASE_SHA256: 'abc123',
      WINDOWS_RELEASE_FILE_SIZE_BYTES: '1048576',
      WINDOWS_RELEASE_PUBLISHED_AT: '2026-06-22T00:00:00.000Z',
      GITHUB_CLIENT_ID: '',
      GITHUB_CLIENT_SECRET: '',
      GOOGLE_CLIENT_ID: '',
      GOOGLE_CLIENT_SECRET: '',
    })

    try {
      await waitForHttpReady(baseUrl, child, logs)

      const healthResponse = await fetch(`${baseUrl}/health`)
      expect(healthResponse.status).toBe(200)
      expect(await healthResponse.json()).toEqual({
        ok: true,
        service: 'hypertwist-auth-server',
      })

      const authHealthResponse = await fetch(`${baseUrl}/api/auth/health`)
      expect(authHealthResponse.status).toBe(200)
      expect(await authHealthResponse.json()).toMatchObject({
        ok: true,
        service: 'hypertwist-auth-server',
        supertokens: {
          configured: true,
          reachable: true,
          ready: true,
          apiVersion: '5.0',
          oauth: {
            github: false,
            google: false,
          },
        },
        fallback: {
          enabled: true,
          active: false,
          reason: null,
        },
        billing: {
          processedEventCount: 0,
          productPlanMapConfigured: true,
          pricePlanMapConfigured: true,
          webhookSecretConfigured: true,
        },
        runtime: {
          mode: 'public',
          public_origin_ready: true,
          cookie_secure: true,
          api_domain: 'https://hypertwist.app',
          website_domain: 'https://hypertwist.app',
          warnings: [],
          errors: [],
        },
        launch: {
          posture: 'launch-ready',
          ready: true,
          missingLabels: [],
          targets: {
            operatorCheckoutTarget: 'https://buy.paddle.com/operator-live',
            studioCheckoutTarget: 'https://buy.paddle.com/studio-live',
          },
          readiness: {
            windowsDownloadConfigured: true,
            operatorCheckoutConfigured: true,
            studioCheckoutConfigured: true,
            mplSourceConfigured: true,
            openSourceRepoConfigured: true,
            billingProductPlanMapConfigured: true,
            billingPricePlanMapConfigured: true,
            billingWebhookSecretConfigured: true,
            publicAuthRuntimeReady: true,
          },
        },
      })

      const releaseManifestResponse = await fetch(`${baseUrl}/api/releases/manifest`)
      expect(releaseManifestResponse.status).toBe(200)
      const releaseManifestPayload = await releaseManifestResponse.json()
      expect(releaseManifestPayload).toMatchObject({
        ok: true,
        manifest: {
          support_email: 'ops@hypertwist.app',
          public_docs_url: 'https://docs.hypertwist.app',
          release_notes_url: 'https://notes.hypertwist.app',
          corresponding_source_url: 'https://hypertwist.app/open-source/source.zip',
          open_source_repo_url: 'https://git.scriptoriumai.io/scriptoriumadmin/hypertwist',
          commerce: {
            operator_checkout_url: 'https://buy.paddle.com/operator-live',
            studio_checkout_url: 'https://buy.paddle.com/studio-live',
            plan_price_operator: '$19 / month',
            plan_price_studio: '$99 / month',
          },
          viewer: {
            authenticated: false,
            canDownload: false,
            plan: null,
            role: null,
            accessStatus: null,
          },
        },
      })
      expect(releaseManifestPayload.manifest.platforms).toEqual(expect.arrayContaining([
        expect.objectContaining({
          platform_key: 'windows',
          platform: 'Windows',
          subtitle: 'Primary shipping lane',
          details: 'Current packaged validation is strongest on the Windows Unreal lane.',
          configured: true,
          channel: 'candidate',
          version: '1.0.0',
          build_id: 'win64-1000',
          published_at: '2026-06-22T00:00:00.000Z',
          file_size_bytes: 1048576,
          checksum_sha256: 'abc123',
          download_available: false,
          download_url: null,
        }),
      ]))
      expect(releaseManifestPayload.manifest.platforms).toHaveLength(3)

      const aboutResponse = await fetch(`${baseUrl}/about`)
      expect(aboutResponse.status).toBe(200)
      expect(await aboutResponse.text()).toContain('HyperTwist bootstrap shell')

      const downloadsResponse = await fetch(`${baseUrl}/app/downloads`)
      expect(downloadsResponse.status).toBe(200)
      expect(await downloadsResponse.text()).toContain('HyperTwist bootstrap shell')

      const missingAssetResponse = await fetch(`${baseUrl}/assets/missing.js`)
      expect(missingAssetResponse.status).toBe(404)
      expect(await missingAssetResponse.text()).toContain('Cannot GET /assets/missing.js')
    } finally {
      await stopChildProcess(child)
    }
  })

  it('applies a verified live webhook and reflects the processed event count through auth health and billing state', async () => {
    const coreHost = getNonLoopbackIpv4()
    if (!coreHost) {
      throw new Error('A non-loopback IPv4 interface is required for public-posture bootstrap proof.')
    }

    const root = makeTempRoot()
    createDistBundle(root)
    const billingStatePath = path.join(root, 'billing-state.json')
    const fakeCore = await startFakeCoreServer(coreHost)
    const serverPort = await getFreePort('127.0.0.1')
    const baseUrl = `http://127.0.0.1:${serverPort}`
    const webhookSecret = 'real-secret-value'

    const { child, logs } = spawnAuthServer({
      ...process.env,
      PORT: String(serverPort),
      SUPERTOKENS_CORE_URI: fakeCore.connectionUri,
      API_DOMAIN: 'https://hypertwist.app',
      WEBSITE_DOMAIN: 'https://hypertwist.app',
      API_BASE_PATH: '/auth',
      WEBSITE_BASE_PATH: '/auth',
      COOKIE_SECURE: 'true',
      SERVE_STATIC_WEBSITE: 'true',
      WEBSITE_DIST_PATH: path.join(root, 'dist'),
      DEFAULT_PLAN: 'free',
      DEFAULT_ROLE: 'operator',
      SUPERTOKENS_HEALTH_TIMEOUT_MS: '1500',
      DESKTOP_LINK_RATE_LIMIT_MAX: '5',
      DESKTOP_LINK_RATE_LIMIT_WINDOW_MS: '900000',
      PADDLE_WEBHOOK_SECRET: webhookSecret,
      BILLING_STATE_PATH: billingStatePath,
      PADDLE_PRODUCT_PLAN_MAP: '{"prod_operator":"operator","prod_studio":"studio"}',
      PADDLE_PRICE_PLAN_MAP: '{"pri_operator":"operator","pri_studio":"studio"}',
      SUPPORT_EMAIL: 'ops@hypertwist.app',
      PUBLIC_DOCS_URL: 'https://docs.hypertwist.app',
      RELEASE_NOTES_URL: 'https://notes.hypertwist.app',
      MPL_SOURCE_URL: 'https://hypertwist.app/open-source/source.zip',
      OPEN_SOURCE_REPO_URL: 'https://git.scriptoriumai.io/scriptoriumadmin/hypertwist',
      VITE_PADDLE_CHECKOUT_URL_OPERATOR: 'https://buy.paddle.com/operator-live',
      VITE_PADDLE_CHECKOUT_URL_STUDIO: 'https://buy.paddle.com/studio-live',
      VITE_PLAN_PRICE_OPERATOR: '$19 / month',
      VITE_PLAN_PRICE_STUDIO: '$99 / month',
      RELEASE_MANIFEST_VERSION: '1.0.0',
      RELEASE_MANIFEST_CHANNEL: 'candidate',
      WINDOWS_DOWNLOAD_URL: 'https://downloads.hypertwist.app/windows.exe',
      WINDOWS_RELEASE_BUILD_ID: 'win64-1000',
      WINDOWS_RELEASE_SHA256: 'abc123',
      WINDOWS_RELEASE_FILE_SIZE_BYTES: '1048576',
      WINDOWS_RELEASE_PUBLISHED_AT: '2026-06-22T00:00:00.000Z',
      GITHUB_CLIENT_ID: '',
      GITHUB_CLIENT_SECRET: '',
      GOOGLE_CLIENT_ID: '',
      GOOGLE_CLIENT_SECRET: '',
    })

    try {
      await waitForHttpReady(baseUrl, child, logs)

      const rawBody = JSON.stringify({
        event_id: 'evt_live_txn',
        event_type: 'transaction.completed',
        occurred_at: '2026-06-22T03:45:00.000Z',
        data: {
          id: 'txn_live_123',
          customer_id: 'ctm_live_123',
          custom_data: {
            email: 'operator@hypertwist.app',
          },
          items: [
            {
              price: {
                id: 'pri_operator',
              },
            },
          ],
        },
      })

      const timestamp = String(Math.floor(Date.now() / 1_000))
      const webhookResponse = await fetch(`${baseUrl}/api/billing/paddle/webhook`, {
        method: 'POST',
        headers: {
          'content-type': 'application/json',
          'paddle-signature': buildPaddleSignatureHeader(rawBody, webhookSecret, timestamp),
        },
        body: rawBody,
      })

      expect(webhookResponse.status).toBe(200)
      expect(await webhookResponse.json()).toEqual({
        received: true,
        verified: true,
        apply_result: {
          kind: 'applied',
          reason: 'processed',
          eventId: 'evt_live_txn',
          eventType: 'transaction.completed',
          email: 'operator@hypertwist.app',
        },
      })

      const authHealthResponse = await fetch(`${baseUrl}/api/auth/health`)
      expect(authHealthResponse.status).toBe(200)
      expect(await authHealthResponse.json()).toMatchObject({
        billing: {
          processedEventCount: 1,
          productPlanMapConfigured: true,
          pricePlanMapConfigured: true,
          webhookSecretConfigured: true,
        },
        fallback: {
          active: false,
        },
        launch: {
          posture: 'launch-ready',
          ready: true,
          missingLabels: [],
        },
      })

      const stateFile = JSON.parse(readFileSync(billingStatePath, 'utf8'))
      expect(stateFile.processedEvents).toMatchObject({
        evt_live_txn: '2026-06-22T03:45:00.000Z',
      })
      expect(stateFile.accounts['operator@hypertwist.app']).toMatchObject({
        email: 'operator@hypertwist.app',
        plan: 'operator',
        canDownload: true,
        accessStatus: 'completed',
        source: 'paddle',
        customerId: 'ctm_live_123',
        transactionId: 'txn_live_123',
        lastEventId: 'evt_live_txn',
        lastEventType: 'transaction.completed',
      })
    } finally {
      await stopChildProcess(child)
    }
  })

  it('resolves /api/auth/me and /api/auth/desktop-link through the bounded testing-session harness after entitlement state is applied', async () => {
    const coreHost = getNonLoopbackIpv4()
    if (!coreHost) {
      throw new Error('A non-loopback IPv4 interface is required for public-posture bootstrap proof.')
    }

    const root = makeTempRoot()
    createDistBundle(root)
    const billingStatePath = path.join(root, 'billing-state.json')
    const fakeCore = await startFakeCoreServer(coreHost)
    const serverPort = await getFreePort('127.0.0.1')
    const baseUrl = `http://127.0.0.1:${serverPort}`
    const webhookSecret = 'real-secret-value'
    const testSessionSecret = 'test-session-secret'

    const { child, logs } = spawnAuthServer({
      ...process.env,
      PORT: String(serverPort),
      TEST_MODE: 'testing',
      HYPERTWIST_TEST_SESSION_SECRET: testSessionSecret,
      SUPERTOKENS_CORE_URI: fakeCore.connectionUri,
      API_DOMAIN: 'https://hypertwist.app',
      WEBSITE_DOMAIN: 'https://hypertwist.app',
      API_BASE_PATH: '/auth',
      WEBSITE_BASE_PATH: '/auth',
      COOKIE_SECURE: 'true',
      SERVE_STATIC_WEBSITE: 'true',
      WEBSITE_DIST_PATH: path.join(root, 'dist'),
      DEFAULT_PLAN: 'free',
      DEFAULT_ROLE: 'operator',
      SUPERTOKENS_HEALTH_TIMEOUT_MS: '1500',
      DESKTOP_LINK_RATE_LIMIT_MAX: '5',
      DESKTOP_LINK_RATE_LIMIT_WINDOW_MS: '900000',
      PADDLE_WEBHOOK_SECRET: webhookSecret,
      BILLING_STATE_PATH: billingStatePath,
      PADDLE_PRODUCT_PLAN_MAP: '{"prod_operator":"operator","prod_studio":"studio"}',
      PADDLE_PRICE_PLAN_MAP: '{"pri_operator":"operator","pri_studio":"studio"}',
      SUPPORT_EMAIL: 'ops@hypertwist.app',
      PUBLIC_DOCS_URL: 'https://docs.hypertwist.app',
      RELEASE_NOTES_URL: 'https://notes.hypertwist.app',
      MPL_SOURCE_URL: 'https://hypertwist.app/open-source/source.zip',
      OPEN_SOURCE_REPO_URL: 'https://git.scriptoriumai.io/scriptoriumadmin/hypertwist',
      VITE_PADDLE_CHECKOUT_URL_OPERATOR: 'https://buy.paddle.com/operator-live',
      VITE_PADDLE_CHECKOUT_URL_STUDIO: 'https://buy.paddle.com/studio-live',
      VITE_PLAN_PRICE_OPERATOR: '$19 / month',
      VITE_PLAN_PRICE_STUDIO: '$99 / month',
      RELEASE_MANIFEST_VERSION: '1.0.0',
      RELEASE_MANIFEST_CHANNEL: 'candidate',
      WINDOWS_DOWNLOAD_URL: 'https://downloads.hypertwist.app/windows.exe',
      WINDOWS_RELEASE_BUILD_ID: 'win64-1000',
      WINDOWS_RELEASE_SHA256: 'abc123',
      WINDOWS_RELEASE_FILE_SIZE_BYTES: '1048576',
      WINDOWS_RELEASE_PUBLISHED_AT: '2026-06-22T00:00:00.000Z',
      GITHUB_CLIENT_ID: '',
      GITHUB_CLIENT_SECRET: '',
      GOOGLE_CLIENT_ID: '',
      GOOGLE_CLIENT_SECRET: '',
    })

    try {
      await waitForHttpReady(baseUrl, child, logs)

      const rawBody = JSON.stringify({
        event_id: 'evt_session_user',
        event_type: 'transaction.completed',
        occurred_at: '2026-06-22T04:10:00.000Z',
        data: {
          id: 'txn_session_123',
          customer_id: 'ctm_session_123',
          custom_data: {
            email: 'operator@hypertwist.app',
          },
          items: [
            {
              price: {
                id: 'pri_operator',
              },
            },
          ],
        },
      })

      const timestamp = String(Math.floor(Date.now() / 1_000))
      const webhookResponse = await fetch(`${baseUrl}/api/billing/paddle/webhook`, {
        method: 'POST',
        headers: {
          'content-type': 'application/json',
          'paddle-signature': buildPaddleSignatureHeader(rawBody, webhookSecret, timestamp),
        },
        body: rawBody,
      })
      expect(webhookResponse.status).toBe(200)

      const testSessionHeader = createSignedTestSessionValue({
        userId: 'user-session-1',
        email: 'operator@hypertwist.app',
        plan: 'free',
        role: 'operator',
        name: 'Operator Session',
        authMethod: 'email',
      }, testSessionSecret)

      const meResponse = await fetch(`${baseUrl}/api/auth/me`, {
        headers: {
          'x-hypertwist-test-session': testSessionHeader,
        },
      })
      expect(meResponse.status).toBe(200)
      expect(await meResponse.json()).toEqual({
        user: {
          id: 'user-session-1',
          email: 'operator@hypertwist.app',
          name: 'Operator Session',
          plan: 'operator',
          role: 'operator',
          can_download: true,
          billing: {
            source: 'paddle',
            access_status: 'completed',
            can_download: true,
            subscription_id: null,
            customer_id: 'ctm_session_123',
            transaction_id: 'txn_session_123',
            last_event_id: 'evt_session_user',
            last_event_type: 'transaction.completed',
            last_event_at: '2026-06-22T04:10:00.000Z',
            updated_at: expect.any(String),
            state_path: billingStatePath,
          },
          auth_method: 'supertokens',
        },
        mode: 'supertokens',
      })

      const publicManifestResponse = await fetch(`${baseUrl}/api/releases/manifest`)
      expect(publicManifestResponse.status).toBe(200)
      const publicManifestPayload = await publicManifestResponse.json()
      expect(publicManifestPayload).toMatchObject({
        manifest: {
          viewer: {
            authenticated: false,
            canDownload: false,
          },
        },
      })
      expect(publicManifestPayload.manifest.platforms).toEqual(expect.arrayContaining([
        expect.objectContaining({
          platform_key: 'windows',
          configured: true,
          version: '1.0.0',
          download_available: false,
          download_url: null,
        }),
      ]))

      const entitledManifestResponse = await fetch(`${baseUrl}/api/releases/manifest`, {
        headers: {
          'x-hypertwist-test-session': testSessionHeader,
        },
      })
      expect(entitledManifestResponse.status).toBe(200)
      const entitledManifestPayload = await entitledManifestResponse.json()
      expect(entitledManifestPayload).toMatchObject({
        manifest: {
          support_email: 'ops@hypertwist.app',
          public_docs_url: 'https://docs.hypertwist.app',
          release_notes_url: 'https://notes.hypertwist.app',
          corresponding_source_url: 'https://hypertwist.app/open-source/source.zip',
          open_source_repo_url: 'https://git.scriptoriumai.io/scriptoriumadmin/hypertwist',
          commerce: {
            operator_checkout_url: 'https://buy.paddle.com/operator-live',
            studio_checkout_url: 'https://buy.paddle.com/studio-live',
            plan_price_operator: '$19 / month',
            plan_price_studio: '$99 / month',
          },
          viewer: {
            authenticated: true,
            canDownload: true,
            plan: 'operator',
            role: 'operator',
            accessStatus: 'completed',
          },
        },
      })
      expect(entitledManifestPayload.manifest.platforms).toEqual(expect.arrayContaining([
        expect.objectContaining({
          platform_key: 'windows',
          configured: true,
          channel: 'candidate',
          version: '1.0.0',
          build_id: 'win64-1000',
          published_at: '2026-06-22T00:00:00.000Z',
          file_size_bytes: 1048576,
          checksum_sha256: 'abc123',
          download_available: true,
          download_url: 'https://downloads.hypertwist.app/windows.exe',
        }),
      ]))

      const desktopLinkResponse = await fetch(`${baseUrl}/api/auth/desktop-link`, {
        method: 'POST',
        headers: {
          origin: 'https://hypertwist.app',
          'content-type': 'application/json',
          'x-hypertwist-test-session': testSessionHeader,
        },
        body: JSON.stringify({}),
      })
      expect(desktopLinkResponse.status).toBe(200)
      const desktopLinkPayload = await desktopLinkResponse.json() as {
        ok: true
        token: string
        expires_at: string
      }
      expect(desktopLinkPayload.ok).toBe(true)
      expect(typeof desktopLinkPayload.token).toBe('string')
      expect(typeof desktopLinkPayload.expires_at).toBe('string')

      const verifyResponse = await fetch(`${baseUrl}/api/auth/desktop-link/verify?token=${encodeURIComponent(desktopLinkPayload.token)}`)
      expect(verifyResponse.status).toBe(200)
      expect(await verifyResponse.json()).toEqual({
        ok: true,
        email: 'operator@hypertwist.app',
        plan: 'operator',
        role: 'operator',
        can_download: true,
        access_status: 'completed',
      })
    } finally {
      await stopChildProcess(child)
    }
  })
})
