import 'server-only'
import { spawn } from 'node:child_process'

// Fire-and-forget SSH to the home Mac to run the capture agent. The Mac's
// authorized_keys entry uses a forced command, so we only send the capture id
// (it arrives via $SSH_ORIGINAL_COMMAND). The Mac script detaches immediately,
// so ssh returns fast; we still cap it with a timeout. Mirrors eorganize's
// "Start AI pass" launcher.
interface SshConfig {
  user: string
  host: string
  port: number
  keyPath: string
  knownHostsPath: string
}

function readSshConfig(): SshConfig {
  return {
    user: process.env.AGENT_SSH_USER || 'erictran',
    host: process.env.AGENT_SSH_HOST || '67.182.44.118',
    port: Number(process.env.AGENT_SSH_PORT || 2222),
    keyPath: process.env.AGENT_SSH_KEY || '/etc/reminder/agent_to_mac',
    knownHostsPath: process.env.AGENT_KNOWN_HOSTS || '/etc/reminder/known_hosts',
  }
}

// Resolves on success, rejects on failure. Callers should catch and log — a
// failed trigger must never fail the capture upload itself (the capture stays
// PENDING and can be retried with the "Run AI pass" button).
// Debounced organize pass: creating/renaming a focus item (or capture-created
// items) schedules one organize run shortly after the burst quiets, so every
// new item gets grouped without a Claude call per keystroke-sized add.
let organizeTimer: ReturnType<typeof setTimeout> | null = null
export function scheduleOrganize(delayMs = 30_000): void {
  if (organizeTimer) clearTimeout(organizeTimer)
  organizeTimer = setTimeout(() => {
    organizeTimer = null
    triggerAgent('organize').catch(err =>
      console.error('[organize] scheduled trigger failed:', err?.message || err))
  }, delayMs)
}

export function triggerAgent(arg: string): Promise<void> {
  const cfg = readSshConfig()
  const args = [
    '-i', cfg.keyPath,
    '-p', String(cfg.port),
    '-o', 'BatchMode=yes',
    '-o', 'ConnectTimeout=10',
    '-o', 'StrictHostKeyChecking=accept-new',
    '-o', `UserKnownHostsFile=${cfg.knownHostsPath}`,
    `${cfg.user}@${cfg.host}`,
    arg,
  ]

  return new Promise<void>((resolve, reject) => {
    const child = spawn('ssh', args, { stdio: ['ignore', 'pipe', 'pipe'] })
    let stderr = ''
    const timer = setTimeout(() => {
      child.kill('SIGTERM')
      reject(new Error('ssh timed out launching agent'))
    }, 15_000)

    child.stderr.on('data', chunk => {
      stderr += chunk.toString()
      if (stderr.length > 2000) stderr = stderr.slice(-2000)
    })
    child.on('error', err => {
      clearTimeout(timer)
      reject(new Error(`ssh spawn failed: ${err.message}`))
    })
    child.on('exit', code => {
      clearTimeout(timer)
      if (code === 0) resolve()
      else reject(new Error(`ssh exited ${code}: ${stderr.trim() || '(no stderr)'}`))
    })
  })
}
