'use client';

import { useState, useEffect, useCallback, useMemo, useRef } from 'react';
import { X, Save, Plus, Trash2, ChevronDown, ChevronRight, Pencil, Check, Play, Square, RefreshCw } from 'lucide-react';
import { toast } from 'sonner';
import { createAgent, updateAgent, getProviders, syncOpenRouterModels, previewVoice } from '@client/api/ai-agents';
import DemoDisabled from '@client/components/demo/DemoDisabled';
import type { AiAgent, LlmProvider, VoiceProvider } from '@client/api/ai-agents';
import AgentPreview from './AgentPreview';
import { useLanguage } from '@client/contexts/LanguageContext';
import {
  CAPABILITY_KEYS,
  REALTIME_MODELS,
  VAD_DEFAULTS,
  DEFAULT_REALTIME_MODEL,
} from '@/shared/config/ai-defaults';

interface FallbackRule {
  id: string;
  trigger: string;
  action: string;
  priority: 'high' | 'medium' | 'low';
}

interface Props {
  agent: AiAgent | null;
  onClose: () => void;
  onSaved: (agent: AiAgent, isNew: boolean) => void;
}

interface KbEntryLite { id: string; title: string; type?: string }
interface MenuCategoryLite { id: string; name: string }

const PRIORITY_CLASS: Record<string, string> = {
  high: 'badge-danger',
  medium: 'badge-warning',
  low: 'badge-neutral',
};

export default function AgentDrawer({ agent, onClose, onSaved }: Props) {
  const { t } = useLanguage();
  const isEditing = !!agent?.id;

  const CAPABILITY_OPTIONS = useMemo(
    () => CAPABILITY_KEYS.map(c => ({
      key: c.key,
      label: t(`aiAgentConfig.capabilities.${c.key}`, c.label),
    })),
    [t]
  );

  const [name, setName] = useState(agent?.name ?? '');
  const [description, setDescription] = useState(agent?.description ?? '');
  const [llmModelId, setLlmModelId] = useState(agent?.llm_model_id ?? '');
  const [voiceModelId, setVoiceModelId] = useState(agent?.voice_model_id ?? '');
  const [voiceLanguageCode, setVoiceLanguageCode] = useState(agent?.voice_language_code ?? '');
  const [llmModelFilter, setLlmModelFilter] = useState('');
  const [verifying, setVerifying] = useState(false);
  const [verifyResult, setVerifyResult] = useState<{ ok: boolean; error?: string; latencyMs?: number } | null>(null);
  const [realtimeModel, setRealtimeModel] = useState(agent?.realtime_model ?? DEFAULT_REALTIME_MODEL);
  const [vadThreshold, setVadThreshold] = useState<number>(agent?.vad_threshold ?? VAD_DEFAULTS.threshold);
  const [vadPrefixPaddingMs, setVadPrefixPaddingMs] = useState<number>(agent?.vad_prefix_padding_ms ?? VAD_DEFAULTS.prefixPaddingMs);
  const [vadSilenceDurationMs, setVadSilenceDurationMs] = useState<number>(agent?.vad_silence_duration_ms ?? VAD_DEFAULTS.silenceDurationMs);
  const [knowledgeBaseIds, setKnowledgeBaseIds] = useState<string[]>(agent?.knowledge_base_ids ?? []);
  const [menuCategoryIds, setMenuCategoryIds] = useState<string[]>(agent?.menu_category_ids ?? []);
  const [kbOptions, setKbOptions] = useState<KbEntryLite[]>([]);
  const [menuCategoryOptions, setMenuCategoryOptions] = useState<MenuCategoryLite[]>([]);
  const [systemPrompt, setSystemPrompt] = useState(agent?.system_prompt ?? '');
  const [greetingScript, setGreetingScript] = useState(agent?.greeting_script ?? '');
  const [closingScript, setClosingScript] = useState(agent?.closing_script ?? '');
  const [isDefault, setIsDefault] = useState(agent?.is_default ?? false);
  const [channelVoice, setChannelVoice] = useState(() => {
    const ch = agent?.channels ?? ['chat', 'voice'];
    return ch.includes('voice');
  });
  const [channelChat, setChannelChat] = useState(() => {
    const ch = agent?.channels ?? ['chat', 'voice'];
    return ch.includes('chat');
  });
  const [capabilities, setCapabilities] = useState<Record<string, boolean>>(() => {
    const caps: Record<string, boolean> = {};
    // Permissive default: when an agent has no capabilities map at all
    // (legacy / freshly-created), every capability is ON. Only explicit
    // `false` values from a stored map disable a capability — that way
    // opening + saving the drawer for a legacy agent doesn't silently
    // gate place_order / book_table / search_knowledge_base / etc.
    const hasMap = agent?.capabilities && typeof agent.capabilities === 'object';
    const stored = (agent?.capabilities as Record<string, boolean> | null | undefined) ?? null;
    CAPABILITY_OPTIONS.forEach(c => { caps[c.key] = hasMap ? (stored?.[c.key] ?? true) : true; });
    return caps;
  });
  const [fallbackRules, setFallbackRules] = useState<FallbackRule[]>(() =>
    (agent?.fallback_rules ?? []).map((r, i) => ({ id: String(i), trigger: r.trigger, action: r.action, priority: (r.priority as FallbackRule['priority']) || 'medium' }))
  );

  const [llmProviders, setLlmProviders] = useState<LlmProvider[]>([]);
  const [voiceProviders, setVoiceProviders] = useState<VoiceProvider[]>([]);
  const [saving, setSaving] = useState(false);
  const [syncing, setSyncing] = useState(false);
  const [previewing, setPreviewing] = useState(false);
  const [isPlaying, setIsPlaying] = useState(false);
  const [showAddRule, setShowAddRule] = useState(false);
  const [newRule, setNewRule] = useState<{ trigger: string; action: string; priority: FallbackRule['priority'] }>({ trigger: '', action: '', priority: 'medium' });
  const [editingRuleId, setEditingRuleId] = useState<string | null>(null);
  const [editRuleForm, setEditRuleForm] = useState<{ trigger: string; action: string; priority: FallbackRule['priority'] }>({ trigger: '', action: '', priority: 'medium' });
  const [expandedSections, setExpandedSections] = useState<Set<string>>(new Set(['identity', 'channels', 'llm', 'voice', 'vad', 'scripts', 'capabilities', 'knowledge', 'menuScope', 'fallback']));
  const [voiceProviderId, setVoiceProviderId] = useState<string>('');

  const audioRef = useRef<HTMLAudioElement | null>(null);
  const audioBlobUrl = useRef<string | null>(null);

  const toggleSection = (key: string) => {
    setExpandedSections(prev => {
      const n = new Set(prev);
      n.has(key) ? n.delete(key) : n.add(key);
      return n;
    });
  };

  const fetchProviders = useCallback(async () => {
    try {
      const providersRes = await getProviders();
      setLlmProviders(providersRes.providers.llm);
      setVoiceProviders(providersRes.providers.voice);
    } catch (err: unknown) {
      toast.error(t('aiAgentConfig.errors.loadProviders', 'Failed to load providers: ') + (err instanceof Error ? err.message : ''));
    }
  }, [t]);

  useEffect(() => { fetchProviders(); }, [fetchProviders]);

  // Load KB entries + menu categories once for the scope pickers. Both
  // endpoints are restaurant-scoped via the session, so no extra params
  // are needed. Failures are non-fatal — the picker simply shows empty.
  useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const [kbRes, catRes] = await Promise.all([
          fetch('/api/knowledge-base?limit=200', { credentials: 'include' }).then(r => r.ok ? r.json() : { entries: [] }),
          fetch('/api/menu/categories', { credentials: 'include' }).then(r => r.ok ? r.json() : { categories: [] }),
        ]);
        if (cancelled) return;
        setKbOptions(Array.isArray(kbRes.entries) ? kbRes.entries.map((e: { id: string; title: string; type?: string }) => ({ id: e.id, title: e.title, type: e.type })) : []);
        setMenuCategoryOptions(Array.isArray(catRes.categories) ? catRes.categories.map((c: { id: string; name: string }) => ({ id: c.id, name: c.name })) : []);
      } catch {
        /* ignore */
      }
    })();
    return () => { cancelled = true; };
  }, []);

  useEffect(() => {
    if (voiceProviders.length > 0) {
      if (voiceModelId) {
        const found = voiceProviders.find(vp => vp.models.some(m => m.id === voiceModelId));
        if (found) setVoiceProviderId(found.id);
      } else if (voiceProviders.length === 1) {
        setVoiceProviderId(voiceProviders[0].id);
      }
    }
  }, [voiceProviders, voiceModelId]);

  useEffect(() => {
    setName(agent?.name ?? '');
    setDescription(agent?.description ?? '');
    setLlmModelId(agent?.llm_model_id ?? '');
    setVoiceModelId(agent?.voice_model_id ?? '');
    setVoiceLanguageCode(agent?.voice_language_code ?? '');
    setRealtimeModel(agent?.realtime_model ?? DEFAULT_REALTIME_MODEL);
    setVadThreshold(agent?.vad_threshold ?? VAD_DEFAULTS.threshold);
    setVadPrefixPaddingMs(agent?.vad_prefix_padding_ms ?? VAD_DEFAULTS.prefixPaddingMs);
    setVadSilenceDurationMs(agent?.vad_silence_duration_ms ?? VAD_DEFAULTS.silenceDurationMs);
    setKnowledgeBaseIds(agent?.knowledge_base_ids ?? []);
    setMenuCategoryIds(agent?.menu_category_ids ?? []);
    setSystemPrompt(agent?.system_prompt ?? '');
    setGreetingScript(agent?.greeting_script ?? '');
    setClosingScript(agent?.closing_script ?? '');
    setIsDefault(agent?.is_default ?? false);
    const ch = agent?.channels ?? ['chat', 'voice'];
    setChannelVoice(ch.includes('voice'));
    setChannelChat(ch.includes('chat'));
    const caps: Record<string, boolean> = {};
    const hasMap = agent?.capabilities && typeof agent.capabilities === 'object';
    const stored = (agent?.capabilities as Record<string, boolean> | null | undefined) ?? null;
    CAPABILITY_OPTIONS.forEach(c => { caps[c.key] = hasMap ? (stored?.[c.key] ?? true) : true; });
    setCapabilities(caps);
    setFallbackRules(
      (agent?.fallback_rules ?? []).map((r, i) => ({ id: String(i), trigger: r.trigger, action: r.action, priority: (r.priority as FallbackRule['priority']) || 'medium' }))
    );
    setVoiceProviderId('');
    audioRef.current?.pause();
    if (audioRef.current) audioRef.current.currentTime = 0;
    setIsPlaying(false);
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [agent?.id]);

  useEffect(() => {
    return () => {
      if (audioBlobUrl.current) URL.revokeObjectURL(audioBlobUrl.current);
      audioRef.current?.pause();
    };
  }, []);

  const selectedVoiceProvider = useMemo(() =>
    voiceProviders.find(vp => vp.id === voiceProviderId),
    [voiceProviders, voiceProviderId]
  );

  const isOpenAIRealtime = selectedVoiceProvider?.name === 'openai_realtime';

  const handleVoiceProviderChange = (providerId: string) => {
    setVoiceProviderId(providerId);
    setVoiceModelId('');
    stopAudio();
  };

  const stopAudio = () => {
    audioRef.current?.pause();
    if (audioRef.current) audioRef.current.currentTime = 0;
    setIsPlaying(false);
  };

  const handlePlayPreview = async () => {
    if (isPlaying) {
      stopAudio();
      return;
    }
    if (!voiceModelId) {
      toast.error(t('aiAgentConfig.errors.selectVoice', 'Select a voice first'));
      return;
    }
    setPreviewing(true);
    try {
      const previewText = greetingScript.trim() || undefined;
      const { audio: arrayBuf, contentType } = await previewVoice(voiceModelId, previewText, undefined);
      if (audioBlobUrl.current) URL.revokeObjectURL(audioBlobUrl.current);
      const blob = new Blob([arrayBuf], { type: contentType || 'audio/mpeg' });
      const url = URL.createObjectURL(blob);
      audioBlobUrl.current = url;

      const audio = new Audio(url);
      audioRef.current = audio;
      audio.onended = () => setIsPlaying(false);
      audio.onerror = () => { setIsPlaying(false); toast.error(t('aiAgentConfig.errors.playbackFailed', 'Audio playback failed')); };
      await audio.play();
      setIsPlaying(true);
    } catch (err: unknown) {
      toast.error(err instanceof Error ? err.message : t('aiAgentConfig.errors.previewFailed', 'Preview failed'));
    } finally {
      setPreviewing(false);
    }
  };

  const handleVerifyOpenRouter = async () => {
    setVerifying(true);
    setVerifyResult(null);
    try {
      const res = await fetch('/api/ai-agents/providers/verify', { method: 'POST' });
      const json = await res.json() as { ok: boolean; error?: string; latencyMs?: number };
      setVerifyResult(json);
      if (json.ok) {
        toast.success(t('aiAgentConfig.verifyOk', 'OpenRouter key verified ({{ms}} ms)', { ms: json.latencyMs ?? 0 }));
      } else {
        toast.error(json.error || t('aiAgentConfig.errors.verifyFailed', 'Verification failed'));
      }
    } catch (err: unknown) {
      const msg = err instanceof Error ? err.message : String(err);
      setVerifyResult({ ok: false, error: msg });
      toast.error(msg);
    } finally {
      setVerifying(false);
    }
  };

  const handleSyncModels = async () => {
    setSyncing(true);
    try {
      const result = await syncOpenRouterModels();
      if (result.success) {
        toast.success(t(
          'aiAgentConfig.syncSuccessFull',
          'OpenRouter sync: fetched {{fetched}} · upserted {{upserted}} · skipped {{skipped}}',
          { fetched: result.fetched, upserted: result.upserted, skipped: result.skipped }
        ));
        await fetchProviders();
      } else {
        toast.error(result.error || t('aiAgentConfig.errors.syncFailed', 'Sync failed'));
      }
    } catch (err: unknown) {
      toast.error(err instanceof Error ? err.message : t('aiAgentConfig.errors.syncFailed', 'Sync failed'));
    } finally {
      setSyncing(false);
    }
  };

  const handleSave = async () => {
    if (!name.trim()) { toast.error(t('aiAgentConfig.errors.nameRequired', 'Agent name is required')); return; }
    setSaving(true);
    try {
      const channels: string[] = [];
      if (channelVoice) channels.push('voice');
      if (channelChat) channels.push('chat');
      if (channels.length === 0) {
        toast.error(t('aiAgentConfig.errors.channelRequired', 'At least one channel (Voice or Chat) must be enabled'));
        setSaving(false);
        return;
      }
      const payload: Partial<AiAgent> = {
        name: name.trim(),
        description: description.trim() || null,
        channels,
        llm_model_id: llmModelId || null,
        voice_model_id: voiceModelId || null,
        voice_language_code: (() => {
          const sel = selectedVoiceProvider?.models.find(vm => vm.id === voiceModelId);
          return sel?.language_code || voiceLanguageCode || null;
        })(),
        realtime_model: isOpenAIRealtime ? (realtimeModel || DEFAULT_REALTIME_MODEL) : null,
        knowledge_base_ids: knowledgeBaseIds,
        menu_category_ids: menuCategoryIds,
        vad_threshold: isOpenAIRealtime ? vadThreshold : null,
        vad_prefix_padding_ms: isOpenAIRealtime ? vadPrefixPaddingMs : null,
        vad_silence_duration_ms: isOpenAIRealtime ? vadSilenceDurationMs : null,
        system_prompt: systemPrompt.trim() || null,
        greeting_script: greetingScript.trim() || null,
        closing_script: closingScript.trim() || null,
        is_default: isDefault,
        capabilities,
        fallback_rules: fallbackRules.map(r => ({ trigger: r.trigger, action: r.action, priority: r.priority })),
      };
      let result: { agent: AiAgent };
      if (isEditing) {
        result = await updateAgent(agent!.id, payload);
      } else {
        result = await createAgent(payload);
      }
      onSaved(result.agent, !isEditing);
      toast.success(isEditing ? t('aiAgentConfig.agentUpdated', 'Agent updated') : t('aiAgentConfig.agentCreated', 'Agent created'));
      onClose();
    } catch (err: unknown) {
      toast.error((err instanceof Error ? err.message : t('aiAgentConfig.errors.saveFailed', 'Save failed')));
    } finally {
      setSaving(false);
    }
  };

  const handleAddRule = () => {
    if (!newRule.trigger.trim() || !newRule.action.trim()) return;
    setFallbackRules(prev => [...prev, { id: Date.now().toString(), ...newRule }]);
    setNewRule({ trigger: '', action: '', priority: 'medium' });
    setShowAddRule(false);
  };

  const startEditRule = (rule: FallbackRule) => {
    setEditingRuleId(rule.id);
    setEditRuleForm({ trigger: rule.trigger, action: rule.action, priority: rule.priority });
  };

  const handleUpdateRule = () => {
    if (!editingRuleId || !editRuleForm.trigger.trim() || !editRuleForm.action.trim()) return;
    setFallbackRules(prev => prev.map(r =>
      r.id === editingRuleId ? { ...r, ...editRuleForm } : r
    ));
    setEditingRuleId(null);
  };

  return (
    <div className="fixed inset-0 z-50 flex">
      <div className="flex-1 bg-black/40 backdrop-blur-sm" onClick={onClose} />
      <div className="w-full max-w-xl bg-white shadow-2xl flex flex-col h-full overflow-hidden">
        <div className="flex items-center justify-between px-5 py-4 border-b" style={{ borderColor: 'hsl(var(--border))' }}>
          <h2 className="font-bold text-lg" style={{ color: 'hsl(var(--foreground))' }}>
            {isEditing ? t('aiAgentConfig.editAgent', 'Edit Agent') : t('aiAgentConfig.newAgent', 'New Agent')}
          </h2>
          <button className="btn-ghost p-1.5" onClick={onClose}><X size={18} /></button>
        </div>

        <div className="flex-1 overflow-y-auto px-5 py-4 space-y-4">
          {/* ── Identity ── */}
          <SectionHeader title={t('aiAgentConfig.sections.identity', 'Identity')} sectionKey="identity" expanded={expandedSections} toggle={toggleSection} />
          {expandedSections.has('identity') && (
            <div className="space-y-3">
              <div>
                <label className="label-base">{t('aiAgentConfig.agentName', 'Agent Name *')}</label>
                <input className="input-base" placeholder={t('aiAgentConfig.placeholders.agentName', 'e.g. Orders Bot')} value={name} onChange={e => setName(e.target.value)} />
              </div>
              <div>
                <label className="label-base">{t('aiAgentConfig.description', 'Description')}</label>
                <input className="input-base" placeholder={t('aiAgentConfig.placeholders.description', "Short description of this agent's purpose")} value={description} onChange={e => setDescription(e.target.value)} />
              </div>
              <div className="flex items-center pt-1">
                <label className="flex items-center gap-2 text-sm cursor-pointer" style={{ color: 'hsl(var(--foreground))' }}>
                  <input type="checkbox" checked={isDefault} onChange={e => setIsDefault(e.target.checked)} />
                  {t('aiAgentConfig.setDefault', 'Set as default agent')}
                </label>
              </div>
            </div>
          )}

          {/* ── Channels ── */}
          <SectionHeader title={t('aiAgentConfig.sections.channels', 'Channels')} sectionKey="channels" expanded={expandedSections} toggle={toggleSection} />
          {expandedSections.has('channels') && (
            <div className="space-y-2">
              <p className="text-xs" style={{ color: 'hsl(var(--muted-foreground))' }}>
                {t('aiAgentConfig.channelsSubtitle', 'Enable the channels this agent should handle. At least one must be active.')}
              </p>
              <div className="flex gap-3">
                <label className="flex items-center gap-3 flex-1 p-3 rounded-lg cursor-pointer border transition-colors"
                  style={{
                    borderColor: channelVoice ? 'hsl(var(--primary))' : 'hsl(var(--border))',
                    backgroundColor: channelVoice ? 'hsl(var(--primary-light))' : 'transparent',
                  }}>
                  <input
                    type="checkbox"
                    checked={channelVoice}
                    onChange={e => setChannelVoice(e.target.checked)}
                    className="w-4 h-4 rounded"
                  />
                  <div>
                    <p className="text-sm font-medium" style={{ color: 'hsl(var(--foreground))' }}>{t('aiAgentConfig.channelVoice', 'Voice')}</p>
                    <p className="text-xs" style={{ color: 'hsl(var(--muted-foreground))' }}>{t('aiAgentConfig.channelVoiceDesc', 'Phone calls & SIP')}</p>
                  </div>
                </label>
                <label className="flex items-center gap-3 flex-1 p-3 rounded-lg cursor-pointer border transition-colors"
                  style={{
                    borderColor: channelChat ? 'hsl(var(--primary))' : 'hsl(var(--border))',
                    backgroundColor: channelChat ? 'hsl(var(--primary-light))' : 'transparent',
                  }}>
                  <input
                    type="checkbox"
                    checked={channelChat}
                    onChange={e => setChannelChat(e.target.checked)}
                    className="w-4 h-4 rounded"
                  />
                  <div>
                    <p className="text-sm font-medium" style={{ color: 'hsl(var(--foreground))' }}>{t('aiAgentConfig.channelChat', 'Chat')}</p>
                    <p className="text-xs" style={{ color: 'hsl(var(--muted-foreground))' }}>{t('aiAgentConfig.channelChatDesc', 'Web & in-app chat')}</p>
                  </div>
                </label>
              </div>
            </div>
          )}

          {/* ── LLM Provider ── */}
          <SectionHeader title={t('aiAgentConfig.sections.llm', 'LLM Provider')} sectionKey="llm" expanded={expandedSections} toggle={toggleSection} />
          {expandedSections.has('llm') && (
            <div className="space-y-2">
              <div className="flex items-center justify-between">
                <label className="label-base mb-0">{t('aiAgentConfig.llmModel', 'LLM Model')}</label>
                <button
                  className="flex items-center gap-1.5 text-xs px-2.5 py-1 rounded-lg border transition-colors"
                  style={{
                    color: 'hsl(var(--primary))',
                    borderColor: 'hsl(var(--primary))',
                    opacity: syncing ? 0.6 : 1,
                  }}
                  onClick={handleSyncModels}
                  disabled={syncing}
                  title={t('aiAgentConfig.syncModelsTitle', 'Fetch latest models from OpenRouter API')}
                >
                  <RefreshCw size={12} className={syncing ? 'animate-spin' : ''} />
                  {syncing ? t('aiAgentConfig.syncing', 'Syncing...') : t('aiAgentConfig.syncModels', 'Sync Models')}
                </button>
              </div>
              <input
                type="search"
                className="input-base"
                placeholder={t('aiAgentConfig.searchModels', 'Search models…')}
                value={llmModelFilter}
                onChange={e => setLlmModelFilter(e.target.value)}
              />
              <select className="input-base" value={llmModelId} onChange={e => setLlmModelId(e.target.value)}>
                <option value="">{t('aiAgentConfig.placeholders.selectLlm', 'Select an LLM model')}</option>
                {llmProviders.map(p => {
                  const q = llmModelFilter.trim().toLowerCase();
                  const filtered = q
                    ? p.models.filter(m => m.display_name.toLowerCase().includes(q) || (m.model_id ?? '').toLowerCase().includes(q))
                    : p.models;
                  if (filtered.length === 0) return null;
                  return (
                    <optgroup key={p.id} label={p.display_name}>
                      {filtered.map(m => (
                        <option key={m.id} value={m.id}>{m.display_name}</option>
                      ))}
                    </optgroup>
                  );
                })}
              </select>
              <div className="flex items-center gap-2">
                <button
                  type="button"
                  onClick={handleVerifyOpenRouter}
                  disabled={verifying}
                  className="text-xs px-2.5 py-1 rounded-lg border"
                  style={{ color: 'hsl(var(--primary))', borderColor: 'hsl(var(--primary))', opacity: verifying ? 0.6 : 1 }}
                  title={t('aiAgentConfig.verifyOpenRouterTitle', 'Probe your OpenRouter API key')}
                >
                  {verifying
                    ? t('aiAgentConfig.verifying', 'Verifying…')
                    : t('aiAgentConfig.verifyOpenRouter', 'Verify OpenRouter Key')}
                </button>
                {verifyResult && (
                  <span className="text-xs" style={{ color: verifyResult.ok ? 'hsl(var(--success))' : 'hsl(var(--danger))' }}>
                    {verifyResult.ok
                      ? t('aiAgentConfig.verifyOkInline', 'OK · {{ms}} ms', { ms: verifyResult.latencyMs ?? 0 })
                      : (verifyResult.error || t('aiAgentConfig.errors.verifyFailed', 'Verification failed'))}
                  </span>
                )}
              </div>
            </div>
          )}

          {/* ── Voice Provider ── */}
          <SectionHeader title={t('aiAgentConfig.sections.voice', 'Voice Provider')} sectionKey="voice" expanded={expandedSections} toggle={toggleSection} />
          {expandedSections.has('voice') && (
            <div className="space-y-3">
              <div>
                <label className="label-base">{t('aiAgentConfig.voiceProvider', 'Voice Provider')}</label>
                <select className="input-base" value={voiceProviderId} onChange={e => handleVoiceProviderChange(e.target.value)}>
                  <option value="">{t('aiAgentConfig.placeholders.selectProvider', 'Select a provider')}</option>
                  {voiceProviders.map(vp => (
                    <option key={vp.id} value={vp.id}>{vp.display_name}</option>
                  ))}
                </select>
              </div>
              {selectedVoiceProvider && (
                <div className="space-y-3">
                  <div>
                    <label className="label-base">{t('aiAgentConfig.voice', 'Voice')}</label>
                    <div className="flex gap-2">
                      <select
                        className="input-base flex-1"
                        value={voiceModelId}
                        onChange={e => { setVoiceModelId(e.target.value); stopAudio(); }}
                      >
                        <option value="">{t('aiAgentConfig.placeholders.selectVoice', 'Select a voice')}</option>
                        {selectedVoiceProvider.models.map(vm => (
                          <option key={vm.id} value={vm.id}>
                            {`${vm.display_name}${vm.gender ? ` — ${vm.gender}` : ''}${vm.language_code ? ` · ${vm.language_code}` : ''}`}
                          </option>
                        ))}
                      </select>
                      <button
                        onClick={handlePlayPreview}
                        disabled={previewing || !voiceModelId}
                        title={isPlaying ? t('aiAgentConfig.stopPreview', 'Stop preview') : t('aiAgentConfig.playPreview', 'Play voice preview')}
                        className="flex items-center gap-1.5 px-3 py-2 rounded-lg border text-sm font-medium transition-colors shrink-0"
                        style={{
                          color: isPlaying ? 'hsl(var(--danger))' : 'hsl(var(--primary))',
                          borderColor: isPlaying ? 'hsl(var(--danger))' : 'hsl(var(--primary))',
                          opacity: !voiceModelId ? 0.4 : 1,
                          backgroundColor: 'transparent',
                          cursor: !voiceModelId ? 'not-allowed' : 'pointer',
                        }}
                      >
                        {previewing
                          ? <span className="w-3.5 h-3.5 border-2 border-current border-t-transparent rounded-full animate-spin" />
                          : isPlaying
                            ? <Square size={13} fill="currentColor" />
                            : <Play size={13} fill="currentColor" />
                        }
                        {previewing ? t('aiAgentConfig.loading', 'Loading') : isPlaying ? t('aiAgentConfig.stop', 'Stop') : t('aiAgentConfig.play', 'Play')}
                      </button>
                    </div>
                  </div>
                  {(() => {
                    const selVoice = selectedVoiceProvider.models.find(vm => vm.id === voiceModelId);
                    const lang = selVoice?.language_code ?? '';
                    if (lang && !lang.toLowerCase().startsWith('en')) {
                      return (
                        <div>
                          <label className="label-base">{t('aiAgentConfig.voiceLanguage', 'Voice Language')}</label>
                          <input className="input-base" value={lang} readOnly disabled />
                          <p className="text-xs mt-1" style={{ color: 'hsl(var(--muted-foreground))' }}>
                            {t('aiAgentConfig.voiceLanguageNote', 'This voice speaks {{lang}}; the agent will respond in this language.', { lang })}
                          </p>
                        </div>
                      );
                    }
                    return null;
                  })()}
                  {isOpenAIRealtime && (
                    <div>
                      <label className="label-base">{t('aiAgentConfig.realtimeModel', 'Realtime Model')}</label>
                      <select
                        className="input-base"
                        value={realtimeModel}
                        onChange={e => setRealtimeModel(e.target.value)}
                      >
                        {REALTIME_MODELS.map(rm => (
                          <option key={rm} value={rm}>
                            {t(`aiAgentConfig.realtimeModels.${rm}`, rm)}
                          </option>
                        ))}
                      </select>
                    </div>
                  )}
                </div>
              )}
            </div>
          )}

          {/* ── Voice Activity Detection ── */}
          {isOpenAIRealtime && (
            <>
              <SectionHeader title={t('aiAgentConfig.sections.vad', 'Voice Activity Detection')} sectionKey="vad" expanded={expandedSections} toggle={toggleSection} />
              {expandedSections.has('vad') && (
                <div className="space-y-4">
                  <p className="text-xs" style={{ color: 'hsl(var(--muted-foreground))' }}>
                    {t('aiAgentConfig.vadSubtitle', "Controls how the AI detects when you've finished speaking. Lower threshold = more sensitive. Longer silence = waits more before responding.")}
                  </p>
                  <div>
                    <div className="flex items-center justify-between mb-1">
                      <label className="label-base mb-0">{t('aiAgentConfig.detectionThreshold', 'Detection Threshold')}</label>
                      <span className="text-xs font-mono" style={{ color: 'hsl(var(--primary))' }}>{vadThreshold.toFixed(2)}</span>
                    </div>
                    <input
                      type="range"
                      min={0}
                      max={1}
                      step={0.05}
                      value={vadThreshold}
                      onChange={e => setVadThreshold(parseFloat(e.target.value))}
                      className="w-full accent-primary"
                    />
                    <div className="flex justify-between text-xs mt-0.5" style={{ color: 'hsl(var(--muted-foreground))' }}>
                      <span>{t('aiAgentConfig.moreSensitive', 'More sensitive (0)')}</span>
                      <span>{t('aiAgentConfig.lessSensitive', 'Less sensitive (1)')}</span>
                    </div>
                  </div>
                  <div className="grid grid-cols-2 gap-3">
                    <div>
                      <label className="label-base">{t('aiAgentConfig.prefixPadding', 'Prefix Padding (ms)')}</label>
                      <input
                        type="number"
                        className="input-base"
                        min={0}
                        max={1000}
                        step={50}
                        value={vadPrefixPaddingMs}
                        onChange={e => setVadPrefixPaddingMs(Math.max(0, Math.min(1000, parseInt(e.target.value, 10) || 0)))}
                      />
                      <p className="text-xs mt-0.5" style={{ color: 'hsl(var(--muted-foreground))' }}>{t('aiAgentConfig.prefixPaddingDesc', 'Audio kept before speech')}</p>
                    </div>
                    <div>
                      <label className="label-base">{t('aiAgentConfig.silenceDuration', 'Silence Duration (ms)')}</label>
                      <input
                        type="number"
                        className="input-base"
                        min={200}
                        max={3000}
                        step={100}
                        value={vadSilenceDurationMs}
                        onChange={e => setVadSilenceDurationMs(Math.max(200, Math.min(3000, parseInt(e.target.value, 10) || 600)))}
                      />
                      <p className="text-xs mt-0.5" style={{ color: 'hsl(var(--muted-foreground))' }}>{t('aiAgentConfig.silenceDurationDesc', 'Pause before turn ends')}</p>
                    </div>
                  </div>
                </div>
              )}
            </>
          )}

          {/* ── Scripts ── */}
          <SectionHeader title={t('aiAgentConfig.sections.scripts', 'Scripts')} sectionKey="scripts" expanded={expandedSections} toggle={toggleSection} />
          {expandedSections.has('scripts') && (
            <div className="space-y-3">
              <div>
                <label className="label-base">{t('aiAgentConfig.greetingScript', 'Greeting Script')}</label>
                <textarea className="input-base resize-none w-full" rows={3} placeholder={t('aiAgentConfig.placeholders.greetingScript', "Hello! Welcome to our restaurant...")}
                  value={greetingScript} onChange={e => setGreetingScript(e.target.value)} />
              </div>
              <div>
                <label className="label-base">{t('aiAgentConfig.closingScript', 'Closing Script')}</label>
                <textarea className="input-base resize-none w-full" rows={3} placeholder={t('aiAgentConfig.placeholders.closingScript', "Thank you for choosing us...")}
                  value={closingScript} onChange={e => setClosingScript(e.target.value)} />
              </div>
              <div>
                <label className="label-base">{t('aiAgentConfig.systemPrompt', 'System Prompt')}</label>
                <textarea className="input-base resize-none w-full" rows={5}
                  placeholder={t('aiAgentConfig.placeholders.systemPrompt', "You are a helpful restaurant assistant. Always be polite and focus on menu recommendations...")}
                  value={systemPrompt} onChange={e => setSystemPrompt(e.target.value)} />
              </div>
            </div>
          )}

          {/* ── Capabilities ── */}
          <SectionHeader title={t('aiAgentConfig.sections.capabilities', 'Capabilities')} sectionKey="capabilities" expanded={expandedSections} toggle={toggleSection} />
          {expandedSections.has('capabilities') && (
            <div className="space-y-2">
              {CAPABILITY_OPTIONS.map(cap => (
                <div key={cap.key} className="flex items-center justify-between p-3 rounded-lg" style={{ backgroundColor: 'hsl(var(--muted))' }}>
                  <span className="text-sm" style={{ color: 'hsl(var(--foreground))' }}>{cap.label}</span>
                  <button onClick={() => setCapabilities(prev => ({ ...prev, [cap.key]: !prev[cap.key] }))}>
                    <div className="w-10 h-6 rounded-full transition-colors flex items-center px-0.5"
                      style={{ backgroundColor: capabilities[cap.key] ? 'hsl(var(--success))' : 'hsl(var(--muted-foreground))' }}>
                      <span className="w-5 h-5 bg-white rounded-full shadow transition-transform"
                        style={{ transform: capabilities[cap.key] ? 'translateX(16px)' : 'translateX(0)' }} />
                    </div>
                  </button>
                </div>
              ))}
            </div>
          )}

          {/* ── Knowledge Base Scope ── */}
          <SectionHeader title={t('aiAgentConfig.sections.knowledge', 'Knowledge Base')} sectionKey="knowledge" expanded={expandedSections} toggle={toggleSection} />
          {expandedSections.has('knowledge') && (
            <div className="space-y-2">
              <p className="text-xs" style={{ color: 'hsl(var(--muted-foreground))' }}>
                {t('aiAgentConfig.knowledgeSubtitle', 'Limit which knowledge base entries this agent can search. Leave empty to use the entire restaurant knowledge base.')}
              </p>
              {kbOptions.length === 0 ? (
                <p className="text-xs italic" style={{ color: 'hsl(var(--muted-foreground))' }}>
                  {t('aiAgentConfig.noKbEntries', 'No knowledge base entries yet — add entries from the Knowledge Base page.')}
                </p>
              ) : (
                <div className="max-h-48 overflow-y-auto border rounded-lg p-2 space-y-1" style={{ borderColor: 'hsl(var(--border))' }}>
                  {kbOptions.map(kb => {
                    const checked = knowledgeBaseIds.includes(kb.id);
                    return (
                      <label key={kb.id} className="flex items-center gap-2 text-sm cursor-pointer p-1 rounded hover:bg-muted" style={{ color: 'hsl(var(--foreground))' }}>
                        <input
                          type="checkbox"
                          checked={checked}
                          onChange={e => setKnowledgeBaseIds(prev =>
                            e.target.checked ? [...prev, kb.id] : prev.filter(id => id !== kb.id)
                          )}
                        />
                        <span className="truncate flex-1">{kb.title}</span>
                        {kb.type && <span className="text-xs" style={{ color: 'hsl(var(--muted-foreground))' }}>{kb.type}</span>}
                      </label>
                    );
                  })}
                </div>
              )}
            </div>
          )}

          {/* ── Menu Category Scope ── */}
          <SectionHeader title={t('aiAgentConfig.sections.menuScope', 'Menu Category Scope')} sectionKey="menuScope" expanded={expandedSections} toggle={toggleSection} />
          {expandedSections.has('menuScope') && (
            <div className="space-y-2">
              <p className="text-xs" style={{ color: 'hsl(var(--muted-foreground))' }}>
                {t('aiAgentConfig.menuScopeSubtitle', 'Choose whether this agent can sell from the entire menu or only a specific set of categories.')}
              </p>
              <div className="flex gap-2 text-xs">
                <label className="flex items-center gap-1 cursor-pointer" style={{ color: 'hsl(var(--foreground))' }}>
                  <input
                    type="radio"
                    name="menu-scope-mode"
                    checked={menuCategoryIds.length === 0}
                    onChange={() => setMenuCategoryIds([])}
                  />
                  {t('aiAgentConfig.menuScopeAll', 'All menu items')}
                </label>
                <label className="flex items-center gap-1 cursor-pointer" style={{ color: 'hsl(var(--foreground))' }}>
                  <input
                    type="radio"
                    name="menu-scope-mode"
                    checked={menuCategoryIds.length > 0}
                    onChange={() => {
                      if (menuCategoryIds.length === 0 && menuCategoryOptions[0]) {
                        setMenuCategoryIds([menuCategoryOptions[0].id]);
                      }
                    }}
                    disabled={menuCategoryOptions.length === 0}
                  />
                  {t('aiAgentConfig.menuScopeSpecific', 'Specific categories')}
                </label>
              </div>
              {menuCategoryOptions.length === 0 ? (
                <p className="text-xs italic" style={{ color: 'hsl(var(--muted-foreground))' }}>
                  {t('aiAgentConfig.noMenuCategories', 'No menu categories configured.')}
                </p>
              ) : menuCategoryIds.length > 0 && (
                <div className="max-h-48 overflow-y-auto border rounded-lg p-2 space-y-1" style={{ borderColor: 'hsl(var(--border))' }}>
                  {menuCategoryOptions.map(cat => {
                    const checked = menuCategoryIds.includes(cat.id);
                    return (
                      <label key={cat.id} className="flex items-center gap-2 text-sm cursor-pointer p-1 rounded hover:bg-muted" style={{ color: 'hsl(var(--foreground))' }}>
                        <input
                          type="checkbox"
                          checked={checked}
                          onChange={e => setMenuCategoryIds(prev =>
                            e.target.checked ? [...prev, cat.id] : prev.filter(id => id !== cat.id)
                          )}
                        />
                        <span className="truncate flex-1">{cat.name}</span>
                      </label>
                    );
                  })}
                </div>
              )}
            </div>
          )}

          {/* ── Fallback Rules ── */}
          <SectionHeader title={t('aiAgentConfig.sections.fallback', 'Fallback Rules')} sectionKey="fallback" expanded={expandedSections} toggle={toggleSection} />
          {expandedSections.has('fallback') && (
            <div className="space-y-3">
              <div className="flex justify-end">
                <button className="btn-ghost text-xs px-2 py-1 flex items-center gap-1" style={{ color: 'hsl(var(--primary))' }}
                  onClick={() => setShowAddRule(true)}>
                  <Plus size={13} /> {t('aiAgentConfig.addRule', 'Add Rule')}
                </button>
              </div>

              {showAddRule && (
                <RuleForm
                  rule={newRule}
                  onChange={setNewRule}
                  onSave={handleAddRule}
                  onCancel={() => setShowAddRule(false)}
                  saveLabel={t('aiAgentConfig.add', 'Add')}
                  t={t}
                />
              )}

              {fallbackRules.length === 0 && !showAddRule && (
                <p className="text-xs text-center py-4" style={{ color: 'hsl(var(--muted-foreground))' }}>
                  {t('aiAgentConfig.noFallbackRules', 'No fallback rules configured. Add rules to handle edge cases.')}
                </p>
              )}

              {fallbackRules.map(rule => (
                editingRuleId === rule.id ? (
                  <RuleForm
                    key={rule.id}
                    rule={editRuleForm}
                    onChange={setEditRuleForm}
                    onSave={handleUpdateRule}
                    onCancel={() => setEditingRuleId(null)}
                    saveLabel={t('aiAgentConfig.save', 'Save')}
                    t={t}
                  />
                ) : (
                  <div key={rule.id} className="flex items-center gap-2 p-3 rounded-lg" style={{ backgroundColor: 'hsl(var(--muted))' }}>
                    <div className="flex-1 min-w-0">
                      <p className="text-sm font-medium truncate" style={{ color: 'hsl(var(--foreground))' }}>{rule.trigger}</p>
                      <p className="text-xs truncate" style={{ color: 'hsl(var(--muted-foreground))' }}>{rule.action}</p>
                    </div>
                    <span className={`badge ${PRIORITY_CLASS[rule.priority]} text-xs`}>{t(`aiAgentConfig.priorities.${rule.priority}`, rule.priority)}</span>
                    <button className="btn-ghost p-1" style={{ color: 'hsl(var(--primary))' }}
                      onClick={() => startEditRule(rule)}>
                      <Pencil size={12} />
                    </button>
                    <button className="btn-ghost p-1" style={{ color: 'hsl(var(--danger))' }}
                      onClick={() => setFallbackRules(prev => prev.filter(r => r.id !== rule.id))}>
                      <Trash2 size={13} />
                    </button>
                  </div>
                )
              ))}
            </div>
          )}

          <div className="lg:hidden pt-4">
            <AgentPreview name={name} greeting={greetingScript} systemPrompt={systemPrompt} closing={closingScript} />
          </div>

          {/* ── Test Agent (live chat) — works for both saved and unsaved drafts ── */}
          <SectionHeader title={t('aiAgentConfig.sections.test', 'Test Agent')} sectionKey="test" expanded={expandedSections} toggle={toggleSection} />
          {expandedSections.has('test') && (
            <TestAgentPanel
              t={t}
              draft={{
                agentId: agent?.id ?? null,
                systemPrompt: systemPrompt.trim() || undefined,
                greetingScript: greetingScript.trim() || undefined,
                closingScript: closingScript.trim() || undefined,
                fallbackRules: fallbackRules.map(r => ({ trigger: r.trigger, action: r.action, priority: r.priority })),
                llmModelId: llmModelId || null,
                branchId: agent?.branch_id ?? null,
                capabilities,
                menuCategoryIds,
                knowledgeBaseIds,
              }}
            />
          )}
        </div>

        <div className="px-5 py-4 border-t flex gap-3" style={{ borderColor: 'hsl(var(--border))' }}>
          <button className="btn-secondary flex-1" onClick={onClose}>{t('aiAgentConfig.cancel', 'Cancel')}</button>
          <DemoDisabled className="flex-1">
            <button className="btn-primary w-full" onClick={handleSave} disabled={saving}>
              {saving ? <span className="w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin" /> : <Save size={15} />}
              {saving ? t('aiAgentConfig.saving', 'Saving...') : isEditing ? t('aiAgentConfig.updateAgent', 'Update Agent') : t('aiAgentConfig.createAgent', 'Create Agent')}
            </button>
          </DemoDisabled>
        </div>
      </div>
    </div>
  );
}

interface TestAgentDraft {
  agentId?: string | null;
  systemPrompt?: string;
  greetingScript?: string;
  closingScript?: string;
  fallbackRules?: Array<{ trigger: string; action: string; priority: string }>;
  llmModelId?: string | null;
  branchId?: string | null;
  capabilities?: Record<string, boolean> | null;
  menuCategoryIds?: string[] | null;
  knowledgeBaseIds?: string[] | null;
}

function TestAgentPanel({ t, draft }: { t: (k: string, fallback: string) => string; draft: TestAgentDraft }) {
  const draftRef = useRef(draft);
  draftRef.current = draft;
  const [history, setHistory] = useState<Array<{ role: 'user' | 'assistant'; content: string }>>([]);
  const [input, setInput] = useState('');
  const [busy, setBusy] = useState(false);

  const send = async () => {
    const text = input.trim();
    if (!text || busy) return;
    const next = [...history, { role: 'user' as const, content: text }];
    setHistory(next);
    setInput('');
    setBusy(true);
    try {
      const res = await fetch('/api/ai-agents/test-chat', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ messages: next, draft: draftRef.current }),
      });
      const json = await res.json() as { reply?: string; error?: string };
      if (!res.ok) {
        toast.error(json.error || t('aiAgentConfig.errors.testFailed', 'Test chat failed'));
        return;
      }
      setHistory([...next, { role: 'assistant', content: json.reply || '' }]);
    } catch (err: unknown) {
      toast.error(err instanceof Error ? err.message : t('aiAgentConfig.errors.testFailed', 'Test chat failed'));
    } finally {
      setBusy(false);
    }
  };

  return (
    <div className="space-y-2">
      <div
        className="border rounded-lg p-3 max-h-64 overflow-y-auto space-y-2 text-sm"
        style={{ borderColor: 'hsl(var(--border))', backgroundColor: 'hsl(var(--muted) / 0.3)' }}
      >
        {history.length === 0 && (
          <p className="text-xs italic" style={{ color: 'hsl(var(--muted-foreground))' }}>
            {t('aiAgentConfig.testEmpty', 'Send a test message to chat with this agent — orders/bookings created here are real.')}
          </p>
        )}
        {history.map((m, i) => (
          <div key={i} className={`flex ${m.role === 'user' ? 'justify-end' : 'justify-start'}`}>
            <div
              className="rounded-lg px-3 py-1.5 max-w-[85%] whitespace-pre-wrap"
              style={{
                backgroundColor: m.role === 'user' ? 'hsl(var(--primary))' : 'hsl(var(--card))',
                color: m.role === 'user' ? 'hsl(var(--primary-foreground))' : 'hsl(var(--foreground))',
                border: m.role === 'assistant' ? '1px solid hsl(var(--border))' : 'none',
              }}
            >
              {m.content}
            </div>
          </div>
        ))}
        {busy && (
          <p className="text-xs" style={{ color: 'hsl(var(--muted-foreground))' }}>
            {t('aiAgentConfig.testThinking', 'Thinking…')}
          </p>
        )}
      </div>
      <div className="flex gap-2">
        <input
          className="input-base flex-1"
          placeholder={t('aiAgentConfig.testPlaceholder', 'Type a test message…')}
          value={input}
          onChange={e => setInput(e.target.value)}
          onKeyDown={e => { if (e.key === 'Enter') { e.preventDefault(); void send(); } }}
          disabled={busy}
        />
        <button className="btn-primary" onClick={() => void send()} disabled={busy || !input.trim()}>
          {t('aiAgentConfig.testSend', 'Send')}
        </button>
      </div>
    </div>
  );
}

function SectionHeader({ title, sectionKey, expanded, toggle }: {
  title: string; sectionKey: string; expanded: Set<string>; toggle: (k: string) => void;
}) {
  const isOpen = expanded.has(sectionKey);
  return (
    <button onClick={() => toggle(sectionKey)}
      className="flex items-center gap-2 w-full py-2 border-b"
      style={{ borderColor: 'hsl(var(--border))' }}>
      {isOpen ? <ChevronDown size={14} /> : <ChevronRight size={14} />}
      <span className="text-xs font-semibold uppercase tracking-wider" style={{ color: 'hsl(var(--muted-foreground))' }}>
        {title}
      </span>
    </button>
  );
}

function RuleForm({ rule, onChange, onSave, onCancel, saveLabel, t }: {
  rule: { trigger: string; action: string; priority: 'high' | 'medium' | 'low' };
  onChange: (r: { trigger: string; action: string; priority: 'high' | 'medium' | 'low' }) => void;
  onSave: () => void;
  onCancel: () => void;
  saveLabel: string;
  t: (key: string, fallback: string) => string;
}) {
  return (
    <div className="border rounded-xl p-3 space-y-2" style={{ borderColor: 'hsl(var(--primary))' }}>
      <div className="grid grid-cols-1 sm:grid-cols-3 gap-2">
        <input className="input-base text-sm" placeholder={t('aiAgentConfig.placeholders.fallbackTrigger', 'Trigger condition')}
          value={rule.trigger} onChange={e => onChange({ ...rule, trigger: e.target.value })} autoFocus />
        <input className="input-base text-sm" placeholder={t('aiAgentConfig.placeholders.fallbackAction', 'Action to take')}
          value={rule.action} onChange={e => onChange({ ...rule, action: e.target.value })} />
        <select className="input-base text-sm" value={rule.priority}
          onChange={e => onChange({ ...rule, priority: e.target.value as 'high' | 'medium' | 'low' })}>
          <option value="high">{t('aiAgentConfig.priorities.high', 'High')}</option>
          <option value="medium">{t('aiAgentConfig.priorities.medium', 'Medium')}</option>
          <option value="low">{t('aiAgentConfig.priorities.low', 'Low')}</option>
        </select>
      </div>
      <div className="flex gap-2">
        <button className="btn-primary text-xs py-1.5 flex-1" onClick={onSave}>
          <Check size={12} /> {saveLabel}
        </button>
        <button className="btn-secondary text-xs py-1.5" onClick={onCancel}>
          <X size={12} /> {t('aiAgentConfig.cancel', 'Cancel')}
        </button>
      </div>
    </div>
  );
}
