import { describe, test, expect } from 'vitest'
import { createMemoryStores } from '../src/store/memory.js'
import { createAuditLog, MAX_META_VALUE_LEN } from '../src/audit/log.js'
import { createAccountRegistry } from '../src/registry/accounts.js'
import { createHostRegistry } from '../src/registry/hosts.js'
import { fingerprint } from '../src/ca/fingerprint.js'
import { generateEd25519 } from '../src/util/crypto.js'

describe('T14 audit log (INV10 zero payload)', () => {
  test('rejects a meta value carrying control/ANSI bytes (terminal payload guard)', async () => {
    const { audit } = createMemoryStores()
    const log = createAuditLog(audit)
    await expect(
      log.writeAuditEvent({
        action: 'attach',
        principalId: 'p',
        accountId: 'a',
        hostId: null,
        ts: new Date().toISOString(),
        meta: { out: 'ls[0m\r\noutput' }, // looks like shell output
      }),
    ).rejects.toThrow(/payload guard/)
  })

  test('rejects an over-long meta value', async () => {
    const { audit } = createMemoryStores()
    const log = createAuditLog(audit)
    await expect(
      log.writeAuditEvent({
        action: 'manage',
        principalId: 'p',
        accountId: 'a',
        hostId: null,
        ts: new Date().toISOString(),
        meta: { blob: 'x'.repeat(MAX_META_VALUE_LEN + 1) },
      }),
    ).rejects.toThrow(/payload guard/)
  })

  test('append-only: entries are queryable, no update/delete surface exists', async () => {
    const { audit } = createMemoryStores()
    const log = createAuditLog(audit)
    await log.writeAuditEvent({ action: 'kill', principalId: 'p', accountId: 'acct', hostId: 'h', ts: new Date().toISOString(), meta: {} })
    const rows = await log.queryAudit('acct', '1970-01-01T00:00:00.000Z', '2999-01-01T00:00:00.000Z')
    expect(rows.length).toBe(1)
    expect(Object.keys(log)).not.toContain('update')
    expect(Object.keys(log)).not.toContain('delete')
  })

  test('control-plane mutations emit audit entries (create + bind)', async () => {
    const stores = createMemoryStores()
    const log = createAuditLog(stores.audit)
    const accounts = createAccountRegistry({ accounts: stores.accounts, audit: log })
    const hosts = createHostRegistry({ hosts: stores.hosts, audit: log })
    const acct = await accounts.createAccount('pro')
    const { publicKeyRaw } = generateEd25519()
    await hosts.bindHost({ accountId: acct.accountId, subdomain: 'alice', agentPubkey: publicKeyRaw, enrollFpr: fingerprint(publicKeyRaw) })
    const rows = await log.queryAudit(acct.accountId, '1970-01-01T00:00:00.000Z', '2999-01-01T00:00:00.000Z')
    expect(rows.map((r) => r.action).sort()).toEqual(['account.create', 'host.bind'])
  })
})
