import { describe, expect, it } from 'vitest'

import {
  buildDefaultRemoteDir,
  buildRemoteStagingManifest,
  buildRemoteStagingProofScript,
  buildSshArgs,
  buildStageArchiveRemoteCommand,
  extractStagingProofSummary,
  resolveStagingProofOptions,
  sanitizeStagingProofManifest,
} from './run-vps-same-origin-staging-proof-lib.mjs'

function createManifest() {
  return {
    checkoutRoot: '/srv/hypertwist/current',
    publicOrigin: 'https://hypertwist.app',
    supportEmail: 'hello@hypertwist.app',
    publicDocsUrl: 'https://hypertwist.app/docs',
    releaseNotesUrl: 'https://hypertwist.app/changelog',
    correspondingSourceUrl: 'https://git.scriptoriumai.io/scriptoriumadmin/hypertwist',
    openSourceRepoUrl: 'https://git.scriptoriumai.io/scriptoriumadmin/hypertwist',
    operatorCheckoutUrl: 'https://buy.paddle.com/operator',
    studioCheckoutUrl: 'https://buy.paddle.com/studio',
    windowsDownloadUrl: 'https://downloads.hypertwist.app/windows.exe',
    releaseManifestVersion: '1.0.0',
    windowsRelease: {
      buildId: 'win64-1000',
      sha256: 'abc123',
      publishedAt: '2026-06-22T00:00:00.000Z',
    },
    server: {
      port: '3011',
      websiteDistPath: '/srv/hypertwist/current/website/dist',
      billingStatePath: '/var/lib/hypertwist/auth/hypertwist-billing-state.json',
      paddleWebhookSecret: 'super-secret-token',
    },
  }
}

describe('resolveStagingProofOptions', () => {
  it('normalizes the required CLI inputs', () => {
    const options = resolveStagingProofOptions({
      manifestPath: 'deploy/hypertwist.same-origin.bundle.json',
      identityFile: '/tmp/key',
      vpsHost: '212.227.13.220',
      vpsUser: 'dev',
      archiveSource: 'worktree',
      remoteDir: '',
      port: '3011',
      waitSeconds: '30',
      keepRemoteDir: true,
      json: true,
      dryRun: false,
      gitRef: 'abc1234',
    })

    expect(options.remoteDir).toBe('/tmp/hypertwist-website-staging-abc1234')
    expect(options.archiveSource).toBe('worktree')
    expect(options.port).toBe(3011)
    expect(options.waitSeconds).toBe(30)
    expect(options.keepRemoteDir).toBe(true)
    expect(options.json).toBe(true)
  })

  it('falls back to git-head when the archive source is omitted or unrecognized', () => {
    const options = resolveStagingProofOptions({
      manifestPath: 'deploy/hypertwist.same-origin.bundle.json',
      identityFile: '/tmp/key',
      vpsHost: '212.227.13.220',
      vpsUser: 'dev',
      archiveSource: 'unexpected-value',
      remoteDir: '',
      port: '3011',
      waitSeconds: '30',
      keepRemoteDir: false,
      json: false,
      dryRun: false,
      gitRef: 'abc1234',
    })

    expect(options.archiveSource).toBe('git-head')
  })
})

describe('buildRemoteStagingManifest', () => {
  it('rewrites runtime-owned paths for the remote staging checkout', () => {
    const manifest = buildRemoteStagingManifest(createManifest(), {
      remoteDir: '/tmp/hypertwist-stage',
      port: 3011,
    })

    expect(manifest.checkoutRoot).toBe('/tmp/hypertwist-stage')
    expect(manifest.server.port).toBe('3011')
    expect(manifest.server.websiteDistPath).toBe('/tmp/hypertwist-stage/website/dist')
    expect(manifest.server.billingStatePath).toBe('/tmp/hypertwist-stage/hypertwist-billing-state.json')
    expect(manifest.server.serveStaticWebsite).toBe(true)
  })
})

describe('sanitizeStagingProofManifest', () => {
  it('masks secret-like values before dry-run output', () => {
    const sanitized = sanitizeStagingProofManifest(createManifest())

    expect(sanitized.server.paddleWebhookSecret).toBe('su***en')
  })
})

describe('buildRemoteStagingProofScript', () => {
  it('includes the expected remote proof steps and summary marker', () => {
    const script = buildRemoteStagingProofScript({
      remoteDir: '/tmp/hypertwist-stage',
      waitSeconds: 20,
      keepRemoteDir: false,
      manifest: buildRemoteStagingManifest(createManifest(), {
        remoteDir: '/tmp/hypertwist-stage',
        port: 3011,
      }),
    })

    expect(script).toContain('npm run render:same-origin-bundle')
    expect(script).toContain('systemd-analyze verify "$BUNDLE_OUT/hypertwist-website-auth-server.service"')
    expect(script).toContain('http://127.0.0.1:$PORT/api/auth/health')
    expect(script).toContain('LISTENER_PIDS=$(ss -ltnp')
    expect(script).toContain('__HYPERTWIST_STAGING_SUMMARY__')
  })
})

describe('extractStagingProofSummary', () => {
  it('parses the emitted summary marker from remote output', () => {
    const summary = extractStagingProofSummary([
      '[remote_dir] /tmp/hypertwist-stage',
      '__HYPERTWIST_STAGING_SUMMARY__{"ok":true,"remoteDir":"/tmp/hypertwist-stage"}',
    ].join('\n'))

    expect(summary).toEqual({
      ok: true,
      remoteDir: '/tmp/hypertwist-stage',
    })
  })
})

describe('ssh helpers', () => {
  it('builds the archive and ssh command shape', () => {
    expect(buildDefaultRemoteDir('abc1234')).toBe('/tmp/hypertwist-website-staging-abc1234')
    expect(buildStageArchiveRemoteCommand('/tmp/hypertwist-stage')).toContain('tar -xf - -C "/tmp/hypertwist-stage"')
    expect(buildSshArgs({
      identityFile: '/tmp/key',
      vpsUser: 'dev',
      vpsHost: '212.227.13.220',
      remoteCommand: 'echo hello',
    })).toEqual([
      '-i',
      '/tmp/key',
      '-o',
      'StrictHostKeyChecking=no',
      'dev@212.227.13.220',
      'echo hello',
    ])
  })
})
