/**
 * Быстрый путь через локальный агент (tablet-agent) — sidecar-служба
 * intent+slots на мини-ПК. Распознаёт команды офлайн за ~2 мс и исполняет
 * их напрямую, минуя облачный LLM.
 *
 * Включается переменной окружения AGENT_URL (напр. http://agent:8091).
 * Если она не задана — tryLocalAgent сразу возвращает null и планшет работает
 * ровно как раньше (облачный LLM). Любая ошибка службы → тоже null → fallback.
 *
 * Разделение ответственности:
 *   • Команды-ДЕЙСТВИЯ (таймер/свет/музыка/очиститель/событие) — исполняет
 *     локальный агент и отвечает коротким подтверждением. Быстро, офлайн.
 *   • Запросы ИНФОРМАЦИИ (погода/календарь/что играет/состояние дома) и всё
 *     неуверенное/none — проваливаются в облачный LLM: он лучше формулирует
 *     ответ по данным.
 */
import { executeTool } from './tools/_registry'
import type { AgentId } from './tools/_types'

const THRESHOLD = parseFloat(process.env.AGENT_THRESHOLD || '0.7')

// Интенты-действия, которые локальный агент исполняет сам (короткое подтверждение).
// Информационные интенты (weather_get, transport_*, calendar_today/week,
// notes_get, home_state, now_playing) сюда НЕ входят — их формулирует LLM.
const ACTION_INTENTS = new Set([
  'timer_set', 'timer_add', 'timer_subtract', 'timer_cancel',
  'purifier_on', 'purifier_off', 'purifier_mode',
  'light_on', 'light_off',
  'music_play', 'music_pause', 'music_resume', 'music_next', 'music_prev', 'music_volume',
  'calendar_create',
])

interface AgentResponse {
  intent: string
  slots: Record<string, string>
  score: number
  tool: { tool: string; args: Record<string, any> } | null
}

async function queryAgent(text: string): Promise<AgentResponse | null> {
  const base = process.env.AGENT_URL
  if (!base) return null
  const r = await fetch(`${base.replace(/\/$/, '')}/predict`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ text }),
    signal: AbortSignal.timeout(1500),
  })
  if (!r.ok) return null
  return r.json()
}

// Короткие естественные подтверждения по интенту. Используют слоты, где уместно.
function confirmText(intent: string, slots: Record<string, string>): string {
  const dur = slots.duration ? ` на ${slots.duration}` : ''
  switch (intent) {
    case 'timer_set': return `Поставила таймер${dur}.`
    case 'timer_add': return `Добавила${slots.duration ? ' ' + slots.duration : ' время'} к таймеру.`
    case 'timer_subtract': return `Убавила${slots.duration ? ' ' + slots.duration : ''} у таймера.`
    case 'timer_cancel': return `Таймер отменила.`
    case 'purifier_on': return `Включаю очиститель.`
    case 'purifier_off': return `Выключаю очиститель.`
    case 'purifier_mode': return `Переключаю режим очистителя${slots.mode ? ' на ' + slots.mode : ''}.`
    case 'light_on': return `Включаю ${slots.device || 'свет'}.`
    case 'light_off': return `Выключаю ${slots.device || 'свет'}.`
    case 'music_play': return `Включаю${slots.query ? ' ' + slots.query : ' музыку'}.`
    case 'music_pause': return `Поставила на паузу.`
    case 'music_resume': return `Продолжаю.`
    case 'music_next': return `Следующий трек.`
    case 'music_prev': return `Предыдущий трек.`
    case 'music_volume': return `Готово, громкость изменила.`
    case 'calendar_create': return `Добавила событие${slots.title ? ' «' + slots.title + '»' : ''}${slots.date ? ' на ' + slots.date : ''}.`
    default: return `Готово.`
  }
}

/**
 * Пытается обработать запрос локальным агентом.
 * Возвращает { text } если команда-действие исполнена, иначе null (→ LLM).
 */
export async function tryLocalAgent(
  text: string,
  agent: AgentId,
): Promise<{ text: string; intent: string } | null> {
  const res = await queryAgent(text)
  if (!res) return null
  if (res.score < THRESHOLD) return null
  if (!ACTION_INTENTS.has(res.intent)) return null      // инфо-запросы → LLM
  if (!res.tool) return null

  const result = await executeTool(res.tool.tool, res.tool.args, agent)
  if (result && (result as any).error) return null      // ошибка tool → пусть LLM разберётся/озвучит
  return { text: confirmText(res.intent, res.slots || {}), intent: res.intent }
}
