/* global React */
const { useState, useMemo, useEffect } = React;

const STORAGE_KEY = 'workers-monitor:registry-v2';

function App() {
  const [tw, setTweak] = window.useTweaks(window.TWEAK_DEFAULTS);
  const { theme, refreshSpeed, showKpis } = tw;

  const [view, setView] = useState('summary'); // summary | workers | tenants | instances | configs | api
  const [instances, setInstances] = useState([]);
  const [tenantStats, setTenantStats] = useState({});
  const [tenants, setTenants] = useState([]);
  const [workerTypes, setWorkerTypes] = useState([]);
  const [loading, setLoading] = useState(true);
  const [loggedIn, setLoggedIn] = useState(null); // null=checking, false=login, true=ok
  const [loginError, setLoginError] = useState('');
  const [selectedInstance, setSelectedInstance] = useState(null);
  const [selectedTenant, setSelectedTenant] = useState(null);
  const [search, setSearch] = useState('');
  const [envFilter, setEnvFilter] = useState('all');
  const [toasts, setToasts] = useState([]);
  const [tickN, setTickN] = useState(0);

  // Cascade config viewer state
  const [cascadeTenant, setCascadeTenant] = useState('');
  const [cascadeEnv, setCascadeEnv] = useState('Prod');
  const [cascadeResolved, setCascadeResolved] = useState([]);

  // Modals
  const [showDrain, setShowDrain] = useState(null);
  const [showStopTenant, setShowStopTenant] = useState(null);
  const [showReload, setShowReload] = useState(null);

  useEffect(() => {
    document.documentElement.classList.toggle('dark', theme === 'dark');
  }, [theme]);

  function loadData() {
    setLoading(true);
    window.loadDashboardData()
      .then(({ instances: inst, workerTypes: wt, tenantStats: ts, tenants: tn }) => {
        setInstances(inst);
        setWorkerTypes(wt);
        setTenantStats(ts);
        setTenants(tn);
        if (tn.length > 0 && !cascadeTenant) setCascadeTenant(tn[0].id);
      })
      .catch(err => toast('error', 'Erro ao carregar dados: ' + err.message))
      .finally(() => setLoading(false));
  }

  // Check auth on mount, load data only if authenticated
  useEffect(() => {
    window.checkAuth().then(ok => {
      setLoggedIn(ok);
      if (ok) loadData();
      else setLoading(false);
    });
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

  async function handleLogin(e) {
    e.preventDefault();
    const form = new FormData(e.target);
    setLoginError('');
    try {
      await window.loginUser(form.get('username'), form.get('password'));
      setLoggedIn(true);
      loadData();
    } catch {
      setLoginError('Usuário ou senha inválidos.');
    }
  }

  async function handleLogout() {
    await window.logoutUser();
    setLoggedIn(false);
    setInstances([]); setWorkerTypes([]); setTenantStats({}); setTenants([]);
  }

  // Cascade config — refetch when tenant/env selector changes
  useEffect(() => {
    if (!cascadeTenant || !cascadeEnv) return;
    window.fetchCascadeConfig(cascadeTenant, cascadeEnv)
      .then(setCascadeResolved)
      .catch(() => setCascadeResolved([]));
  }, [cascadeTenant, cascadeEnv]);

  // Live tick — heartbeat updates + drain progress
  useEffect(() => {
    if (refreshSpeed === 0) return;
    const interval = Math.max(800, 5000 / refreshSpeed);
    const t = setInterval(() => {
      setInstances(prev => prev.map(inst => {
        const next = { ...inst };
        next.lastHeartbeat = inst.currentStatus === 'Zombie' ? inst.lastHeartbeat : Date.now() - Math.floor(Math.random() * 5000);
        if (inst.currentStatus === 'Running') {
          next.currentWorkload = Math.max(5, Math.min(100, inst.currentWorkload + Math.floor((Math.random() - 0.5) * 8)));
          next.cpu = Math.max(0, Math.min(100, inst.cpu + (Math.random() - 0.5) * 6));
          next.sparkline = [...inst.sparkline.slice(1), 30 + Math.random() * 50];
        }
        if (inst.currentStatus === 'Draining') {
          next.remainingTasks = Math.max(0, inst.remainingTasks - Math.floor(2 + Math.random() * 8));
          if (next.remainingTasks === 0) next.currentStatus = 'ReadyToDie';
        }
        return next;
      }));
      setTickN(n => n + 1);
    }, interval);
    return () => clearInterval(t);
  }, [refreshSpeed]);

  const toast = (type, message) => {
    const id = Date.now() + Math.random();
    setToasts(t => [...t, { id, type, message }]);
    setTimeout(() => setToasts(t => t.filter(x => x.id !== id)), 4000);
  };

  // C2 commands
  const handleDrain = async (instance) => {
    setInstances(prev => prev.map(i => i.instanceId === instance.instanceId ? { ...i, currentStatus: 'Draining' } : i));
    setShowDrain(null);
    try {
      const res = await fetch('/api/v1/commands/drain', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', ...authHeaders() },
        body: JSON.stringify({ instanceId: instance.instanceId }),
      });
      if (res.status === 401) toast('error', 'Auth required — drain bloqueado (401)');
      else toast('info', `Drain iniciado: ${instance.instanceId}`);
    } catch {
      toast('error', `Falha ao chamar drain — ${instance.instanceId}`);
    }
  };

  const handleReloadConfig = async (tenantId, environment) => {
    setShowReload(null);
    try {
      const res = await fetch('/api/v1/commands/reload-config', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', ...authHeaders() },
        body: JSON.stringify({ tenantId, environment }),
      });
      if (res.status === 401) toast('error', 'Auth required — reload bloqueado (401)');
      else toast('success', `Hot reload: TenantContext invalidado para ${tenantId}@${environment}`);
    } catch {
      toast('error', `Falha ao reload config — ${tenantId}@${environment}`);
    }
  };

  const handleStopTenant = (tenant) => {
    setTenants(prev => prev.map(t => t.id === tenant.id ? { ...t, status: 'PendingStop', deactivationStatus: 'ContractCancelled' } : t));
    toast('info', `${tenant.id} → PendingStop. Workers vão drenar buffers e reportar FullyStopped.`);
    setShowStopTenant(null);
    setTimeout(() => setTenants(prev => prev.map(t => t.id === tenant.id ? { ...t, status: 'Stopping' } : t)), 1500);
  };

  const healthSummary = useMemo(() => window.buildHealthSummary(instances), [instances, tickN]);

  const filteredInstances = useMemo(() => {
    let list = instances;
    if (search) {
      const q = search.toLowerCase();
      list = list.filter(i => i.instanceId.toLowerCase().includes(q) || i.workerTypeId.toLowerCase().includes(q) || i.assignments.some(a => a.toLowerCase().includes(q)));
    }
    if (envFilter !== 'all') {
      list = list.filter(i => i.assignments.some(a => a.endsWith('@' + envFilter)));
    }
    return list;
  }, [instances, search, envFilter]);

  // Group instances by worker type
  const instancesByType = useMemo(() => {
    const out = {};
    workerTypes.forEach(wt => {
      out[wt.id] = filteredInstances.filter(i => i.workerTypeId === wt.id);
    });
    return out;
  }, [filteredInstances, workerTypes]);

  // Aggregate processing instances per tenant
  const processingInstancesPerTenant = useMemo(() => {
    const out = {};
    tenants.forEach(t => {
      out[t.id] = instances.filter(i =>
        i.assignments.some(a => a.startsWith(t.id + '@')) &&
        (i.currentStatus === 'Running' || i.currentStatus === 'Draining')
      );
    });
    return out;
  }, [instances, tenants, tickN]);

  const VIEWS = [
    { id: 'summary', label: 'Health Summary', icon: 'activity', count: null },
    { id: 'workers', label: 'Worker Pools', icon: 'server', count: workerTypes.length },
    { id: 'tenants', label: 'Tenants', icon: 'users', count: tenants.length },
    { id: 'instances', label: 'Instances', icon: 'layers', count: instances.length },
    { id: 'configs', label: 'Configurations', icon: 'settings', count: cascadeResolved.length || null },
    { id: 'api', label: 'API Contract', icon: 'code', count: null },
  ];

  if (loggedIn === null) return (
    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100vh', flexDirection: 'column', gap: 16, color: 'var(--muted-foreground)', fontFamily: 'var(--font-mono)', fontSize: 13 }}>
      <div className="live-dot" style={{ width: 10, height: 10 }}></div>
      Verificando autenticação...
    </div>
  );

  if (loggedIn === false) return (
    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100vh', background: 'var(--background)' }}>
      <form onSubmit={handleLogin} style={{ display: 'flex', flexDirection: 'column', gap: 14, minWidth: 320, padding: 32, borderRadius: 12, border: '1px solid var(--border)', background: 'var(--card)' }}>
        <div style={{ marginBottom: 4 }}>
          <h2 style={{ margin: 0, fontSize: 18, fontWeight: 600 }}>Workers Control Plane</h2>
          <p style={{ margin: '4px 0 0', fontSize: 12, color: 'var(--muted-foreground)' }}>Faça login para acessar o dashboard</p>
        </div>
        <input name="username" placeholder="Usuário" autoFocus required
          style={{ padding: '8px 12px', borderRadius: 6, border: '1px solid var(--border)', background: 'var(--input)', color: 'var(--foreground)', fontSize: 14 }} />
        <input name="password" type="password" placeholder="Senha" required
          style={{ padding: '8px 12px', borderRadius: 6, border: '1px solid var(--border)', background: 'var(--input)', color: 'var(--foreground)', fontSize: 14 }} />
        {loginError && <span style={{ color: 'var(--destructive)', fontSize: 13 }}>{loginError}</span>}
        <button type="submit"
          style={{ padding: '9px 12px', borderRadius: 6, background: 'var(--primary)', color: 'var(--primary-foreground)', border: 'none', cursor: 'pointer', fontWeight: 600, fontSize: 14 }}>
          Entrar
        </button>
      </form>
    </div>
  );

  if (loading) return (
    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100vh', flexDirection: 'column', gap: 16, color: 'var(--muted-foreground)', fontFamily: 'var(--font-mono)', fontSize: 13 }}>
      <div className="live-dot" style={{ width: 10, height: 10 }}></div>
      Conectando ao Control Plane...
    </div>
  );

  return (
    <>
      <div className="topbar">
        <div className="topbar-brand"><div className="brand-logo">W</div><span>Workers Control Plane</span></div>
        <div className="topbar-env">prod · multi-tenant · v1.0</div>
        <div className="topbar-spacer"></div>
        <div className="topbar-status" title="JWT validated · all communications protected">
          <span style={{ color: 'var(--success)', fontWeight: 600 }}>JWT</span>
          <span style={{ opacity: 0.5 }}>·</span>
          <span>AES-256</span>
          <span style={{ opacity: 0.5 }}>·</span>
          <span className="live-dot"></span>
          {refreshSpeed === 0 ? 'paused' : `heartbeat ${(5/refreshSpeed).toFixed(0)}s`}
        </div>
        <button className="icon-btn" onClick={() => setTweak('theme', theme === 'dark' ? 'light' : 'dark')}><window.Icon name={theme === 'dark' ? 'sun' : 'moon'} size={16}/></button>
        <button className="icon-btn"><window.Icon name="bell" size={16}/></button>
        <button className="icon-btn" onClick={handleLogout} title="Sair"><window.Icon name="log-out" size={16}/></button>
      </div>

      <div className="app">
        <aside className="sidebar">
          <div className="sidebar-section">Environment</div>
          {['all', 'Prod', 'Hml', 'Dev'].map(e => (
            <div key={e} className={`sidebar-item ${envFilter === e ? 'active' : ''}`} onClick={() => setEnvFilter(e)}>
              <window.Icon name="layers" size={14}/>
              {e === 'all' ? 'Todos' : e}
              {e !== 'all' && <span className="badge">{instances.filter(i => i.assignments.some(a => a.endsWith('@' + e))).length}</span>}
            </div>
          ))}
          <div className="sidebar-section">Quick stats</div>
          <div style={{ padding: '0 10px', fontSize: 12, color: 'var(--muted-foreground)', display: 'flex', flexDirection: 'column', gap: 6, fontFamily: 'var(--font-mono)' }}>
            <div>online: <span style={{ color: 'var(--success)' }}>{healthSummary.online}/{healthSummary.totalInstances}</span></div>
            <div>draining: <span style={{ color: 'var(--warning)' }}>{healthSummary.draining}</span></div>
            <div>zombies: <span style={{ color: 'var(--destructive)' }}>{healthSummary.zombies}</span></div>
            <div>tenants ativos: <span style={{ color: 'var(--foreground)' }}>{tenants.filter(t => t.status === 'Active').length}</span></div>
          </div>
        </aside>

        <main className="main">
          <div className="page-header">
            <div>
              <h1 className="page-title">Control Plane V1.0</h1>
              <div className="page-subtitle">Orquestração multi-tenant · Hot Reload · Graceful Shutdown · Cascade EAV configuration</div>
            </div>
          </div>

          <div className="view-tabs">
            {VIEWS.map(v => (
              <div key={v.id} className={`view-tab ${view === v.id ? 'active' : ''}`} onClick={() => setView(v.id)}>
                <window.Icon name={v.icon} size={14}/>
                {v.label}
                {v.count != null && <span className="count">{v.count}</span>}
              </div>
            ))}
          </div>

          {view === 'summary' && <SummaryView health={healthSummary} instances={instances} tenants={tenants} workerTypes={workerTypes} tenantStats={tenantStats}/>}
          {view === 'workers' && <WorkersView types={workerTypes} instancesByType={instancesByType} onPickInstance={setSelectedInstance}/>}
          {view === 'tenants' && <TenantsView tenants={tenants} stats={tenantStats} processing={processingInstancesPerTenant} onPick={setSelectedTenant} onStop={setShowStopTenant} onReload={(t) => setShowReload({ tenantId: t.id, environment: 'Prod' })}/>}
          {view === 'instances' && <InstancesView instances={filteredInstances} search={search} setSearch={setSearch} onPick={setSelectedInstance} onDrain={setShowDrain}/>}
          {view === 'configs' && <ConfigsView tenant={cascadeTenant} setTenant={setCascadeTenant} env={cascadeEnv} setEnv={setCascadeEnv} resolved={cascadeResolved} tenants={tenants}/>}
          {view === 'api' && <ApiContractView/>}
        </main>
      </div>

      {selectedInstance && <InstanceDrawer instance={selectedInstance} onClose={() => setSelectedInstance(null)} onDrain={(i) => { setSelectedInstance(null); setShowDrain(i); }} toast={toast}/>}
      {selectedTenant && <TenantDrawer tenant={selectedTenant} stats={tenantStats[selectedTenant.id]} processing={processingInstancesPerTenant[selectedTenant.id] || []} onClose={() => setSelectedTenant(null)} toast={toast}/>}

      {showDrain && (
        <ConfirmModal title="Drenar instância (Graceful Shutdown)" icon="alert"
          body={<>Vai chamar <code>POST /api/v1/commands/drain</code> em <strong>{showDrain.instanceId}</strong>. A instância recusará novos assignments e drenará seu buffer atual ({showDrain.remainingTasks} tasks). Quando RemainingTasks=0, irá para ReadyToDie.</>}
          confirmLabel="Iniciar drain" confirmKind="warning" onCancel={() => setShowDrain(null)} onConfirm={() => handleDrain(showDrain)}/>
      )}
      {showStopTenant && (
        <ConfirmModal title="Parar tenant (PendingStop)" icon="alert"
          body={<>Workers afetados pararão de aceitar novos itens para <strong>{showStopTenant.id}</strong>, processarão o buffer atual e reportarão <code>FullyStopped</code>. Esta operação respeita a cadeia <code>PendingStop → Stopping → FullyStopped</code>.</>}
          confirmLabel="Confirmar parada" confirmKind="danger" onCancel={() => setShowStopTenant(null)} onConfirm={() => handleStopTenant(showStopTenant)}/>
      )}
      {showReload && (
        <ConfirmModal title="Reload de configuração" icon="refresh"
          body={<>Vai chamar <code>POST /api/v1/commands/reload-config</code> com <code>{`{ tenantId: "${showReload.tenantId}", environment: "${showReload.environment}" }`}</code>. Workers invalidarão o TenantContext em cache e o reconstruirão sem reiniciar.</>}
          confirmLabel="Disparar Hot Reload" confirmKind="primary" onCancel={() => setShowReload(null)} onConfirm={() => handleReloadConfig(showReload.tenantId, showReload.environment)}/>
      )}

      <div className="toasts">{toasts.map(t => <div key={t.id} className={`toast ${t.type}`}><span className="ico"></span>{t.message}</div>)}</div>

      <window.TweaksPanel title="Tweaks">
        <window.TweakSection title="Tema">
          <window.TweakRadio value={theme} onChange={v => setTweak('theme', v)} options={[{value:'dark',label:'Dark'},{value:'light',label:'Light'}]}/>
        </window.TweakSection>
        <window.TweakSection title={`Heartbeat: ${refreshSpeed === 0 ? 'pausado' : refreshSpeed + 'x'}`}>
          <window.TweakSlider value={refreshSpeed} onChange={v => setTweak('refreshSpeed', v)} min={0} max={5} step={1}/>
        </window.TweakSection>
        <window.TweakToggle label="Mostrar KPIs" value={showKpis} onChange={v => setTweak('showKpis', v)}/>
      </window.TweaksPanel>
    </>
  );
}

// ─── Health Summary view ───
function SummaryView({ health, instances, tenants, workerTypes, tenantStats }) {
  const totalProcessed = Object.values(tenantStats).reduce((s, x) => s + x.totalProcessed, 0);
  const totalFailed = Object.values(tenantStats).reduce((s, x) => s + x.failed, 0);
  const errorRate = ((totalFailed / (totalProcessed || 1)) * 100).toFixed(2);
  const activeTenants = tenants.filter(t => t.status === 'Active').length;
  const stoppingTenants = tenants.filter(t => t.status === 'PendingStop' || t.status === 'Stopping').length;

  return (
    <>
      <div className="kpi-row" style={{ gridTemplateColumns: 'repeat(5, 1fr)' }}>
        <KpiCard label="Total instâncias" value={health.totalInstances}/>
        <KpiCard label="Online" value={health.online} delta={`${Math.round(health.online/health.totalInstances*100)}%`} deltaKind="up"/>
        <KpiCard label="Draining" value={health.draining} delta={health.draining > 0 ? 'graceful' : 'ok'} deltaKind={health.draining > 0 ? 'neutral' : 'up'}/>
        <KpiCard label="ReadyToDie" value={health.readyToDie} delta="aguardando OS kill" deltaKind="neutral"/>
        <KpiCard label="Zombies" value={health.zombies} delta={health.zombies > 0 ? 'sem heartbeat' : 'ok'} deltaKind={health.zombies > 0 ? 'down' : 'up'}/>
      </div>

      <div className="kpi-row" style={{ gridTemplateColumns: 'repeat(4, 1fr)' }}>
        <KpiCard label="Tenants ativos" value={activeTenants} unit={`/ ${tenants.length}`}/>
        <KpiCard label="Tenants em parada" value={stoppingTenants} delta="graceful" deltaKind="neutral"/>
        <KpiCard label="Processados (24h)" value={window.fmtNum(totalProcessed)}/>
        <KpiCard label="Taxa de erro" value={errorRate} unit="%" delta={parseFloat(errorRate) > 1 ? 'atenção' : 'ok'} deltaKind={parseFloat(errorRate) > 1 ? 'down' : 'up'}/>
      </div>

      <div className="charts-grid" style={{ marginTop: 16 }}>
        <div className="chart-card">
          <div className="chart-header"><span className="chart-title">Worker types · instâncias por tipo</span></div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
            {workerTypes.map(wt => {
              const list = instances.filter(i => i.workerTypeId === wt.id);
              const running = list.filter(i => i.currentStatus === 'Running').length;
              return (
                <div key={wt.id} style={{ display: 'grid', gridTemplateColumns: '1fr 60px 100px', alignItems: 'center', gap: 10, fontSize: 12 }}>
                  <span className="mono" style={{ fontWeight: 500 }}>{wt.id}</span>
                  <span className="mono muted" style={{ textAlign: 'right' }}>{running}/{list.length}</span>
                  <window.MiniBar value={running} max={list.length || 1}/>
                </div>
              );
            })}
          </div>
        </div>
        <div className="chart-card">
          <div className="chart-header"><span className="chart-title">Tenants · status</span></div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            {tenants.map(t => (
              <div key={t.id} style={{ display: 'grid', gridTemplateColumns: '1fr auto', alignItems: 'center', gap: 8, fontSize: 12 }}>
                <span className="mono">{t.id} <span className="muted">· {t.tier}</span></span>
                <window.StatusBadge status={t.status}/>
              </div>
            ))}
          </div>
        </div>
        <div className="chart-card full">
          <div className="chart-header"><span className="chart-title">Architecture overview</span></div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 12, fontSize: 12 }}>
            {[
              { t: 'Control Plane', d: 'Banco de dados central · Single Source of Truth · orquestra todas as instâncias', i: 'server' },
              { t: 'Cascade Config (EAV)', d: '3 níveis: System Global → Tenant Global → Tenant Environment · resolução O(1) em memória', i: 'layers' },
              { t: 'JWT + AES-256', d: 'Scopes worker:read/admin · MASTER_KEY via env · segredos em repouso criptografados', i: 'shield' },
              { t: 'Self-Healing', d: 'Worker mantém TenantContext em cache se Control Plane fica offline; telemetria enfileirada localmente', i: 'restart' },
            ].map((b, i) => (
              <div key={i} style={{ padding: 12, background: 'var(--muted)', borderRadius: 8 }}>
                <div style={{ fontWeight: 600, marginBottom: 4 }}>{b.t}</div>
                <div className="muted" style={{ fontSize: 11.5, lineHeight: 1.5 }}>{b.d}</div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </>
  );
}

// ─── Workers Pool view ───
function WorkersView({ types, instancesByType, onPickInstance }) {
  return (
    <>
      {types.map(wt => {
        const list = instancesByType[wt.id] || [];
        if (list.length === 0) return null;
        const running = list.filter(i => i.currentStatus === 'Running').length;
        const draining = list.filter(i => i.currentStatus === 'Draining').length;
        const zombies = list.filter(i => i.currentStatus === 'Zombie').length;
        return (
          <div key={wt.id} className="worker-card expanded">
            <div className="worker-card-header" style={{ cursor: 'default' }}>
              <div className="worker-icon"><window.Icon name="server" size={18}/></div>
              <div className="worker-info">
                <div className="worker-name">{wt.id} <span style={{ fontWeight: 400, color: 'var(--muted-foreground)', fontSize: 12 }}>· {wt.displayName}</span></div>
                <div className="worker-desc">{wt.description}</div>
              </div>
              <div className="worker-rollup">
                <div className="rollup-stat"><div className="v" style={{ color: 'var(--success)' }}>{running}</div><div className="l">running</div></div>
                {draining > 0 && <div className="rollup-stat"><div className="v" style={{ color: 'var(--warning)' }}>{draining}</div><div className="l">draining</div></div>}
                {zombies > 0 && <div className="rollup-stat"><div className="v" style={{ color: 'var(--destructive)' }}>{zombies}</div><div className="l">zombies</div></div>}
                <div className="rollup-stat"><div className="v">{list.length}</div><div className="l">total</div></div>
              </div>
            </div>
            <div className="instances-list">
              <div className="instance-row head">
                <div>Status</div><div>Instance ID</div><div>Host / Assignments</div>
                <div className="num">Workload</div><div className="num">Remaining</div><div className="num">Uptime</div><div>Trend</div><div className="num">CPU</div><div>Heartbeat</div>
              </div>
              {list.map(inst => (
                <div key={inst.instanceId} className="instance-row" onClick={() => onPickInstance(inst)}>
                  <div><window.StatusBadge status={inst.currentStatus}/></div>
                  <div className="mono" style={{ fontSize: 12 }}>{inst.instanceId}</div>
                  <div className="mono" style={{ fontSize: 11, color: 'var(--muted-foreground)', overflow: 'hidden' }}>
                    {inst.hostAddress}
                    <div style={{ marginTop: 2, display: 'flex', flexWrap: 'wrap', gap: 3 }}>
                      {inst.assignments.slice(0, 4).map(a => {
                        const [tn, env] = a.split('@');
                        return <span key={a} className="env-pill" style={{ background: 'var(--muted)' }}>{tn}<span className={'env-pill ' + env} style={{ marginLeft: 2, padding: '0 4px' }}>{env}</span></span>;
                      })}
                      {inst.assignments.length > 4 && <span className="env-pill">+{inst.assignments.length - 4}</span>}
                    </div>
                  </div>
                  <div className="num">{inst.currentWorkload}</div>
                  <div className="num" style={{ color: inst.remainingTasks > 0 && inst.currentStatus === 'Draining' ? 'var(--warning)' : 'var(--foreground)' }}>{inst.remainingTasks}</div>
                  <div className="num muted">{Math.floor((Date.now() - inst.startupTime)/86400000)}d</div>
                  <div><window.Sparkline data={inst.sparkline} width={70} height={20} color={inst.currentStatus === 'Zombie' ? 'var(--destructive)' : inst.currentStatus === 'Draining' ? 'var(--warning)' : 'var(--success)'} fill/></div>
                  <div className="num muted">{Math.round(inst.cpu)}%</div>
                  <div className="mono muted" style={{ fontSize: 11 }}>{window.fmtRelTime(inst.lastHeartbeat)}</div>
                </div>
              ))}
            </div>
          </div>
        );
      })}
    </>
  );
}

// ─── Tenants view ───
function TenantsView({ tenants, stats, processing, onPick, onStop, onReload }) {
  return (
    <>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
        <div className="tenant-card" style={{ background: 'var(--muted)', cursor: 'default', padding: '8px 16px' }}>
          <div className="tenant-card-row" style={{ fontSize: 10, textTransform: 'uppercase', letterSpacing: '0.05em', color: 'var(--muted-foreground)', fontWeight: 500 }}>
            <div>Tenant</div><div>Status</div><div>Environments</div>
            <div className="stat-l">Processing</div><div className="stat-l">Avg ms</div><div className="stat-l">Processados</div><div className="stat-l">Falhas</div><div>Ações</div>
          </div>
        </div>
        {tenants.map(t => {
          const s = stats[t.id] || { totalProcessed: 0, failed: 0, avgProcessingTimeMs: 0 };
          const procInstances = processing[t.id] || [];
          return (
            <div key={t.id} className={`tenant-card ${t.status === 'FullyStopped' ? 'stopped' : ''}`} onClick={() => onPick(t)}>
              <div className="tenant-card-row">
                <div>
                  <div className="name">{t.id} <span className="env-pill" style={{ background: t.tier === 'premium' ? 'color-mix(in oklch, var(--primary) 14%, transparent)' : 'var(--muted)', color: t.tier === 'premium' ? 'var(--primary)' : 'var(--muted-foreground)' }}>{t.tier}</span></div>
                  <div className="meta">{t.name}</div>
                </div>
                <div><window.StatusBadge status={t.status}/></div>
                <div>
                  {t.environments.map(e => <span key={e} className={'env-pill ' + e}>{e}</span>)}
                  {t.deactivationStatus && <div style={{ marginTop: 4, fontSize: 10, color: 'var(--muted-foreground)', fontFamily: 'var(--font-mono)' }}>↳ {t.deactivationStatus}</div>}
                </div>
                <div><div className="stat-v">{procInstances.length}</div><div className="stat-l">instâncias</div></div>
                <div><div className="stat-v">{s.avgProcessingTimeMs}<span style={{ fontWeight: 400, opacity: 0.6 }}>ms</span></div><div className="stat-l">média</div></div>
                <div><div className="stat-v">{window.fmtNum(s.totalProcessed)}</div><div className="stat-l">24h</div></div>
                <div><div className="stat-v" style={{ color: s.failed > 0 ? 'var(--destructive)' : 'var(--foreground)' }}>{window.fmtNum(s.failed)}</div><div className="stat-l">falhas</div></div>
                <div onClick={e => e.stopPropagation()} style={{ display: 'flex', gap: 2 }}>
                  <button className="icon-btn" title="Hot Reload Config" onClick={() => onReload(t)}><window.Icon name="refresh" size={13}/></button>
                  {t.status === 'Active' && <button className="icon-btn" title="Stop tenant" onClick={() => onStop(t)}><window.Icon name="stop" size={13}/></button>}
                </div>
              </div>
            </div>
          );
        })}
      </div>
    </>
  );
}

// ─── Instances view ───
function InstancesView({ instances, search, setSearch, onPick, onDrain }) {
  return (
    <>
      <div className="toolbar">
        <input className="search-input" placeholder="Buscar por instance id, worker type, tenant@env..." value={search} onChange={e => setSearch(e.target.value)}/>
      </div>
      <div className="worker-card expanded">
        <div className="instances-list">
          <div className="instance-row head">
            <div>Status</div><div>Instance ID</div><div>Host / WorkerType</div>
            <div className="num">Workload</div><div className="num">Remaining</div><div className="num">Uptime</div><div>Drain progress</div><div className="num">Heartbeat</div><div>Actions</div>
          </div>
          {instances.map(inst => (
            <div key={inst.instanceId} className="instance-row" onClick={() => onPick(inst)}>
              <div><window.StatusBadge status={inst.currentStatus}/></div>
              <div className="mono" style={{ fontSize: 12 }}>{inst.instanceId}</div>
              <div className="mono" style={{ fontSize: 11, color: 'var(--muted-foreground)' }}>
                {inst.hostAddress}
                <div style={{ marginTop: 2 }}>{inst.workerTypeId}</div>
              </div>
              <div className="num">{inst.currentWorkload}</div>
              <div className="num">{inst.remainingTasks}</div>
              <div className="num muted">{Math.floor((Date.now() - inst.startupTime)/86400000)}d {Math.floor(((Date.now() - inst.startupTime) % 86400000)/3600000)}h</div>
              <div>
                {inst.currentStatus === 'Draining' ? (
                  <div className="drain-progress">
                    <div className="drain-bar"><span style={{ width: Math.max(5, 100 - (inst.remainingTasks / 800) * 100) + '%' }}></span></div>
                  </div>
                ) : <span className="muted" style={{ fontSize: 11 }}>—</span>}
              </div>
              <div className="mono muted" style={{ fontSize: 11 }}>{window.fmtRelTime(inst.lastHeartbeat)}</div>
              <div onClick={e => e.stopPropagation()} style={{ display: 'flex', gap: 2 }}>
                {(inst.currentStatus === 'Running' || inst.currentStatus === 'Idle') && <button className="icon-btn" title="Drain" onClick={() => onDrain(inst)}><window.Icon name="stop" size={13}/></button>}
              </div>
            </div>
          ))}
        </div>
      </div>
    </>
  );
}

// ─── Configurations view (EAV cascade viewer) ───
function ConfigsView({ tenant, setTenant, env, setEnv, resolved, tenants }) {
  return (
    <>
      <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 14, flexWrap: 'wrap' }}>
        <div style={{ fontSize: 13, color: 'var(--muted-foreground)' }}>Resolver cascata para</div>
        <div className="btn-group">
          {tenants.filter(t => t.status !== 'FullyStopped').map(t => (
            <button key={t.id} className={`btn ${tenant === t.id ? 'active' : ''}`} onClick={() => setTenant(t.id)}>{t.id}</button>
          ))}
        </div>
        <div className="btn-group">
          {window.ENVIRONMENTS.map(e => (
            <button key={e} className={`btn ${env === e ? 'active' : ''}`} onClick={() => setEnv(e)}>{e}</button>
          ))}
        </div>
        <div style={{ marginLeft: 'auto', fontSize: 11, color: 'var(--muted-foreground)', fontFamily: 'var(--font-mono)' }}>
          {resolved.length} chaves resolvidas · O(1) em cache
        </div>
      </div>

      <div className="cascade-table">
        <div className="cascade-row head">
          <div>Key</div><div>Resolved from</div><div>Value</div>
          <div>L1 · System</div><div>L2 · Tenant</div><div>L3 · Tenant+Env</div>
        </div>
        {resolved.map(r => (
          <div key={r.key} className="cascade-row">
            <div className="key">
              {r.key}
              {r.isEncrypted && <span className="encryption-badge" style={{ marginLeft: 6 }}>🔒 AES-256</span>}
            </div>
            <div>
              <span className={'level-tag level-' + (r.resolvedFrom === 'TenantEnvironment' ? 3 : r.resolvedFrom === 'TenantGlobal' ? 2 : 1)}>
                L{r.resolvedFrom === 'TenantEnvironment' ? 3 : r.resolvedFrom === 'TenantGlobal' ? 2 : 1}
              </span>
            </div>
            <div className="v win">{r.value}</div>
            <div className={'v ' + (r.resolvedFrom === 'SystemGlobal' ? 'win' : '')}>{r.l1 ?? <span className="dim">—</span>}</div>
            <div className={'v ' + (r.resolvedFrom === 'TenantGlobal' ? 'win' : '')}>{r.l2 ?? <span className="dim">—</span>}</div>
            <div className={'v ' + (r.resolvedFrom === 'TenantEnvironment' ? 'win' : '')}>{r.l3 ?? <span className="dim">—</span>}</div>
          </div>
        ))}
      </div>

      <div className="section-title" style={{ marginTop: 22 }}>Como funciona <span className="count">resolução em cascata</span></div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 10 }}>
        {[
          { l: 1, t: 'System Global', d: 'TenantId=NULL · TenantEnvironmentId=NULL. Default da plataforma.', ex: 'LogRetentionDays = 30' },
          { l: 2, t: 'Tenant Global', d: 'TenantId set · TenantEnvironmentId=NULL. Padrão do cliente.', ex: 'LogRetentionDays = 90 (cliente premium)' },
          { l: 3, t: 'Tenant Environment', d: 'Ambos preenchidos. O mais específico vence.', ex: 'ConnectionString = "Server=ProdDB;..."' },
        ].map(b => (
          <div key={b.l} className="chart-card">
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 6 }}>
              <span className={'level-tag level-' + b.l}>L{b.l}</span>
              <span style={{ fontWeight: 600, fontSize: 13 }}>{b.t}</span>
            </div>
            <div className="muted" style={{ fontSize: 12, marginBottom: 8 }}>{b.d}</div>
            <div className="mono" style={{ fontSize: 11, color: 'var(--muted-foreground)', background: 'var(--muted)', padding: '6px 8px', borderRadius: 6 }}>{b.ex}</div>
          </div>
        ))}
      </div>
    </>
  );
}

// ─── API contract view ───
function ApiContractView() {
  const sections = [
    { title: 'Registro e Inventário (Worker ↔ Monitor)', methods: [
      { v: 'POST', p: '/api/v1/inventory/register', d: 'Bootstrap: instância anuncia que está ligada' },
      { v: 'PATCH', p: '/api/v1/inventory/{instanceId}/heartbeat', d: 'Atualização de saúde a cada 30s' },
    ]},
    { title: 'Painel de Monitoramento (UI ↔ Monitor)', methods: [
      { v: 'GET', p: '/api/v1/monitor/health-summary', d: 'Dashboard principal de infraestrutura' },
      { v: 'GET', p: '/api/v1/monitor/workers/{workerTypeId}', d: 'Visão detalhada de um pool' },
      { v: 'GET', p: '/api/v1/monitor/tenants/{tenantId}/status', d: 'Visão de processamento por cliente' },
    ]},
    { title: 'Comando e Controle — C2', methods: [
      { v: 'POST', p: '/api/v1/commands/reload-config', d: 'Hot Reload: invalida TenantContext em cache' },
      { v: 'POST', p: '/api/v1/commands/drain', d: 'Inicia Graceful Shutdown de uma instância' },
    ]},
    { title: 'Telemetria (Worker ↔ Monitor)', methods: [
      { v: 'POST', p: '/api/v1/telemetry/stats/batch', d: 'Envio de WorkerStatistics em lote' },
    ]},
  ];
  return (
    <>
      {sections.map((s, i) => (
        <div key={i} style={{ marginBottom: 18 }}>
          <div className="section-title">{s.title}</div>
          <div className="api-contract">
            {s.methods.map((m, j) => (
              <div key={j} className="api-method">
                <span className={`verb verb-${m.v}`}>{m.v}</span>
                <div><div className="path">{m.p}</div><div className="desc">{m.d}</div></div>
              </div>
            ))}
          </div>
        </div>
      ))}
      <div className="section-title">Segurança</div>
      <div className="chart-card">
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 12, fontSize: 12 }}>
          <div><strong>JWT Auth</strong><div className="muted" style={{ marginTop: 4 }}>Todos os endpoints protegidos. Validação rigorosa de Scopes (worker:read, worker:admin) e Audience.</div></div>
          <div><strong>AES-256 em repouso</strong><div className="muted" style={{ marginTop: 4 }}>ConfigurationSettings com IsEncrypted=true · descriptografia apenas em memória · MASTER_KEY via variável de ambiente.</div></div>
        </div>
      </div>
    </>
  );
}

// ─── Drawers ───
function InstanceDrawer({ instance, onClose, onDrain, toast }) {
  const [tab, setTab] = useState('overview');
  const series = useMemo(() => window.generateTimeSeries(instance.instanceId.split('').reduce((s, c) => s + c.charCodeAt(0), 0)), [instance.instanceId]);
  const logs = useMemo(() => window.generateLogs(instance.instanceId.split('').reduce((s, c) => s + c.charCodeAt(0), 0), instance, 200), [instance.instanceId]);

  useEffect(() => {
    const h = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', h);
    return () => window.removeEventListener('keydown', h);
  }, [onClose]);

  return (
    <>
      <div className="drawer-overlay" onClick={onClose}></div>
      <div className="drawer">
        <div className="drawer-header">
          <window.StatusBadge status={instance.currentStatus}/>
          <div className="drawer-title">
            <h2>{instance.instanceId}</h2>
            <div className="sub">
              <span>{instance.workerTypeId}</span>
              <span>{instance.hostAddress}</span>
              <span>uptime: {Math.floor((Date.now() - instance.startupTime)/86400000)}d</span>
              <span>tasks: {instance.remainingTasks}</span>
            </div>
          </div>
          <div className="drawer-actions">
            {(instance.currentStatus === 'Running' || instance.currentStatus === 'Idle') && (
              <button className="btn danger" onClick={() => onDrain(instance)}><window.Icon name="stop"/> Drain</button>
            )}
            <button className="icon-btn" onClick={onClose}><window.Icon name="close" size={16}/></button>
          </div>
        </div>
        <div className="drawer-tabs">
          {['overview', 'assignments', 'logs'].map(t => (
            <div key={t} className={`drawer-tab ${tab === t ? 'active' : ''}`} onClick={() => setTab(t)}>{t}</div>
          ))}
        </div>
        <div className="drawer-body">
          {tab === 'overview' && (
            <>
              <div className="detail-stats">
                <div className="detail-stat"><div className="lbl">Workload</div><div className="val">{instance.currentWorkload}</div></div>
                <div className="detail-stat"><div className="lbl">Remaining</div><div className="val">{instance.remainingTasks}</div></div>
                <div className="detail-stat"><div className="lbl">CPU</div><div className="val">{Math.round(instance.cpu)}<span className="unit">%</span></div></div>
                <div className="detail-stat"><div className="lbl">Memory</div><div className="val">{Math.round(instance.mem)}<span className="unit">MB</span></div></div>
                <div className="detail-stat"><div className="lbl">Heartbeat</div><div className="val" style={{ fontSize: 13 }}>{window.fmtRelTime(instance.lastHeartbeat)}</div></div>
                <div className="detail-stat"><div className="lbl">Status</div><div className="val" style={{ fontSize: 13 }}>{instance.currentStatus}</div></div>
              </div>
              <div className="charts-grid">
                <div className="chart-card"><div className="chart-header"><span className="chart-title">Throughput</span></div><window.LineChart series={series.map(s => s.throughput)} color="var(--success)"/></div>
                <div className="chart-card"><div className="chart-header"><span className="chart-title">Latency</span></div><window.LineChart series={series.map(s => s.latency)} color="var(--info)" formatY={v => Math.round(v) + 'ms'}/></div>
              </div>
            </>
          )}
          {tab === 'assignments' && (
            <div className="cascade-table">
              <div className="cascade-row head" style={{ gridTemplateColumns: '180px 100px 1fr' }}>
                <div>Tenant</div><div>Environment</div><div>TenantEnvironmentKey</div>
              </div>
              {instance.assignments.map(a => {
                const [tn, env] = a.split('@');
                return (
                  <div key={a} className="cascade-row" style={{ gridTemplateColumns: '180px 100px 1fr' }}>
                    <div className="key">{tn}</div>
                    <div><span className={'env-pill ' + env}>{env}</span></div>
                    <div className="v">{a}</div>
                  </div>
                );
              })}
            </div>
          )}
          {tab === 'logs' && (
            <div className="logs-terminal">
              {logs.slice(0, 100).map((l, i) => (
                <div key={i} className="log-line">
                  <span className="ts">{window.fmtTime(l.t)}</span>
                  <span className={`lvl lvl-${l.level}`}>{l.level}</span>
                  <span className="msg"><span style={{ color: 'oklch(0.65 0.12 184)' }}>[{l.tenantId}@{l.environment}]</span> {l.msg}</span>
                </div>
              ))}
            </div>
          )}
        </div>
      </div>
    </>
  );
}

function TenantDrawer({ tenant, stats, processing, onClose, toast }) {
  useEffect(() => {
    const h = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', h);
    return () => window.removeEventListener('keydown', h);
  }, [onClose]);
  return (
    <>
      <div className="drawer-overlay" onClick={onClose}></div>
      <div className="drawer">
        <div className="drawer-header">
          <window.StatusBadge status={tenant.status}/>
          <div className="drawer-title">
            <h2>{tenant.id}</h2>
            <div className="sub">
              <span>{tenant.name}</span>
              <span>tier: {tenant.tier}</span>
              <span>environments: {tenant.environments.join(', ')}</span>
            </div>
          </div>
          <button className="icon-btn" onClick={onClose}><window.Icon name="close" size={16}/></button>
        </div>
        <div className="drawer-body">
          <div className="detail-stats">
            <div className="detail-stat"><div className="lbl">Processing instances</div><div className="val">{processing.length}</div></div>
            <div className="detail-stat"><div className="lbl">Avg ms</div><div className="val">{stats.avgProcessingTimeMs}</div></div>
            <div className="detail-stat"><div className="lbl">Processados (24h)</div><div className="val">{window.fmtNum(stats.totalProcessed)}</div></div>
            <div className="detail-stat"><div className="lbl">Falhas</div><div className="val" style={{ color: stats.failed > 0 ? 'var(--destructive)' : 'inherit' }}>{window.fmtNum(stats.failed)}</div></div>
            <div className="detail-stat"><div className="lbl">Worker types</div><div className="val">{stats.activeWorkerTypes.length}</div></div>
            <div className="detail-stat"><div className="lbl">Status</div><div className="val" style={{ fontSize: 13 }}>{tenant.status}</div></div>
          </div>
          <div className="section-title">Instâncias processando este tenant <span className="count">{processing.length}</span></div>
          <div className="worker-card expanded"><div className="instances-list">
            <div className="instance-row head">
              <div>Status</div><div>Instance</div><div>WorkerType</div><div className="num">Workload</div><div className="num">Remaining</div><div className="num">CPU</div><div></div><div></div><div></div>
            </div>
            {processing.length === 0 ? <div style={{ padding: 20 }} className="muted">Nenhuma instância ativa para este tenant</div> :
              processing.map(i => (
                <div key={i.instanceId} className="instance-row">
                  <div><window.StatusBadge status={i.currentStatus}/></div>
                  <div className="mono">{i.instanceId}</div>
                  <div className="mono muted" style={{ fontSize: 11 }}>{i.workerTypeId}</div>
                  <div className="num">{i.currentWorkload}</div>
                  <div className="num">{i.remainingTasks}</div>
                  <div className="num muted">{Math.round(i.cpu)}%</div>
                  <div></div><div></div><div></div>
                </div>
              ))
            }
          </div></div>
        </div>
      </div>
    </>
  );
}

// ─── Helpers ───
function KpiCard({ label, value, unit, delta, deltaKind = 'neutral' }) {
  return (
    <div className="kpi">
      <div className="kpi-label">{label}</div>
      <div className="kpi-value">{value}{unit && <span className="unit">{unit}</span>}</div>
      <div className="kpi-meta">{delta && <span className={`kpi-delta ${deltaKind}`}>{delta}</span>}</div>
    </div>
  );
}

function ConfirmModal({ title, icon, body, confirmLabel, confirmKind, onCancel, onConfirm }) {
  return (
    <div className="modal-overlay" onClick={onCancel}>
      <div className="modal" onClick={e => e.stopPropagation()}>
        <div className="modal-header"><window.Icon name={icon} size={16}/><h3 className="modal-title">{title}</h3></div>
        <div className="modal-body">{body}</div>
        <div className="modal-footer">
          <button className="btn" onClick={onCancel}>Cancelar</button>
          <button className={`btn ${confirmKind === 'danger' ? 'danger' : confirmKind === 'primary' ? 'primary' : ''}`} onClick={onConfirm}>{confirmLabel}</button>
        </div>
      </div>
    </div>
  );
}

window.App = App;
