import { describe, expect, it } from 'vitest'
import { AgentConfigSchema, isLoopbackWsUrl, loadAgentConfig } from '../src/config/agentConfig.js'

const base = {
  relayUrl: 'wss://relay.example.com/agent',
  enrollUrl: 'https://example.com/enroll',
  stateDir: '/tmp/wta',
  localTargetUrl: 'ws://127.0.0.1:3000',
  subdomain: null,
  hostId: null,
}

describe('AgentConfig validation', () => {
  it('parses a valid config', () => {
    expect(() => AgentConfigSchema.parse(base)).not.toThrow()
  })

  it('rejects a non-wss relayUrl', () => {
    expect(() => AgentConfigSchema.parse({ ...base, relayUrl: 'http://relay.example.com' })).toThrow()
    expect(() => AgentConfigSchema.parse({ ...base, relayUrl: 'ws://relay.example.com' })).toThrow()
  })

  it('rejects a non-https enrollUrl', () => {
    expect(() => AgentConfigSchema.parse({ ...base, enrollUrl: 'http://example.com/enroll' })).toThrow()
  })

  it('rejects a non-loopback localTargetUrl (anti-SSRF)', () => {
    expect(() => AgentConfigSchema.parse({ ...base, localTargetUrl: 'ws://10.0.0.5:3000' })).toThrow()
    expect(() => AgentConfigSchema.parse({ ...base, localTargetUrl: 'ws://evil.example.com:3000' })).toThrow()
  })

  it('accepts loopback localTargetUrl variants', () => {
    expect(isLoopbackWsUrl('ws://127.0.0.1:3000')).toBe(true)
    expect(isLoopbackWsUrl('ws://localhost:3000')).toBe(true)
    expect(isLoopbackWsUrl('ws://127.5.5.5:3000')).toBe(true)
    expect(isLoopbackWsUrl('ws://[::1]:3000')).toBe(true)
    expect(isLoopbackWsUrl('ws://10.0.0.5:3000')).toBe(false)
    expect(isLoopbackWsUrl('wss://127.0.0.1:3000')).toBe(false)
  })

  it('REGRESSION: rejects a crafted suffixed-hostname target (anti-SSRF bypass)', () => {
    // Hostname, not a loopback literal — the outbound dial would DNS-resolve and connect out.
    expect(isLoopbackWsUrl('ws://127.0.0.1.attacker.example.com:3000/x')).toBe(false)
    expect(isLoopbackWsUrl('ws://127.evil.net:3000')).toBe(false)
    expect(() =>
      AgentConfigSchema.parse({ ...base, localTargetUrl: 'ws://127.0.0.1.attacker.example.com:3000' }),
    ).toThrow()
  })

  it('loadAgentConfig fails fast on a missing relayUrl', () => {
    expect(() => loadAgentConfig({} as NodeJS.ProcessEnv, {})).toThrow()
  })

  it('loadAgentConfig reads env and lets argv override', () => {
    const cfg = loadAgentConfig(
      { RELAY_URL: 'wss://a/agent', ENROLL_URL: 'https://a/enroll' } as unknown as NodeJS.ProcessEnv,
      { subdomain: 'host-42' },
    )
    expect(cfg.relayUrl).toBe('wss://a/agent')
    expect(cfg.subdomain).toBe('host-42')
    expect(cfg.localTargetUrl).toBe('ws://127.0.0.1:3000')
  })
})
