/**
 * DeveloperLogEncryptor - Encrypted developer logs
 * DD §16.2. Encrypts developer log chunks using project key.
 *
 * @module packages/runtime/src/logging/DeveloperLogEncryptor
 */

import { createHash, randomBytes, createCipheriv, createDecipheriv } from 'crypto'
import { appendFileSync, readFileSync, existsSync, mkdirSync } from 'fs'
import { join } from 'path'

const ALGORITHM = 'aes-256-gcm'
const IV_LENGTH = 12
const TAG_LENGTH = 16

export class DeveloperLogEncryptor {
  private key: Buffer
  private log_path: string

  constructor(project_root: string, project_key?: string) {
    this.log_path = join(project_root, '.air', 'logs', 'air.developer.log')
    const key_source = project_key || process.env.AIRCODING_PROJECT_KEY
    if (!key_source) {
      throw new Error(
        'DeveloperLogEncryptor requires a project key. ' +
        'Set AIRCODING_PROJECT_KEY environment variable or pass project_key parameter.'
      )
    }
    this.key = this.derive_key(key_source)

    // Ensure log directory exists
    const dir = join(this.log_path, '..')
    if (!existsSync(dir)) mkdirSync(dir, { recursive: true })
  }

  /**
   * Encrypt and write a developer log entry.
   * INV-3: Uses SecretRedactor for secrets before writing.
   */
  write(entry: Record<string, unknown>): void {
    const iv = randomBytes(IV_LENGTH)
    const cipher = createCipheriv(ALGORITHM, this.key, iv)

    const plaintext = JSON.stringify({
      ...entry,
      timestamp: new Date().toISOString()
    })

    const encrypted = Buffer.concat([
      cipher.update(plaintext, 'utf-8'),
      cipher.final()
    ])
    const tag = cipher.getAuthTag()

    // Format: IV (12) + Tag (16) + Encrypted
    const chunk = Buffer.concat([iv, tag, encrypted])
    appendFileSync(this.log_path, chunk.toString('base64') + '\n')
  }

  /**
   * Decrypt and read developer logs.
   * TODO(P8): Implement chunk-by-chunk decryption for log reading.
   */
  read(): Array<Record<string, unknown>> {
    if (!existsSync(this.log_path)) return []

    const entries: Array<Record<string, unknown>> = []
    try {
      const content = readFileSync(this.log_path, 'utf-8')
      const lines = content.trim().split('\n')

      for (const line of lines) {
        if (!line) continue
        try {
          const chunk = Buffer.from(line, 'base64')
          const iv = chunk.subarray(0, IV_LENGTH)
          const tag = chunk.subarray(IV_LENGTH, IV_LENGTH + TAG_LENGTH)
          const encrypted = chunk.subarray(IV_LENGTH + TAG_LENGTH)

          const decipher = createDecipheriv(ALGORITHM, this.key, iv)
          decipher.setAuthTag(tag)
          const decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()])
          entries.push(JSON.parse(decrypted.toString('utf-8')))
        } catch {
          // Skip corrupted entries
        }
      }
    } catch {
      // File unreadable
    }

    return entries
  }

  private derive_key(seed: string): Buffer {
    return createHash('sha256').update(seed).digest()
  }
}
