import { describe, expect, it, vi } from 'vitest'
import type { AgentConfig } from '../src/config/agentConfig.js'
import {
  RootRefusedError,
  detectPlatform,
  installService,
  uninstallService,
  type InstallDeps,
} from '../src/service/install.js'

const CFG: AgentConfig = {
  relayUrl: 'wss://relay/agent',
  enrollUrl: 'https://x/enroll',
  stateDir: '/tmp/x',
  localTargetUrl: 'ws://127.0.0.1:3000',
  subdomain: 'host-42',
  hostId: 'h-1',
}

function deps(uid = 501): InstallDeps & { writes: Array<[string, string]>; runs: Array<[string, readonly string[]]> } {
  const writes: Array<[string, string]> = []
  const runs: Array<[string, readonly string[]]> = []
  return {
    writes,
    runs,
    writeFile: (p, c) => writes.push([p, c]),
    runCommand: async (cmd, args) => {
      runs.push([cmd, args])
    },
    getuid: () => uid,
    homedir: () => '/home/alice',
    username: () => 'alice',
    binPath: () => '/usr/local/bin/web-terminal-agent',
  }
}

describe('detectPlatform (T17)', () => {
  it('maps darwin→launchd, linux→systemd, else null', () => {
    expect(detectPlatform('darwin')).toBe('launchd')
    expect(detectPlatform('linux')).toBe('systemd')
    expect(detectPlatform('win32')).toBeNull()
  })
})

describe('installService (T17)', () => {
  it('refuses to install as root (negative, least privilege)', async () => {
    await expect(installService(CFG, 'systemd', deps(0))).rejects.toBeInstanceOf(RootRefusedError)
  })

  it('systemd: writes a run-as-user unit and enables it', async () => {
    const d = deps()
    await installService(CFG, 'systemd', d)
    const [, unit] = d.writes[0]!
    expect(unit).toContain('ExecStart=/usr/local/bin/web-terminal-agent run')
    expect(unit).toContain('User=alice')
    expect(unit).not.toContain('User=root')
    expect(unit).toContain('Restart=on-failure')
    expect(d.runs[0]![0]).toBe('systemctl')
  })

  it('launchd: writes a plist with ProgramArguments run + KeepAlive', async () => {
    const d = deps()
    await installService(CFG, 'launchd', d)
    const [path, plist] = d.writes[0]!
    expect(path).toContain('LaunchAgents')
    expect(plist).toContain('<string>run</string>')
    expect(plist).toContain('<key>KeepAlive</key>')
    expect(d.runs[0]![0]).toBe('launchctl')
  })

  it('uninstall unloads cleanly', async () => {
    const d = deps()
    await uninstallService('launchd', d)
    expect(d.runs[0]).toEqual(['launchctl', ['unload', '/home/alice/Library/LaunchAgents/com.web-terminal.agent.plist']])
  })
})
