/* ============================================================
   WebServicesTab.jsx — Web Servis Entegrasyonu Yönetim Ekranı
   ============================================================ */
window.WebServicesTab = function WebServicesTab({ toast }) {
  const { useState, useEffect, useCallback } = React;

  /* ── State ─────────────────────────────────────────────── */
  const [authList, setAuthList] = useState([]);
  const [serviceList, setServiceList] = useState([]);
  const [logs, setLogs] = useState([]);
  const [loading, setLoading] = useState(true);

  // Modal state
  const [authModal, setAuthModal] = useState(null); // null | 'new' | {id,...}
  const [svcModal, setSvcModal] = useState(null); // null | 'new' | {id,...}
  const [testPanel, setTestPanel] = useState(null); // null | service obj
  const [authTestPanel, setAuthTestPanel] = useState(null); // null | auth obj
  const [logsPanel, setLogsPanel] = useState(null); // null | service obj
  const [activeSection, setActiveSection] = useState('services'); // 'services' | 'auth'

  /* ── Fetch ─────────────────────────────────────────────── */
  const load = useCallback(async () => {
    setLoading(true);
    const [a, s] = await Promise.all([
      apiFetch('/api/ws/auth'),
      apiFetch('/api/ws/services'),
    ]);
    setAuthList(a || []);
    setServiceList(s || []);
    setLoading(false);
  }, []);

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

  /* ── Auth CRUD ─────────────────────────────────────────── */
  const saveAuth = async (data) => {
    const isEdit = !!data.id;
    const url = isEdit ? `/api/ws/auth/${data.id}` : '/api/ws/auth';
    const method = isEdit ? 'PUT' : 'POST';
    const res = await apiFetch(url, { method, body: JSON.stringify(data) });
    if (res?.id) {
      toast(isEdit ? 'Auth güncellendi' : 'Auth oluşturuldu', 'success');
      setAuthModal(null);
      load();
    }
  };

  const deleteAuth = async (id) => {
    if (!confirm('Auth konfigürasyonu silinsin mi?')) return;
    await apiFetch(`/api/ws/auth/${id}`, { method: 'DELETE' });
    toast('Auth silindi', 'success');
    load();
  };

  /* ── Service CRUD ──────────────────────────────────────── */
  const saveSvc = async (data) => {
    const isEdit = !!data.id;
    const url = isEdit ? `/api/ws/services/${data.id}` : '/api/ws/services';
    const method = isEdit ? 'PUT' : 'POST';
    const res = await apiFetch(url, { method, body: JSON.stringify(data) });
    if (res?.id) {
      toast(isEdit ? 'Servis güncellendi' : 'Servis oluşturuldu', 'success');
      setSvcModal(null);
      load();
    }
  };

  const deleteSvc = async (id) => {
    if (!confirm('Servis konfigürasyonu silinsin mi?')) return;
    await apiFetch(`/api/ws/services/${id}`, { method: 'DELETE' });
    toast('Servis silindi', 'success');
    load();
  };

  const toggleActive = async (svc) => {
    await apiFetch(`/api/ws/services/${svc.id}`, {
      method: 'PUT',
      body: JSON.stringify({ ...svc, is_active: !svc.is_active }),
    });
    load();
  };

  /* ── Logs ──────────────────────────────────────────────── */
  const openLogs = async (svc) => {
    setLogsPanel(svc);
    const data = await apiFetch(`/api/ws/logs?svc_id=${svc.id}&limit=50`);
    setLogs(data || []);
  };

  /* ── Render ────────────────────────────────────────────── */
  const AUTH_TYPE_LABELS = {
    oauth2_client_credentials: 'OAuth2 Client Credentials',
    oauth2_password: 'OAuth2 Password',
    api_key_header: 'API Key (Header)',
    api_key_query: 'API Key (Query)',
    basic_auth: 'Basic Auth',
    bearer_static: 'Static Bearer Token',
    custom_header: 'Custom Header',
    none: 'Auth Yok',
  };
  const METHOD_COLORS = { GET:'#10b981', POST:'#6366f1', PUT:'#f59e0b', PATCH:'#8b5cf6' };
  const CT_LABELS = { json:'REST/JSON', soap:'SOAP/XML', xml:'REST/XML', form:'Form', multipart:'Multipart' };

  return (
    <div style={{ padding: '0 0 40px' }}>
      {/* ── Page Header ── */}
      <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:24 }}>
        <div>
          <h2 style={{ margin:0, fontSize:22, fontWeight:600 }}>Web Servis Entegrasyonları</h2>
          <p style={{ margin:'4px 0 0', color:'var(--text-dim)', fontSize:14 }}>
            IVR akışlarından dış servislere bağlantı kurun — kod yazmadan
          </p>
        </div>
        <div style={{ display:'flex', gap:10 }}>
          <button
            className={`btn ${activeSection==='services' ? 'btn-primary' : 'btn-secondary'}`}
            onClick={() =>setActiveSection('services')}
          >Servisler ({serviceList.length})</button>
          <button
            className={`btn ${activeSection==='auth' ? 'btn-primary' : 'btn-secondary'}`}
            onClick={() =>setActiveSection('auth')}
          >Auth Konfigürasyonları ({authList.length})</button>
        </div>
      </div>

      {loading ? (
        <div style={{ textAlign:'center', padding:60, color:'var(--text-dim)' }}>Yükleniyor…</div>
      ) : activeSection === 'auth' ? (
        /* ════════════ AUTH SECTION ════════════ */
        <div>
          <div style={{ display:'flex', justifyContent:'flex-end', marginBottom:16 }}>
            <button className="btn btn-primary" onClick={() =>setAuthModal({})}>
              + Yeni Auth Konfigürasyonu
            </button>
          </div>
          {authList.length === 0 ? (
            <EmptyState icon="" text="Henüz auth konfigürasyonu yok" />
          ) : (
            <div style={{ display:'grid', gridTemplateColumns:'repeat(auto-fill,minmax(340px,1fr))', gap:16 }}>
              {authList.map(a => (
                <AuthCard key={a.id} auth={a}
                  onEdit={() =>setAuthModal(a)}
                  onDelete={() =>deleteAuth(a.id)}
                  onTest={() =>setAuthTestPanel(a)}
                  labels={AUTH_TYPE_LABELS}
                />
              ))}
            </div>
          )}
        </div>
      ) : (
        /* ════════════ SERVICES SECTION ════════════ */
        <div>
          <div style={{ display:'flex', justifyContent:'flex-end', marginBottom:16 }}>
            <button className="btn btn-primary" onClick={() =>setSvcModal({})}>
              + Yeni Servis
            </button>
          </div>
          {serviceList.length === 0 ? (
            <EmptyState icon="" text="Henüz servis tanımlanmamış" sub="IVR akışlarınızda kullanmak için servis ekleyin" />
          ) : (
            <div style={{ display:'flex', flexDirection:'column', gap:14 }}>
              {serviceList.map(s => (
                <ServiceCard key={s.id} svc={s}
                  authName={authList.find(a =>a.id === s.auth_config_id)?.name}
                  methodColors={METHOD_COLORS}
                  ctLabels={CT_LABELS}
                  onEdit={() =>setSvcModal(s)}
                  onDelete={() =>deleteSvc(s.id)}
                  onTest={() =>setTestPanel(s)}
                  onLogs={() =>openLogs(s)}
                  onToggle={() =>toggleActive(s)}
                />
              ))}
            </div>
          )}
        </div>
      )}

      {/* ── Modals ── */}
      {authModal !== null && (
        <AuthModal
          initial={authModal}
          onSave={saveAuth}
          onClose={() =>setAuthModal(null)}
          typeLabels={AUTH_TYPE_LABELS}
        />
      )}
      {svcModal !== null && (
        <ServiceModal
          initial={svcModal}
          authList={authList}
          ctLabels={CT_LABELS}
          onSave={saveSvc}
          onClose={() =>setSvcModal(null)}
        />
      )}
      {testPanel && (
        <TestPanel
          svc={testPanel}
          onClose={() =>setTestPanel(null)}
          toast={toast}
        />
      )}
      {authTestPanel && (
        <AuthTestPanel
          auth={authTestPanel}
          onClose={() =>setAuthTestPanel(null)}
          toast={toast}
        />
      )}
      {logsPanel && (
        <WsLogsPanel
          svc={logsPanel}
          logs={logs}
          onClose={() => { setLogsPanel(null); setLogs([]); }}
        />
      )}
    </div>
  );
};

/* ============================================================
   AUTH CARD
   ============================================================ */
function AuthCard({ auth, onEdit, onDelete, onTest, labels }) {
  const TYPE_ICONS = {
    oauth2_client_credentials: 'OAuth2',
    oauth2_password: 'OAuth2',
    api_key_header: 'Key',
    api_key_query: 'Key',
    basic_auth: 'Basic',
    bearer_static: 'Bearer',
    custom_header: 'Custom',
    none: 'None',
  };
  return (
    <div className="card" style={{ padding:18 }}>
      <div style={{ display:'flex', justifyContent:'space-between', alignItems:'flex-start' }}>
        <div>
          <div style={{ fontSize:15, fontWeight:600 }}>
            {auth.name}
          </div>
          <div style={{ marginTop:6 }}>
            <span style={{
              background:'var(--bg-hover)', borderRadius:6, padding:'2px 10px',
              fontSize:12, color:'var(--text-dim)', fontWeight:500
            }}>
              {labels[auth.auth_type] || auth.auth_type}
            </span>
          </div>
          {auth.description && (
            <div style={{ marginTop:8, fontSize:13, color:'var(--text-dim)' }}>{auth.description}</div>
          )}
          {auth.token_url && (
            <div style={{ marginTop:6, fontSize:12, color:'var(--text-dim)', wordBreak:'break-all' }}>
               {auth.token_url}
            </div>
          )}
        </div>
        <div style={{ display:'flex', gap:6 }}>
          <button className="btn btn-primary" style={{ padding:'4px 10px', fontSize:13 }} onClick={onTest}>Test Et</button>
          <button className="btn btn-secondary" style={{ padding:'4px 10px', fontSize:13 }} onClick={onEdit}>Düzenle</button>
          <button className="btn btn-danger" style={{ padding:'4px 10px', fontSize:13 }} onClick={onDelete}>Sil</button>
        </div>
      </div>
    </div>
  );
}

/* ============================================================
   SERVICE CARD
   ============================================================ */
function ServiceCard({ svc, authName, methodColors, ctLabels, onEdit, onDelete, onTest, onLogs, onToggle }) {
  return (
    <div className="card" style={{ padding:18, opacity: svc.is_active ? 1 : 0.6 }}>
      <div style={{ display:'flex', justifyContent:'space-between', alignItems:'flex-start', gap:16 }}>
        {/* Sol: Bilgiler */}
        <div style={{ flex:1, minWidth:0 }}>
          <div style={{ display:'flex', alignItems:'center', gap:10, flexWrap:'wrap' }}>
            <span style={{ fontSize:15, fontWeight:600 }}>{svc.name}</span>
            {/* Method badge */}
            <span style={{
              background: methodColors[svc.method] || '#6366f1',
              color:'#fff', borderRadius:5, padding:'1px 8px', fontSize:11, fontWeight:600
            }}>{svc.method}</span>
            {/* Content type badge */}
            <span style={{
              background:'var(--bg-hover)', borderRadius:5, padding:'1px 8px',
              fontSize:11, color:'var(--text-dim)', fontWeight:600
            }}>{ctLabels[svc.content_type] || svc.content_type}</span>
            {/* Auth badge */}
            {authName && (
              <span style={{
                background:'rgba(99,102,241,0.1)', color:'#6366f1', borderRadius:5,
                padding:'1px 8px', fontSize:11, fontWeight:600
              }}> {authName}</span>
            )}
            {svc.trigger_on_call_start && !svc.background_lookup && (
              <span style={{ background:'rgba(245,158,11,0.12)', color:'#d97706', borderRadius:5, padding:'1px 8px', fontSize:11, fontWeight:600 }}>
                Çağrı başı sorgula
              </span>
            )}
            {svc.trigger_on_call_start && svc.background_lookup && (
              <span style={{ background:'rgba(99,102,241,0.12)', color:'#6366f1', borderRadius:5, padding:'1px 8px', fontSize:11, fontWeight:600 }}>
                Arka planda sorgula
              </span>
            )}
            {!svc.is_active && (
              <span style={{ background:'#fef2f2', color:'#ef4444', borderRadius:5, padding:'1px 8px', fontSize:11 }}>Pasif</span>
            )}
          </div>

          {/* URL */}
          <div style={{
            marginTop:8, fontSize:13, color:'var(--text-dim)', fontFamily:'monospace',
            background:'var(--bg-hover)', borderRadius:6, padding:'4px 10px',
            wordBreak:'break-all'
          }}>
            {svc.url}
          </div>

          {/* Response mappings özeti */}
          {svc.response_mappings?.length > 0 && (
            <div style={{ marginTop:8, display:'flex', flexWrap:'wrap', gap:6 }}>
              {svc.response_mappings.map((m, i) => (
                <span key={i} style={{
                  background:'rgba(16,185,129,0.1)', color:'#059669', borderRadius:5,
                  padding:'1px 8px', fontSize:11, fontWeight:500
                }}>
                  {m.path} → <b>{m.variable}</b>
                </span>
              ))}
            </div>
          )}

          {svc.description && (
            <div style={{ marginTop:6, fontSize:13, color:'var(--text-dim)' }}>{svc.description}</div>
          )}
        </div>

        {/* Sağ: Butonlar */}
        <div style={{ display:'flex', flexDirection:'column', gap:6, flexShrink:0 }}>
          <button className="btn btn-primary" style={{ fontSize:13, padding:'5px 12px' }} onClick={onTest}>Test Et</button>
          <button className="btn btn-secondary" style={{ fontSize:13, padding:'5px 12px' }} onClick={onEdit}>Düzenle</button>
          <button className="btn btn-secondary" style={{ fontSize:13, padding:'5px 12px' }} onClick={onLogs}>Loglar</button>
          <button className="btn btn-secondary" style={{ fontSize:13, padding:'5px 12px' }} onClick={onToggle}>
            {svc.is_active ? 'Pasif' : 'Aktif'}
          </button>
          <button className="btn btn-danger" style={{ fontSize:13, padding:'5px 12px' }} onClick={onDelete}>Sil</button>
        </div>
      </div>
    </div>
  );
}

/* ============================================================
   AUTH MODAL
   ============================================================ */
function AuthModal({ initial, onSave, onClose, typeLabels }) {
  const { useState } = React;
  const [form, setForm] = useState({
    name: '', description: '', auth_type: 'oauth2_client_credentials',
    token_url: '', client_id: '', client_secret: '', scope: '',
    username: '', password: '',
    api_key: '', api_key_header_name: 'X-API-Key', api_key_query_name: 'api_key',
    static_token: '',
    custom_headers: [],
    token_ttl_override_sec: '',
    is_active: true,
    ...initial
  });

  const set = (k, v) =>setForm(f => ({ ...f, [k]: v }));
  const atype = form.auth_type;

  return (
    <ModalOverlay onClose={onClose} title={form.id ? 'Auth Düzenle' : 'Yeni Auth Konfigürasyonu'} width={600}>
      <FormRow label="Ad *">
        <input className="form-input" value={form.name} onChange={e =>set('name', e.target.value)} placeholder="Şirket CRM Token" />
      </FormRow>
      <FormRow label="Açıklama">
        <input className="form-input" value={form.description || ''} onChange={e =>set('description', e.target.value)} />
      </FormRow>
      <FormRow label="Auth Tipi *">
        <select className="form-select" value={atype} onChange={e =>set('auth_type', e.target.value)}>
          {Object.entries(typeLabels).map(([k,v]) => <option key={k} value={k}>{v}</option>)}
        </select>
      </FormRow>

      {/* OAuth2 alanları */}
      {(atype === 'oauth2_client_credentials' || atype === 'oauth2_password') && (<>
        <FormRow label="Token URL *">
          <input className="form-input" value={form.token_url || ''} onChange={e =>set('token_url', e.target.value)} placeholder="https://api.sirket.com/oauth/token" />
        </FormRow>
        <FormRow label="Client ID">
          <input className="form-input" value={form.client_id || ''} onChange={e =>set('client_id', e.target.value)} />
        </FormRow>
        <FormRow label="Client Secret">
          <input className="form-input" type="password" value={form.client_secret || ''} onChange={e =>set('client_secret', e.target.value)} />
        </FormRow>
        <FormRow label="Scope">
          <input className="form-input" value={form.scope || ''} onChange={e =>set('scope', e.target.value)} placeholder="read write" />
        </FormRow>
      </>)}

      {/* Password ek alanlar */}
      {(atype === 'oauth2_password' || atype === 'basic_auth') && (<>
        <FormRow label="Kullanıcı Adı">
          <input className="form-input" value={form.username || ''} onChange={e =>set('username', e.target.value)} />
        </FormRow>
        <FormRow label="Şifre">
          <input className="form-input" type="password" value={form.password || ''} onChange={e =>set('password', e.target.value)} />
        </FormRow>
      </>)}

      {/* API Key */}
      {atype === 'api_key_header' && (<>
        <FormRow label="Header Adı">
          <input className="form-input" value={form.api_key_header_name || 'X-API-Key'} onChange={e =>set('api_key_header_name', e.target.value)} />
        </FormRow>
        <FormRow label="API Key">
          <input className="form-input" type="password" value={form.api_key || ''} onChange={e =>set('api_key', e.target.value)} />
        </FormRow>
      </>)}

      {atype === 'api_key_query' && (<>
        <FormRow label="Parametre Adı">
          <input className="form-input" value={form.api_key_query_name || 'api_key'} onChange={e =>set('api_key_query_name', e.target.value)} />
        </FormRow>
        <FormRow label="API Key">
          <input className="form-input" type="password" value={form.api_key || ''} onChange={e =>set('api_key', e.target.value)} />
        </FormRow>
      </>)}

      {/* Static Bearer */}
      {atype === 'bearer_static' && (
        <FormRow label="Token">
          <textarea className="form-input" rows={3} value={form.static_token || ''} onChange={e =>set('static_token', e.target.value)} placeholder="eyJ..." />
        </FormRow>
      )}

      {/* Token TTL override */}
      {(atype === 'oauth2_client_credentials' || atype === 'oauth2_password') && (
        <FormRow label="Token TTL (sn, boşsa otomatik)">
          <input className="form-input" type="number" value={form.token_ttl_override_sec || ''} onChange={e =>set('token_ttl_override_sec', e.target.value ? parseInt(e.target.value) : null)} placeholder="3600" />
        </FormRow>
      )}

      <div style={{ display:'flex', justifyContent:'flex-end', gap:10, marginTop:24 }}>
        <button className="btn btn-secondary" onClick={onClose}>İptal</button>
        <button className="btn btn-primary" onClick={() =>onSave(form)}>Kaydet</button>
      </div>
    </ModalOverlay>
  );
}

/* ============================================================
   SERVICE MODAL — sekmeli yapı
   ============================================================ */
function ServiceModal({ initial, authList, ctLabels, onSave, onClose }) {
  const { useState, useRef } = React;
  const [tab, setTab] = useState('basic');
  const [form, setForm] = useState({
    name: '', description: '',
    url: '', method: 'POST', content_type: 'json',
    request_body_template: '', query_params_template: null,
    extra_headers: null, soap_action: '',
    auth_config_id: null,
    response_mappings: [],
    timeout_sec: 5, on_error: 'continue', on_error_transfer_ext: '',
    success_status_codes: null, log_enabled: true,
    trigger_on_call_start: false, background_lookup: false, prompt_context_template: '',
    allow_private_network: false, is_active: true,
    ...initial,
    response_mappings: initial?.response_mappings || [],
  });

  // Değişken paneli için son odaklanan alan
  const lastFocusedRef = useRef(null);
  const trackFocus = (e) => { lastFocusedRef.current = e.target; };
  const onInsertVar = (name) => {
    const el = lastFocusedRef.current;
    if (el && window.insertAtCursor) window.insertAtCursor(el, `{${name}}`);
  };

  const set = (k, v) =>setForm(f => ({ ...f, [k]: v }));

  /* Response mapping yönetimi */
  const addMapping = () =>set('response_mappings', [...form.response_mappings, { path:'', variable:'', default:'' }]);
  const updMapping = (i, k, v) =>set('response_mappings', form.response_mappings.map((m, idx) =>idx===i ? {...m,[k]:v} : m));
  const delMapping = (i) =>set('response_mappings', form.response_mappings.filter((_,idx) =>idx!==i));

  /* Extra headers (JSON edit) */
  const [headersJson, setHeadersJson] = useState(
    form.extra_headers ? JSON.stringify(form.extra_headers, null, 2) : ''
  );
  const [queryJson, setQueryJson] = useState(
    form.query_params_template ? JSON.stringify(form.query_params_template, null, 2) : ''
  );

  const handleSave = () => {
    const data = { ...form };
    // JSON alanlarını parse et
    try { data.extra_headers = headersJson.trim() ? JSON.parse(headersJson) : null; } catch { alert('Extra Headers geçersiz JSON'); return; }
    try { data.query_params_template = queryJson.trim() ? JSON.parse(queryJson) : null; } catch { alert('Query Params geçersiz JSON'); return; }
    if (data.auth_config_id === '' || data.auth_config_id === 'null') data.auth_config_id = null;
    if (data.auth_config_id) data.auth_config_id = parseInt(data.auth_config_id);
    onSave(data);
  };

  const TABS = [
    { id:'basic', label:'Temel' },
    { id:'request', label:'İstek' },
    { id:'mapping', label:'Yanıt Mapping' },
    { id:'behavior', label:'Davranış' },
  ];

  return (
    <ModalOverlay onClose={onClose} title={form.id ? 'Servis Düzenle' : 'Yeni Servis'} width={740}>
      {/* Sekmeler */}
      <div style={{ display:'flex', gap:4, marginBottom:20, borderBottom:'1px solid var(--border)', paddingBottom:8 }}>
        {TABS.map(t => (
          <button key={t.id}
            onClick={() =>setTab(t.id)}
            style={{
              padding:'5px 14px', borderRadius:8, border:'none', cursor:'pointer', fontSize:13,
              background: tab===t.id ? 'var(--primary)' : 'transparent',
              color: tab===t.id ? '#fff' : 'var(--text-dim)', fontWeight: tab===t.id ? 600 : 400
            }}
          >{t.label}</button>
        ))}
      </div>

      {/* ── Temel ── */}
      {tab === 'basic' && (<>
        <FormRow label="Servis Adı *">
          <input className="form-input" value={form.name} onChange={e =>set('name', e.target.value)} placeholder="Müşteri Sorgulama" />
        </FormRow>
        <FormRow label="Açıklama">
          <input className="form-input" value={form.description || ''} onChange={e =>set('description', e.target.value)} />
        </FormRow>
        <FormRow label="URL *">
          <input className="form-input" value={form.url} onChange={e =>set('url', e.target.value)}
            onFocus={trackFocus}
            placeholder="https://api.sirket.com/customers/{caller_id}" />
          <div style={{ fontSize:12, color:'var(--text-dim)', marginTop:4 }}>
             <code style={{ background:'var(--bg-hover)', padding:'1px 4px', borderRadius:3 }}>{'{caller_id}'}</code>gibi IVR değişkenlerini kullanabilirsiniz
          </div>
          {window.VariableHintPanel && (
            <div style={{ marginTop:8 }}>
              <window.VariableHintPanel context="qc_end" compact={true} onInsert={onInsertVar} />
            </div>
          )}
        </FormRow>
        <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr', gap:12 }}>
          <FormRow label="HTTP Metodu">
            <select className="form-select" value={form.method} onChange={e =>set('method', e.target.value)}>
              {['GET','POST','PUT','PATCH'].map(m => <option key={m}>{m}</option>)}
            </select>
          </FormRow>
          <FormRow label="İçerik Tipi">
            <select className="form-select" value={form.content_type} onChange={e =>set('content_type', e.target.value)}>
              {Object.entries(ctLabels).map(([k,v]) => <option key={k} value={k}>{v}</option>)}
            </select>
          </FormRow>
          <FormRow label="Timeout (sn)">
            <input className="form-input" type="number" min={1} max={30} value={form.timeout_sec} onChange={e =>set('timeout_sec', parseInt(e.target.value))} />
          </FormRow>
        </div>
        <FormRow label="Auth Konfigürasyonu">
          <select className="form-select" value={form.auth_config_id || ''} onChange={e =>set('auth_config_id', e.target.value || null)}>
            <option value="">— Auth Yok —</option>
            {authList.map(a => <option key={a.id} value={a.id}>{a.name}</option>)}
          </select>
        </FormRow>
        {form.content_type === 'soap' && (
          <FormRow label="SOAPAction Header">
            <input className="form-input" value={form.soap_action || ''} onChange={e =>set('soap_action', e.target.value)} placeholder="urn:GetCustomer" />
          </FormRow>
        )}
        <FormRow label="Çağrı Başında Otomatik Sorgula">
          <label style={{ display:'flex', alignItems:'center', gap:10, cursor:'pointer' }}>
            <input
              type="checkbox"
              checked={!!form.trigger_on_call_start}
              onChange={e => set('trigger_on_call_start', e.target.checked)}
            />
            <span style={{ fontSize:13 }}>
              Çağrı gelir gelmez <code style={{ background:'var(--bg-hover)', padding:'1px 4px', borderRadius:3 }}>caller_id</code> ile otomatik sorgula
            </span>
          </label>
          {form.trigger_on_call_start && (
            <div style={{ marginTop:6, fontSize:12, color:'#d97706', background:'rgba(245,158,11,0.08)', borderRadius:8, padding:'8px 12px' }}>
              Bu servis çağrı başlar başlamaz <code style={{ background:'rgba(0,0,0,0.06)', padding:'1px 4px', borderRadius:3 }}>caller_id</code> ile otomatik çalışır.
              Yanıt Mapping'de tanımladığınız değişkenler AI asistanın sistemine eklenir.
              {!form.background_lookup && <><br/><b> customer_name</b> değişkeni varsa karşılama mesajında isim kullanılır.</>}
            </div>
          )}
        </FormRow>
        {form.trigger_on_call_start && (
          <FormRow label="Arka Planda Çalıştır">
            <label style={{ display:'flex', alignItems:'center', gap:10, cursor:'pointer' }}>
              <input
                type="checkbox"
                checked={!!form.background_lookup}
                onChange={e => set('background_lookup', e.target.checked)}
              />
              <span style={{ fontSize:13 }}>
                Hoşgeldin mesajı oynatılırken arka planda sorgu yap (hız kazanımı)
              </span>
            </label>
            {form.background_lookup ? (
              <div style={{ marginTop:6, fontSize:12, color:'#6366f1', background:'rgba(99,102,241,0.07)', borderRadius:8, padding:'8px 12px' }}>
                Hoşgeldin mesajı ve WS sorgusu aynı anda çalışır. Müşteri konuşmaya başlamadan önce sonuç hazır olur.
                Karşılama metninde müşteri adı kullanılamaz; ancak konuşma boyunca tüm WS verileri AI'a aktarılır.
              </div>
            ) : (
              <div style={{ marginTop:6, fontSize:12, color:'var(--text-dim)' }}>
                WS yanıtı beklendikten sonra hoşgeldin oynatılır. Müşteri adını karşılama metninde kullanabilirsiniz.
              </div>
            )}
          </FormRow>
        )}
        {form.trigger_on_call_start && (
          <FormRow label="AI Prompt Şablonu">
            <textarea
              className="form-input"
              rows={3}
              value={form.prompt_context_template || ''}
              onChange={e => set('prompt_context_template', e.target.value)}
              placeholder={`Müşteri Adı: {customer_name}\nSegment: {crm_segment}\nBakiye: {crm_balance} TL`}
              style={{ fontFamily:'monospace', fontSize:13 }}
            />
            <div style={{ fontSize:12, color:'var(--text-dim)', marginTop:4 }}>
              Yanıt Mapping'deki değişkenleri <code style={{ background:'var(--bg-hover)', padding:'1px 4px', borderRadius:3 }}>{'{değişken_adı}'}</code> ile kullanın.
              Boş bırakırsanız tüm değişkenler otomatik olarak eklenir.
            </div>
          </FormRow>
        )}
      </>)}

      {/* ── İstek ── */}
      {tab === 'request' && (<>
        {window.VariableHintPanel && (
          <div style={{ marginBottom:12 }}>
            <window.VariableHintPanel context="qc_end" onInsert={onInsertVar} />
            <div style={{ fontSize:11, color:'var(--text-dim)', marginTop:4 }}>
              Değişken ekleneceği alana önce tıklayın (imleç konumu), sonra yukarıdan değişkene tıklayın.
            </div>
          </div>
        )}
        {form.method !== 'GET' && (
          <FormRow label={form.content_type === 'soap' ? 'SOAP Envelope Template' : 'Request Body Template'}>
            <textarea className="form-input" rows={8} value={form.request_body_template || ''} onChange={e =>set('request_body_template', e.target.value)}
              onFocus={trackFocus}
              placeholder={form.content_type === 'soap'
                ? `<soapenv:Envelope xmlns:soapenv="...">\n <soapenv:Body>\n <GetCustomer>\n <Phone>{caller_id}</Phone>\n </GetCustomer>\n </soapenv:Body>\n</soapenv:Envelope>`
                : `{\n "phone": "{caller_id}",\n "account_no": "{dtmf_input}"\n}`}
              style={{ fontFamily:'monospace', fontSize:13 }}
            />
            <div style={{ fontSize:12, color:'var(--text-dim)', marginTop:4 }}>
               IVR değişkenleri: <code style={{ background:'var(--bg-hover)', padding:'1px 4px', borderRadius:3 }}>{'{caller_id}'}</code>&nbsp;
              <code style={{ background:'var(--bg-hover)', padding:'1px 4px', borderRadius:3 }}>{'{dtmf_input}'}</code>
            </div>
          </FormRow>
        )}
        <FormRow label="Query Parametreler (JSON — GET için)">
          <textarea className="form-input" rows={3} value={queryJson} onChange={e =>setQueryJson(e.target.value)}
            onFocus={trackFocus}
            placeholder={'{ "phone": "{caller_id}", "format": "json" }'}
            style={{ fontFamily:'monospace', fontSize:13 }}
          />
        </FormRow>
        <FormRow label="Ekstra HTTP Header'lar (JSON)">
          <textarea className="form-input" rows={3} value={headersJson} onChange={e =>setHeadersJson(e.target.value)}
            onFocus={trackFocus}
            placeholder={'{ "Accept-Language": "tr-TR", "X-Source": "IVR" }'}
            style={{ fontFamily:'monospace', fontSize:13 }}
          />
        </FormRow>
      </>)}

      {/* ── Yanıt Mapping ── */}
      {tab === 'mapping' && (
        <div>
          <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:12 }}>
            <div style={{ fontSize:13, color:'var(--text-dim)' }}>
              REST/JSON için <b>JSONPath</b> ($.data.name) &nbsp;|&nbsp; SOAP/XML için <b>XPath</b> (//CustomerName/text())
            </div>
            <button className="btn btn-secondary" style={{ fontSize:12 }} onClick={addMapping}>+ Mapping Ekle</button>
          </div>
          {form.response_mappings.length === 0 ? (
            <div style={{ textAlign:'center', padding:32, color:'var(--text-dim)', fontSize:14 }}>
              Henüz mapping yok. Yanıttan IVR değişkenine veri aktarmak için ekleyin.
            </div>
          ) : (
            <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
              {/* Header */}
              <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr auto', gap:10, fontSize:12, fontWeight:600, color:'var(--text-dim)', padding:'0 4px' }}>
                <span>Path (JSONPath / XPath)</span>
                <span>IVR Değişkeni</span>
                <span>Varsayılan</span>
                <span></span>
              </div>
              {form.response_mappings.map((m, i) => (
                <div key={i} style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr auto', gap:10, alignItems:'center' }}>
                  <input className="form-input" value={m.path} onChange={e =>updMapping(i,'path',e.target.value)}
                    placeholder="$.data.name veya //Name/text()" style={{ fontFamily:'monospace', fontSize:12 }} />
                  <input className="form-input" value={m.variable} onChange={e =>updMapping(i,'variable',e.target.value)}
                    placeholder="crm_name" style={{ fontFamily:'monospace', fontSize:12 }} />
                  <input className="form-input" value={m.default} onChange={e =>updMapping(i,'default',e.target.value)}
                    placeholder="boş" style={{ fontSize:12 }} />
                  <button style={{ background:'none', border:'none', cursor:'pointer', fontSize:16, color:'var(--danger)' }} onClick={() =>delMapping(i)}>X</button>
                </div>
              ))}
            </div>
          )}

          {/* Örnek */}
          <div style={{ marginTop:20, background:'var(--bg-hover)', borderRadius:10, padding:14, fontSize:13 }}>
            <div style={{ fontWeight:600, marginBottom:8 }}>Örnek Kullanım</div>
            <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:16 }}>
              <div>
                <div style={{ fontSize:12, color:'var(--text-dim)', marginBottom:4 }}>REST/JSON yanıtı:</div>
                <pre style={{ margin:0, fontSize:11, color:'#10b981' }}>{`{
  "data": {
    "name": "Ahmet Yılmaz",
    "segment": "VIP"
  }
}`}</pre>
              </div>
              <div>
                <div style={{ fontSize:12, color:'var(--text-dim)', marginBottom:4 }}>Mapping:</div>
                <pre style={{ margin:0, fontSize:11, color:'#6366f1' }}>{`path: $.data.name
variable: crm_name

path: $.data.segment
variable: crm_segment`}</pre>
              </div>
            </div>
          </div>
        </div>
      )}

      {/* ── Davranış ── */}
      {tab === 'behavior' && (<>
        <FormRow label="Hata Durumunda">
          <select className="form-select" value={form.on_error} onChange={e =>set('on_error', e.target.value)}>
            <option value="continue">Akışa devam et</option>
            <option value="hangup">Çağrıyı kapat</option>
            <option value="transfer">Extension'a transfer et</option>
          </select>
        </FormRow>
        {form.on_error === 'transfer' && (
          <FormRow label="Transfer Extension">
            <input className="form-input" value={form.on_error_transfer_ext || ''} onChange={e =>set('on_error_transfer_ext', e.target.value)} placeholder="8001" />
          </FormRow>
        )}
        <FormRow label="Çağrı Logları">
          <label style={{ display:'flex', alignItems:'center', gap:8, cursor:'pointer' }}>
            <input type="checkbox" checked={!!form.log_enabled} onChange={e =>set('log_enabled', e.target.checked)} />
            <span>Her çağrıyı logla (KVKK hassas veri içeriyorsa kapatın)</span>
          </label>
        </FormRow>
        <FormRow label="Özel Ağ İzni (SSRF)">
          <label style={{ display:'flex', alignItems:'flex-start', gap:8, cursor:'pointer' }}>
            <input type="checkbox" checked={!!form.allow_private_network}
              onChange={e =>set('allow_private_network', e.target.checked)} style={{ marginTop: 3 }} />
            <div>
              <div style={{ fontSize: 13 }}>Private/localhost adreslerine izin ver</div>
              <div style={{ fontSize: 11, color:'#d97706', marginTop: 2 }}>
                Yalnızca test/dev ortamı için. Production'da KAPALI tutun — aksi halde dahili ağ adreslerine SSRF saldırısına açık olur.
              </div>
            </div>
          </label>
        </FormRow>
        <FormRow label="Aktif">
          <label style={{ display:'flex', alignItems:'center', gap:8, cursor:'pointer' }}>
            <input type="checkbox" checked={!!form.is_active} onChange={e =>set('is_active', e.target.checked)} />
            <span>Servis aktif</span>
          </label>
        </FormRow>
      </>)}

      <div style={{ display:'flex', justifyContent:'flex-end', gap:10, marginTop:24 }}>
        <button className="btn btn-secondary" onClick={onClose}>İptal</button>
        <button className="btn btn-primary" onClick={handleSave}>Kaydet</button>
      </div>
    </ModalOverlay>
  );
}

/* ============================================================
   TEST PANEL
   ============================================================ */
function TestPanel({ svc, onClose, toast }) {
  const { useState } = React;
  const [vars, setVars] = useState([{ key:'caller_id', value:'' }]);
  const [result, setResult] = useState(null);
  const [loading, setLoading] = useState(false);

  const addVar = () =>setVars(v => [...v, { key:'', value:'' }]);
  const updVar = (i, k, v) =>setVars(list =>list.map((row, idx) =>idx===i ? {...row,[k]:v} : row));
  const delVar = (i) =>setVars(list =>list.filter((_,idx) =>idx!==i));

  const run = async () => {
    setLoading(true);
    setResult(null);
    const variables = {};
    vars.forEach(({ key, value }) => { if (key.trim()) variables[key.trim()] = value; });
    const res = await apiFetch(`/api/ws/test/${svc.id}`, {
      method: 'POST',
      body: JSON.stringify({ call_uuid:'TEST', variables }),
    });
    setResult(res);
    setLoading(false);
    if (res?.success) toast('Test başarılı ', 'success');
    else toast('Test başarısız ', 'error');
  };

  return (
    <ModalOverlay onClose={onClose} title={`Test — ${svc.name}`} width={640}>
      <div style={{ marginBottom:16, fontSize:13, color:'var(--text-dim)' }}>
        IVR'dan gönderilecek kanal değişkenlerini girin ve servisi test edin.
      </div>

      {/* Değişkenler */}
      <div style={{ marginBottom:16 }}>
        <div style={{ display:'flex', justifyContent:'space-between', marginBottom:8 }}>
          <span style={{ fontWeight:600, fontSize:14 }}>IVR Değişkenleri</span>
          <button className="btn btn-secondary" style={{ fontSize:12 }} onClick={addVar}>+ Ekle</button>
        </div>
        <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
          {vars.map((row, i) => (
            <div key={i} style={{ display:'grid', gridTemplateColumns:'1fr 1fr auto', gap:8 }}>
              <input className="form-input" value={row.key} onChange={e =>updVar(i,'key', e.target.value)} placeholder="caller_id" style={{ fontFamily:'monospace', fontSize:13 }} />
              <input className="form-input" value={row.value} onChange={e =>updVar(i,'value',e.target.value)} placeholder="05321234567" style={{ fontSize:13 }} />
              <button style={{ background:'none', border:'none', cursor:'pointer', fontSize:16, color:'var(--danger)' }} onClick={() =>delVar(i)}>X</button>
            </div>
          ))}
        </div>
      </div>

      <button className="btn btn-primary" style={{ width:'100%', padding:10 }} onClick={run} disabled={loading}>
        {loading ? 'Çağrılıyor…' : 'Test Çalıştır'}
      </button>

      {/* Sonuç */}
      {result && (
        <div style={{ marginTop:20 }}>
          <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:12 }}>
            <span style={{ fontSize:20 }}>{result.success ? '✅' : '❌'}</span>
            <span style={{ fontWeight:600 }}>{result.success ? 'Başarılı' : 'Başarısız'}</span>
            {result.response_status && (
              <span style={{
                fontSize:12, fontWeight:600,
                color: result.success ? '#10b981' : '#ef4444',
                background: result.success ? 'rgba(16,185,129,0.1)' : 'rgba(239,68,68,0.1)',
                borderRadius:5, padding:'2px 8px'
              }}>HTTP {result.response_status}</span>
            )}
            {result.error && <span style={{ color:'var(--danger)', fontSize:13 }}>({result.error})</span>}
          </div>

          {/* Auth Bilgisi */}
          {result.auth_info && (
            <div style={{
              marginBottom:16, borderRadius:8, border:'1px solid var(--border)',
              overflow:'hidden'
            }}>
              <div style={{
                background:'rgba(99,102,241,0.08)', padding:'6px 12px',
                fontSize:12, fontWeight:700, color:'#6366f1', letterSpacing:'0.04em'
              }}>
                AUTH SERVİSİ
              </div>
              <div style={{ padding:'10px 12px', display:'flex', flexDirection:'column', gap:6 }}>
                <div style={{ display:'grid', gridTemplateColumns:'110px 1fr', gap:8, fontSize:13 }}>
                  <span style={{ color:'var(--text-dim)' }}>Konfigürasyon</span>
                  <span style={{ fontWeight:600 }}>{result.auth_info.name}</span>
                </div>
                <div style={{ display:'grid', gridTemplateColumns:'110px 1fr', gap:8, fontSize:13 }}>
                  <span style={{ color:'var(--text-dim)' }}>Tip</span>
                  <span style={{ fontFamily:'monospace', fontSize:12 }}>{result.auth_info.type}</span>
                </div>
                {result.auth_info.token_url && (
                  <div style={{ display:'grid', gridTemplateColumns:'110px 1fr', gap:8, fontSize:13 }}>
                    <span style={{ color:'var(--text-dim)' }}>Token URL</span>
                    <span style={{ fontFamily:'monospace', fontSize:12, wordBreak:'break-all', color:'var(--text-dim)' }}>{result.auth_info.token_url}</span>
                  </div>
                )}
                <div style={{ display:'grid', gridTemplateColumns:'110px 1fr', gap:8, fontSize:13 }}>
                  <span style={{ color:'var(--text-dim)' }}>Durum</span>
                  <span>
                    {result.auth_info.status === 'cache_hit' && (
                      <span style={{ background:'rgba(16,185,129,0.1)', color:'#059669', borderRadius:5, padding:'2px 8px', fontSize:12, fontWeight:600 }}>
                        Önbellekten kullanıldı
                      </span>
                    )}
                    {result.auth_info.status === 'fetched' && (
                      <span style={{ background:'rgba(99,102,241,0.1)', color:'#6366f1', borderRadius:5, padding:'2px 8px', fontSize:12, fontWeight:600 }}>
                        Token alındı
                      </span>
                    )}
                    {result.auth_info.status === 'static' && (
                      <span style={{ background:'rgba(245,158,11,0.1)', color:'#d97706', borderRadius:5, padding:'2px 8px', fontSize:12, fontWeight:600 }}>
                        Statik kimlik
                      </span>
                    )}
                  </span>
                </div>
                <div style={{ display:'grid', gridTemplateColumns:'110px 1fr', gap:8, fontSize:13 }}>
                  <span style={{ color:'var(--text-dim)' }}>Süre</span>
                  <span style={{ fontSize:12, color:'var(--text-dim)' }}>{result.auth_info.duration_ms} ms</span>
                </div>
              </div>
            </div>
          )}

          {/* REQUEST */}
          {(result.request_url || result.request_headers || result.request_body) && (
            <div style={{
              marginBottom:16, borderRadius:8, border:'1px solid var(--border)',
              overflow:'hidden'
            }}>
              <div style={{
                background:'rgba(16,185,129,0.08)', padding:'6px 12px',
                fontSize:12, fontWeight:700, color:'#059669', letterSpacing:'0.04em'
              }}>
                REQUEST
              </div>
              <div style={{ padding:'10px 12px', display:'flex', flexDirection:'column', gap:8 }}>
                {result.request_url && (
                  <div style={{ fontSize:12, fontFamily:'monospace', wordBreak:'break-all', color:'var(--text)' }}>
                    <span style={{ fontWeight:700, marginRight:6 }}>{svc.method || 'GET'}</span>
                    <span style={{ color:'var(--text-dim)' }}>{result.request_url}</span>
                  </div>
                )}
                {result.request_headers && Object.keys(result.request_headers).length > 0 && (
                  <div>
                    <div style={{ fontSize:11, fontWeight:700, color:'var(--text-dim)', marginBottom:3, letterSpacing:'0.04em' }}>HEADERS</div>
                    <div style={{
                      fontFamily:'monospace', fontSize:11, whiteSpace:'pre-wrap',
                      wordBreak:'break-all', color:'var(--text-dim)',
                      background:'var(--bg-hover)', borderRadius:4, padding:'6px 10px'
                    }}>
                      {Object.entries(result.request_headers).map(([k, v]) => `${k}: ${v}`).join('\n')}
                    </div>
                  </div>
                )}
                {result.request_body && (
                  <div>
                    <div style={{ fontSize:11, fontWeight:700, color:'var(--text-dim)', marginBottom:3, letterSpacing:'0.04em' }}>BODY</div>
                    <div style={{
                      fontFamily:'monospace', fontSize:11, whiteSpace:'pre-wrap',
                      wordBreak:'break-all', color:'var(--text-dim)',
                      background:'var(--bg-hover)', borderRadius:4, padding:'6px 10px'
                    }}>
                      {result.request_body}
                    </div>
                  </div>
                )}
              </div>
            </div>
          )}

          {result.success && Object.keys(result.variables || {}).length > 0 && (
            <div>
              <div style={{ fontWeight:600, fontSize:13, marginBottom:8 }}>Eşlenen Değişkenler:</div>
              <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
                {Object.entries(result.variables).map(([k, v]) => (
                  <div key={k} style={{ display:'flex', gap:12, background:'var(--bg-hover)', borderRadius:8, padding:'6px 12px', fontSize:13 }}>
                    <span style={{ fontFamily:'monospace', color:'#6366f1', fontWeight:600, minWidth:140 }}>{k}</span>
                    <span style={{ color:'var(--text)', wordBreak:'break-all' }}>{v || <em style={{ color:'var(--text-dim)' }}>boş</em>}</span>
                  </div>
                ))}
              </div>
            </div>
          )}

          {result.success && Object.keys(result.variables || {}).length === 0 && (
            <div style={{ color:'var(--text-dim)', fontSize:13 }}>Servis yanıt verdi fakat eşlenen değişken yok. Mapping ayarlarını kontrol edin.</div>
          )}
        </div>
      )}
    </ModalOverlay>
  );
}

/* ============================================================
   AUTH TEST PANEL
   ============================================================ */
function AuthTestPanel({ auth, onClose, toast }) {
  const { useState } = React;
  const [result, setResult] = useState(null);
  const [loading, setLoading] = useState(false);

  const run = async () => {
    setLoading(true);
    setResult(null);
    const res = await apiFetch(`/api/ws/auth/test/${auth.id}`, { method: 'POST' });
    setResult(res);
    setLoading(false);
    if (res?.success) toast('Auth testi başarılı', 'success');
    else toast('Auth testi başarısız', 'error');
  };

  return (
    <ModalOverlay onClose={onClose} title={`Auth Test — ${auth.name}`} width={520}>
      <div style={{ marginBottom:16, fontSize:13, color:'var(--text-dim)' }}>
        Auth konfigürasyonunu test edin. Token alınabiliyorsa veya kimlik doğrulama geçerliyse başarılı sayılır.
      </div>

      <div style={{ marginBottom:16, background:'var(--bg-hover)', borderRadius:8, padding:'10px 14px', fontSize:13 }}>
        <div style={{ display:'flex', gap:12 }}>
          <span style={{ color:'var(--text-dim)', minWidth:90 }}>Konfigürasyon</span>
          <span style={{ fontWeight:600 }}>{auth.name}</span>
        </div>
        <div style={{ display:'flex', gap:12, marginTop:6 }}>
          <span style={{ color:'var(--text-dim)', minWidth:90 }}>Auth Tipi</span>
          <span style={{ fontWeight:600 }}>{auth.auth_type}</span>
        </div>
        {auth.token_url && (
          <div style={{ display:'flex', gap:12, marginTop:6 }}>
            <span style={{ color:'var(--text-dim)', minWidth:90 }}>Token URL</span>
            <span style={{ fontFamily:'monospace', fontSize:12, wordBreak:'break-all' }}>{auth.token_url}</span>
          </div>
        )}
      </div>

      <button className="btn btn-primary" style={{ width:'100%', padding:10 }} onClick={run} disabled={loading}>
        {loading ? 'Test ediliyor…' : 'Auth Testini Çalıştır'}
      </button>

      {result && (
        <div style={{ marginTop:20 }}>
          <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:12 }}>
            <span style={{ fontSize:20 }}>{result.success ? '✅' : '❌'}</span>
            <span style={{ fontWeight:600 }}>{result.success ? 'Başarılı' : 'Başarısız'}</span>
            {result.response_status && (
              <span style={{
                fontSize:12, fontWeight:600,
                color: result.success ? '#10b981' : '#ef4444',
                background: result.success ? 'rgba(16,185,129,0.1)' : 'rgba(239,68,68,0.1)',
                borderRadius:5, padding:'2px 8px'
              }}>HTTP {result.response_status}</span>
            )}
          </div>
          {result.error && (
            <div style={{
              background:'rgba(239,68,68,0.08)', borderRadius:8, padding:'10px 14px',
              fontSize:13, color:'#ef4444', fontFamily:'monospace', wordBreak:'break-all'
            }}>
              {result.error}
            </div>
          )}
          {result.success && !result.error && (
            <div style={{
              background:'rgba(16,185,129,0.08)', borderRadius:8, padding:'10px 14px',
              fontSize:13, color:'#059669'
            }}>
              Kimlik doğrulama başarıyla tamamlandı. Bu auth konfigürasyonu servislerde kullanılabilir.
            </div>
          )}
        </div>
      )}
    </ModalOverlay>
  );
}

/* ============================================================
   LOGS PANEL
   ============================================================ */
function WsLogsPanel({ svc, logs, onClose }) {
  const { useState } = React;
  const [expanded, setExpanded] = useState({});
  const toggle = (id) => setExpanded(s => ({ ...s, [id]: !s[id] }));

  const sectionStyle = (color) => ({
    marginTop:6, borderRadius:6, padding:'6px 10px',
    background: `rgba(${color},0.06)`, borderLeft:`3px solid rgba(${color},0.35)`
  });
  const labelStyle = (color) => ({
    fontSize:11, fontWeight:700, color:`rgb(${color})`,
    marginBottom:4, letterSpacing:'0.04em'
  });
  const monoBox = {
    fontFamily:'monospace', fontSize:11, whiteSpace:'pre-wrap',
    wordBreak:'break-all', color:'var(--text-dim)', marginTop:4,
    background:'var(--bg-hover)', borderRadius:4, padding:'4px 8px'
  };

  return (
    <ModalOverlay onClose={onClose} title={`Çağrı Logları — ${svc.name}`} width={820}>
      {logs.length === 0 ? (
        <div style={{ textAlign:'center', padding:40, color:'var(--text-dim)' }}>Henüz log kaydı yok.</div>
      ) : (
        <div style={{ display:'flex', flexDirection:'column', gap:10, maxHeight:600, overflowY:'auto' }}>
          {logs.map(log => (
            <div key={log.id} style={{
              background:'var(--bg-hover)', borderRadius:10, padding:'10px 14px',
              borderLeft: `4px solid ${log.success ? '#10b981' : '#ef4444'}`
            }}>
              {/* ── Başlık satırı ── */}
              <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center' }}>
                <div style={{ display:'flex', gap:8, alignItems:'center', flexWrap:'wrap' }}>
                  <span style={{ fontWeight:700, fontSize:12, color: log.success ? '#10b981' : '#ef4444' }}>
                    {log.success ? 'OK' : 'FAIL'}
                  </span>
                  <span style={{ fontFamily:'monospace', fontSize:11, color:'var(--text-dim)' }}>{log.call_uuid}</span>
                  {log.response_status && (
                    <span style={{ fontSize:11, fontWeight:600, color: log.success ? '#10b981' : '#ef4444' }}>
                      HTTP {log.response_status}
                    </span>
                  )}
                  {log.duration_ms && (
                    <span style={{ fontSize:11, color:'var(--text-dim)' }}>{log.duration_ms}ms</span>
                  )}
                </div>
                <div style={{ display:'flex', gap:8, alignItems:'center' }}>
                  <span style={{ fontSize:11, color:'var(--text-dim)' }}>
                    {fmtDateTime(log.called_at, { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit' })}
                  </span>
                  <button
                    style={{ background:'none', border:'1px solid var(--border)', borderRadius:4,
                      padding:'2px 8px', fontSize:11, cursor:'pointer', color:'var(--text-dim)' }}
                    onClick={() => toggle(log.id)}
                  >{expanded[log.id] ? 'Kapat' : 'Detay'}</button>
                </div>
              </div>

              {log.error_message && (
                <div style={{ fontSize:12, color:'#ef4444', marginTop:4 }}>Hata: {log.error_message}</div>
              )}

              {/* Eşlenen değişkenler — her zaman göster */}
              {log.mapped_variables && Object.keys(log.mapped_variables).length > 0 && (
                <div style={{ display:'flex', flexWrap:'wrap', gap:6, marginTop:6 }}>
                  {Object.entries(log.mapped_variables).map(([k, v]) => (
                    <span key={k} style={{
                      background:'rgba(99,102,241,0.1)', color:'#6366f1',
                      borderRadius:5, padding:'1px 8px', fontSize:11
                    }}>{k}: <b>{v}</b></span>
                  ))}
                </div>
              )}

              {/* ── Detay bölümü ── */}
              {expanded[log.id] && (
                <div style={{ marginTop:10, display:'flex', flexDirection:'column', gap:6 }}>

                  {/* Auth */}
                  {log.auth_info && (
                    <div style={sectionStyle('99,102,241')}>
                      <div style={labelStyle('99,102,241')}>AUTH</div>
                      <div style={{ display:'flex', flexWrap:'wrap', gap:6, alignItems:'center' }}>
                        <span style={{ fontSize:11, fontWeight:600 }}>{log.auth_info.name}</span>
                        <span style={{ fontSize:10, fontFamily:'monospace', background:'var(--bg-hover)', borderRadius:3, padding:'1px 6px', color:'var(--text-dim)' }}>
                          {log.auth_info.type}
                        </span>
                        {log.auth_info.status === 'cache_hit' && (
                          <span style={{ fontSize:10, fontWeight:600, color:'#059669', background:'rgba(16,185,129,0.1)', borderRadius:3, padding:'1px 6px' }}>önbellekten</span>
                        )}
                        {log.auth_info.status === 'fetched' && (
                          <span style={{ fontSize:10, fontWeight:600, color:'#6366f1', background:'rgba(99,102,241,0.1)', borderRadius:3, padding:'1px 6px' }}>token alındı</span>
                        )}
                        {log.auth_info.status === 'static' && (
                          <span style={{ fontSize:10, fontWeight:600, color:'#d97706', background:'rgba(245,158,11,0.1)', borderRadius:3, padding:'1px 6px' }}>statik</span>
                        )}
                        {log.auth_info.token_preview && (
                          <span style={{ fontSize:10, fontFamily:'monospace', color:'var(--text)' }}>
                            token: <b>{log.auth_info.token_preview}</b>
                          </span>
                        )}
                        {log.auth_info.duration_ms != null && (
                          <span style={{ fontSize:10, color:'var(--text-dim)' }}>{log.auth_info.duration_ms}ms</span>
                        )}
                      </div>
                      {log.auth_info.token_url && (
                        <div style={{ fontSize:10, color:'var(--text-dim)', marginTop:3, fontFamily:'monospace', wordBreak:'break-all' }}>
                          Token URL: {log.auth_info.token_url}
                        </div>
                      )}
                    </div>
                  )}

                  {/* Request */}
                  <div style={sectionStyle('16,185,129')}>
                    <div style={labelStyle('5,150,105')}>REQUEST</div>
                    <div style={{ fontSize:11, marginBottom:4 }}>
                      <span style={{ fontWeight:600 }}>{log.request_method}</span>
                      {' '}
                      <span style={{ fontFamily:'monospace', wordBreak:'break-all', color:'var(--text-dim)' }}>{log.request_url}</span>
                    </div>
                    {log.request_headers && Object.keys(log.request_headers).length > 0 && (
                      <div>
                        <div style={{ fontSize:10, fontWeight:700, color:'var(--text-dim)', marginBottom:2 }}>HEADERS</div>
                        <div style={monoBox}>
                          {Object.entries(log.request_headers).map(([k, v]) =>
                            `${k}: ${v}`
                          ).join('\n')}
                        </div>
                      </div>
                    )}
                    {log.request_body && (
                      <div style={{ marginTop:4 }}>
                        <div style={{ fontSize:10, fontWeight:700, color:'var(--text-dim)', marginBottom:2 }}>BODY</div>
                        <div style={monoBox}>{log.request_body}</div>
                      </div>
                    )}
                  </div>

                  {/* Response body */}
                  {log.response_body && (
                    <div style={sectionStyle('245,158,11')}>
                      <div style={labelStyle('180,115,0')}>RESPONSE BODY</div>
                      <div style={monoBox}>{log.response_body}</div>
                    </div>
                  )}
                </div>
              )}
            </div>
          ))}
        </div>
      )}
    </ModalOverlay>
  );
}

/* ============================================================
   SHARED HELPERS
   ============================================================ */
function ModalOverlay({ children, onClose, title, width=600 }) {
  return (
    <div style={{
      position:'fixed', inset:0, background:'rgba(0,0,0,0.5)',
      display:'flex', alignItems:'center', justifyContent:'center', zIndex:1000
    }} onClick={e =>e.target===e.currentTarget && onClose()}>
      <div style={{
        background:'var(--bg-card)', borderRadius:16, padding:28,
        width: Math.min(width, window.innerWidth - 32), maxWidth:'100%',
        maxHeight:'90vh', overflowY:'auto',
        boxShadow:'0 24px 60px rgba(0,0,0,0.35)'
      }}>
        <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:20 }}>
          <h3 style={{ margin:0, fontSize:17, fontWeight:600 }}>{title}</h3>
          <button style={{ background:'none', border:'none', cursor:'pointer', fontSize:20, color:'var(--text-dim)' }} onClick={onClose}>X</button>
        </div>
        {children}
      </div>
    </div>
  );
}

function FormRow({ label, children }) {
  return (
    <div style={{ marginBottom:14 }}>
      <label style={{ display:'block', fontSize:13, fontWeight:600, marginBottom:5, color:'var(--text-dim)' }}>{label}</label>
      {children}
    </div>
  );
}

function EmptyState({ icon, text, sub }) {
  return (
    <div style={{ textAlign:'center', padding:'60px 20px', color:'var(--text-dim)' }}>
      {icon && <div style={{ fontSize:16, marginBottom:12 }}>{icon}</div>}
      <div style={{ fontSize:16, fontWeight:600 }}>{text}</div>
      {sub && <div style={{ fontSize:14, marginTop:6 }}>{sub}</div>}
    </div>
  );
}

async function apiFetch(url, opts = {}) {
  const token = localStorage.getItem('access_token');
  try {
    const res = await fetch(url, {
      headers: { 'Content-Type':'application/json', 'Authorization': `Bearer ${token}`, ...(opts.headers||{}) },
      ...opts,
    });
    if (!res.ok) return null;
    return await res.json();
  } catch { return null; }
}
