/**
 * SOUL File Reader — reads/writes .soul.md files from agent-core/soul/
 * with 30s TTL cache and backup support.
 */

import fs from 'fs/promises'
import path from 'path'

const AGENT_CORE_PATH = process.env.AGENT_CORE_PATH || path.join(process.cwd(), 'agent-core')
const SOUL_DIR = path.join(AGENT_CORE_PATH, 'soul')
const BACKUPS_DIR = path.join(SOUL_DIR, '.backups')

// 30s TTL cache
const cache = new Map<string, { content: string; timestamp: number }>()
const CACHE_TTL = 30_000

function getSoulFilePath(agentId: string): string {
  // Prevent path traversal
  const safe = agentId.replace(/[^a-z0-9-]/g, '')
  return path.join(SOUL_DIR, `${safe}.soul.md`)
}

/**
 * Read a SOUL file with 30s cache
 */
export async function readSoulFile(agentId: string): Promise<string | null> {
  const cached = cache.get(agentId)
  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
    return cached.content
  }

  try {
    const filePath = getSoulFilePath(agentId)
    const content = await fs.readFile(filePath, 'utf-8')
    cache.set(agentId, { content, timestamp: Date.now() })
    return content
  } catch {
    return null
  }
}

/**
 * Write a SOUL file — creates backup first, then writes new content
 */
export async function writeSoulFile(agentId: string, content: string): Promise<void> {
  const filePath = getSoulFilePath(agentId)

  // Ensure backups dir exists
  await fs.mkdir(BACKUPS_DIR, { recursive: true })

  // Create backup of current file
  try {
    const current = await fs.readFile(filePath, 'utf-8')
    const backupName = `${agentId}-${Date.now()}.soul.md`
    await fs.writeFile(path.join(BACKUPS_DIR, backupName), current, 'utf-8')
  } catch {
    // No existing file to backup
  }

  // Write new content
  await fs.writeFile(filePath, content, 'utf-8')

  // Invalidate cache
  cache.delete(agentId)
}

/**
 * List backup versions for an agent
 */
export async function listSoulBackups(agentId: string): Promise<Array<{ filename: string; timestamp: number; size: number }>> {
  try {
    const files = await fs.readdir(BACKUPS_DIR)
    const prefix = `${agentId}-`
    const backups: Array<{ filename: string; timestamp: number; size: number }> = []

    for (const file of files) {
      if (!file.startsWith(prefix) || !file.endsWith('.soul.md')) continue
      const tsStr = file.slice(prefix.length, -'.soul.md'.length)
      const ts = parseInt(tsStr, 10)
      if (isNaN(ts)) continue

      const stat = await fs.stat(path.join(BACKUPS_DIR, file))
      backups.push({ filename: file, timestamp: ts, size: stat.size })
    }

    return backups.sort((a, b) => b.timestamp - a.timestamp)
  } catch {
    return []
  }
}

/**
 * Read a specific backup file
 */
export async function readSoulBackup(filename: string): Promise<string | null> {
  try {
    // Prevent path traversal
    const safe = path.basename(filename)
    return await fs.readFile(path.join(BACKUPS_DIR, safe), 'utf-8')
  } catch {
    return null
  }
}

/**
 * Check if SOUL file exists
 */
export async function soulFileExists(agentId: string): Promise<boolean> {
  try {
    await fs.access(getSoulFilePath(agentId))
    return true
  } catch {
    return false
  }
}

/**
 * Get SOUL file stats
 */
export async function getSoulFileStats(agentId: string): Promise<{ size: number; createdAt: string; updatedAt: string } | null> {
  try {
    const stat = await fs.stat(getSoulFilePath(agentId))
    return {
      size: stat.size,
      createdAt: stat.birthtime.toISOString(),
      updatedAt: stat.mtime.toISOString(),
    }
  } catch {
    return null
  }
}
