import { useEffect, useState, useCallback, useRef } from 'react';
import CodeMirror from '@uiw/react-codemirror';
import { json } from '@codemirror/lang-json';
import { markdown } from '@codemirror/lang-markdown';
import { yaml } from '@codemirror/lang-yaml';
import { oneDark } from '@codemirror/theme-one-dark';
import type {
  OpenClawStatus, OpenClawAgent, OpenClawSkill, OpenClawLogs,
  OpenClawModels, FileTreeNode, ReadFileResult, AgentMemoryResult
} from '../api/client';
import { api } from '../api/client';

// ═════════════════════════════════════════════════════════════════════════════════
// Tab definitions
// ═════════════════════════════════════════════════════════════════════════════════

const TABS = [
  { id: 'status', label: 'Status', icon: '🔋' },
  { id: 'filesystem', label: 'Arborescence', icon: '📂' },
  { id: 'config', label: 'Configuration', icon: '⚙️' },
  { id: 'agents', label: 'Agents', icon: '🤖' },
  { id: 'skills', label: 'Skills', icon: '🧩' },
  { id: 'logs', label: 'Logs', icon: '📟' },
  { id: 'models', label: 'Modèles', icon: '🧠' },
] as const;

type TabId = (typeof TABS)[number]['id'];

// ═════════════════════════════════════════════════════════════════════════════════
// Main Page
// ═════════════════════════════════════════════════════════════════════════════════

export default function OpenClawPage() {
  const [activeTab, setActiveTab] = useState<TabId>('status');
  const [status, setStatus] = useState<OpenClawStatus | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    api.openclawStatus()
      .then(s => { setStatus(s); setLoading(false); })
      .catch(() => setLoading(false));
  }, []);

  if (loading) {
    return (
      <div className="flex items-center justify-center h-64">
        <div className="text-center">
          <div className="text-5xl mb-3 animate-spin-slow">🐙</div>
          <div className="text-gray-500 text-sm">Connexion à OpenClaw…</div>
        </div>
      </div>
    );
  }

  return (
    <div className="space-y-6 animate-fade-in">
      {/* Header */}
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-4">
          <div className="w-12 h-12 rounded-2xl bg-gradient-to-br from-purple-600/30 to-indigo-600/30 border border-purple-500/20 flex items-center justify-center text-2xl">
            🐙
          </div>
          <div>
            <h1 className="text-xl font-bold text-white tracking-tight">OpenClaw</h1>
            <div className="flex items-center gap-2 text-xs text-gray-500">
              <span className={`w-2 h-2 rounded-full ${status?.gateway_online ? 'bg-green-400 shadow-[0_0_8px_rgba(74,222,128,0.5)]' : 'bg-red-400 shadow-[0_0_8px_rgba(248,113,113,0.5)]'}`}></span>
              {status?.gateway_online ? 'Gateway opérationnel' : 'Gateway hors ligne'}
              <span className="text-gray-700">•</span>
              <span className="uppercase tracking-wider">{status?.openclaw_type}</span>
            </div>
          </div>
        </div>
      </div>

      {/* Tab Bar */}
      <div className="flex gap-1 p-1 rounded-2xl bg-surface-800/60 border border-glass-border overflow-x-auto">
        {TABS.map(tab => (
          <button
            key={tab.id}
            onClick={() => setActiveTab(tab.id)}
            className={`flex items-center gap-2 px-4 py-2.5 rounded-xl text-sm font-medium transition-all duration-200 whitespace-nowrap ${
              activeTab === tab.id
                ? 'bg-gradient-to-r from-purple-600/20 to-indigo-600/20 text-white border border-purple-500/20 shadow-[0_0_12px_rgba(147,51,234,0.1)]'
                : 'text-gray-500 hover:text-gray-300 hover:bg-glass'
            }`}
          >
            <span className="text-base">{tab.icon}</span>
            <span>{tab.label}</span>
            {tab.id === 'agents' && status && (
              <span className="ml-1 px-1.5 py-0.5 rounded-full bg-purple-500/20 text-purple-300 text-[10px] font-bold">{status.agent_count}</span>
            )}
            {tab.id === 'skills' && status && (
              <span className="ml-1 px-1.5 py-0.5 rounded-full bg-indigo-500/20 text-indigo-300 text-[10px] font-bold">{status.skill_count}</span>
            )}
          </button>
        ))}
      </div>

      {/* Tab Content */}
      <div className="animate-fade-in">
        {activeTab === 'status' && <StatusTab status={status} />}
        {activeTab === 'filesystem' && <FilesystemTab />}
        {activeTab === 'config' && <ConfigTab />}
        {activeTab === 'agents' && <AgentsTab />}
        {activeTab === 'skills' && <SkillsTab />}
        {activeTab === 'logs' && <LogsTab />}
        {activeTab === 'models' && <ModelsTab />}
      </div>
    </div>
  );
}


// ═════════════════════════════════════════════════════════════════════════════════
// Tab 1 — Status
// ═════════════════════════════════════════════════════════════════════════════════

function StatusTab({ status }: { status: OpenClawStatus | null }) {
  if (!status) return <EmptyState message="Impossible de charger le status" />;

  const metrics = [
    { label: 'Gateway', value: status.gateway_online ? 'En ligne' : 'Hors ligne', accent: status.gateway_online ? 'green' : 'red', icon: '🔌' },
    { label: 'Mode', value: status.openclaw_type, accent: 'purple', icon: '⚡' },
    { label: 'Bind', value: status.gateway_bind, accent: 'blue', icon: '🌐' },
    { label: 'Port', value: String(status.gateway_port), accent: 'indigo', icon: '🔗' },
    { label: 'Agents', value: String(status.agent_count), accent: 'amber', icon: '🤖' },
    { label: 'Skills', value: String(status.skill_count), accent: 'teal', icon: '🧩' },
  ];

  return (
    <div className="space-y-6">
      {/* Hero health card */}
      <div className={`glass-card p-6 relative overflow-hidden ${status.gateway_online ? 'border-green-500/20' : 'border-red-500/20'}`}>
        <div className="absolute -top-20 -right-20 w-60 h-60 rounded-full blur-3xl opacity-10"
          style={{ background: status.gateway_online ? 'radial-gradient(circle, #22C55E, transparent)' : 'radial-gradient(circle, #EF4444, transparent)' }}
        />
        <div className="flex items-center gap-6 relative z-10">
          <div className={`w-20 h-20 rounded-3xl flex items-center justify-center text-4xl ${
            status.gateway_online
              ? 'bg-gradient-to-br from-green-500/20 to-emerald-600/10 border border-green-500/30'
              : 'bg-gradient-to-br from-red-500/20 to-rose-600/10 border border-red-500/30'
          }`} style={status.gateway_online ? { animation: 'pulse-glow 3s ease-in-out infinite' } : undefined}>
            {status.gateway_online ? '✅' : '❌'}
          </div>
          <div>
            <h2 className="text-2xl font-bold text-white">
              {status.gateway_online ? 'Gateway Opérationnel' : 'Gateway Hors Ligne'}
            </h2>
            <p className="text-gray-400 text-sm mt-1">
              {status.foxy_home} — Port {status.gateway_port}
            </p>
            <div className="flex items-center gap-3 mt-2">
              <span className={`badge ${status.gateway_online ? 'badge-completed' : 'badge-failed'}`}>
                {status.gateway_mode}
              </span>
              <span className="badge bg-purple-500/15 text-purple-300">
                {status.openclaw_type}
              </span>
              {status.config_exists && (
                <span className="badge bg-blue-500/15 text-blue-300">config ✓</span>
              )}
            </div>
          </div>
        </div>
      </div>

      {/* Metrics grid */}
      <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-3">
        {metrics.map(m => (
          <MetricCard key={m.label} {...m} />
        ))}
      </div>
    </div>
  );
}


function MetricCard({ label, value, accent, icon }: { label: string; value: string; accent: string; icon: string }) {
  const colorMap: Record<string, { bg: string; text: string }> = {
    green: { bg: 'from-green-500/10 to-green-600/5', text: 'text-green-400' },
    red: { bg: 'from-red-500/10 to-red-600/5', text: 'text-red-400' },
    purple: { bg: 'from-purple-500/10 to-purple-600/5', text: 'text-purple-400' },
    blue: { bg: 'from-blue-500/10 to-blue-600/5', text: 'text-blue-400' },
    indigo: { bg: 'from-indigo-500/10 to-indigo-600/5', text: 'text-indigo-400' },
    amber: { bg: 'from-amber-500/10 to-amber-600/5', text: 'text-amber-400' },
    teal: { bg: 'from-teal-500/10 to-teal-600/5', text: 'text-teal-400' },
  };
  const c = colorMap[accent] || colorMap.purple;

  return (
    <div className={`glass-card p-4 bg-gradient-to-br ${c.bg}`}>
      <div className="text-lg mb-1">{icon}</div>
      <div className="text-[10px] text-gray-500 uppercase tracking-wider">{label}</div>
      <div className={`text-lg font-extrabold ${c.text} mt-0.5`}>{value}</div>
    </div>
  );
}


function TreeNode({ node, depth, onSelect }: { node: FileTreeNode; depth: number, onSelect?: (n: FileTreeNode) => void }) {
  const [open, setOpen] = useState(depth < 1);
  const isDir = node.type === 'directory';
  const indent = depth * 20;

  return (
    <div>
      <div
        className={`flex items-center gap-2 py-1 px-2 rounded-lg transition-colors cursor-pointer ${
          isDir ? 'hover:bg-surface-700/50' : 'hover:bg-surface-700/50 text-gray-400'
        }`}
        style={{ paddingLeft: `${indent + 8}px` }}
        onClick={() => {
          if (isDir) setOpen(!open);
          else onSelect?.(node);
        }}
      >
        {isDir ? (
          <span className="text-yellow-400 w-4 text-center">{open ? '📂' : '📁'}</span>
        ) : (
          <span className="text-gray-500 w-4 text-center">📄</span>
        )}
        <span className={isDir ? 'text-white font-medium' : 'text-gray-400'}>{node.name}</span>
        {node.size != null && !isDir && (
          <span className="text-gray-600 ml-auto text-[10px]">{formatSize(node.size)}</span>
        )}
      </div>
      {isDir && open && node.children?.map(child => (
        <TreeNode key={child.path} node={child} depth={depth + 1} onSelect={onSelect} />
      ))}
    </div>
  );
}


function formatSize(bytes: number): string {
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
}


// ═════════════════════════════════════════════════════════════════════════════════
// Tab 2 — Configuration
// ═════════════════════════════════════════════════════════════════════════════════

function ConfigTab() {
  const [config, setConfig] = useState<Record<string, unknown> | null>(null);
  const [loading, setLoading] = useState(true);
  const [editing, setEditing] = useState(false);

  const fetchConfig = () => {
    setLoading(true);
    api.openclawConfig()
      .then(d => { setConfig(d.config); setLoading(false); })
      .catch(() => setLoading(false));
  };

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

  if (loading) return <LoadingSpinner />;
  if (!config) return <EmptyState message="openclaw.json introuvable ou illisible" />;

  const sections = Object.entries(config);

  return (
    <div className="space-y-6">
      {editing && <ConfigFileEditor onClose={() => setEditing(false)} onSave={() => { setEditing(false); fetchConfig(); }} />}

      {/* Premium Header */}
      <div className="flex flex-col sm:flex-row items-start sm:items-center justify-between glass-card p-6 border-l-4 border-l-purple-500 relative overflow-hidden group">
        <div className="absolute top-0 right-0 w-64 h-full bg-gradient-to-l from-purple-500/10 to-transparent opacity-50 group-hover:opacity-100 transition-opacity"></div>
        <div className="relative z-10 mb-4 sm:mb-0">
          <h2 className="text-xl font-bold text-white flex items-center gap-3">
            <span>⚙️</span> Configuration Globale
          </h2>
          <p className="text-gray-400 text-sm mt-1.5 flex items-center gap-2">
            Paramètres système chargés depuis <code className="px-1.5 py-0.5 rounded bg-surface-800 text-purple-300 font-mono text-xs">openclaw.json</code>
          </p>
        </div>
        <div className="relative z-10 shrink-0">
          <button 
            onClick={() => setEditing(true)}
            className="px-5 py-2.5 rounded-xl bg-gradient-to-r from-purple-600 to-indigo-600 text-white text-sm font-semibold hover:from-purple-500 hover:to-indigo-500 transition-all shadow-[0_0_15px_rgba(147,51,234,0.3)] hover:scale-105 flex items-center gap-2"
          >
            <span>✏️</span> Modifier config
          </button>
        </div>
      </div>

      {/* Grid of config sections */}
      <div className="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-5">
        {sections.map(([key, value]) => {
          const isObject = typeof value === 'object' && value !== null;
          
          return (
            <div key={key} className="glass-card flex flex-col h-full border border-surface-700/50 hover:border-purple-500/30 transition-all group overflow-hidden">
              <div className="bg-surface-800/80 p-4 border-b border-surface-700/50 flex justify-between items-center group-hover:bg-surface-700/50 transition-colors">
                <h3 className="font-bold text-white text-sm tracking-wide flex items-center gap-2">
                  <span className="text-purple-400 text-lg">❖</span> {key.toUpperCase()}
                </h3>
                {isObject && (
                  <span className="px-2 py-0.5 rounded-md bg-surface-900/50 text-gray-400 text-[10px] font-mono border border-surface-700">
                    {Array.isArray(value) ? `${(value as unknown[]).length} items` : `${Object.keys(value as object).length} clés`}
                  </span>
                )}
              </div>
              <div className="p-4 bg-[#1e222a] flex-1 overflow-auto max-h-96 custom-scrollbar shrink-0">
                {isObject ? (
                  <pre className="text-[11px] font-mono text-[#abb2bf] whitespace-pre-wrap leading-relaxed">
                    {JSON.stringify(value, null, 2)}
                  </pre>
                ) : (
                  <div className="h-full flex items-center">
                    <code className="text-[13px] text-green-300 font-mono bg-surface-900/50 px-3 py-2 rounded-lg break-all border border-green-500/10 w-full text-center">
                      {renderValue(value)}
                    </code>
                  </div>
                )}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}


function renderValue(v: unknown): string {
  if (v === null) return 'null';
  if (typeof v === 'boolean') return v ? 'true' : 'false';
  if (typeof v === 'number') return String(v);
  if (typeof v === 'string') return v.length > 80 ? v.slice(0, 77) + '…' : v;
  return String(v);
}


// ═════════════════════════════════════════════════════════════════════════════════
// Tab 3 — Agents (with Memory Viewer)
// ═════════════════════════════════════════════════════════════════════════════════

function AgentMemoryViewer({ agentName }: { agentName: string }) {
  const [memory, setMemory] = useState<AgentMemoryResult | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let active = true;
    api.openclawAgentMemory(agentName)
      .then(res => {
        if (active) {
          setMemory(res);
          setLoading(false);
        }
      })
      .catch(err => {
        console.error(err);
        if (active) setLoading(false);
      });
    return () => { active = false; };
  }, [agentName]);

  if (loading) {
    return (
      <div className="flex flex-col items-center justify-center p-8 text-gray-400">
        <span className="text-3xl animate-spin-slow mb-4">⌛</span>
        <p className="animate-pulse">Connexion à la mémoire QMD de l'agent...</p>
      </div>
    );
  }

  if (!memory || !memory.has_db) {
    return (
      <div className="bg-surface-800/50 border border-glass-border rounded-xl p-8 text-center flex flex-col items-center justify-center">
        <span className="text-5xl opacity-30 grayscale mb-4">🗄️</span>
        <h3 className="text-white font-semibold mb-2">Mémoire Introuvable</h3>
        <p className="text-gray-400 text-sm max-w-md mx-auto">
          Aucune base de données SQLite QMD n'a été trouvée pour cet agent dans le workspace. 
          Lumina ne dispose pas (encore) d'une trame chronologique ici.
        </p>
        <p className="text-xs text-gray-500 font-mono mt-4">Astuce : Vérifiez la configuration du dossier workspace sous FOXY_HOME.</p>
      </div>
    );
  }

  return (
    <div className="space-y-6">
      <div className="flex justify-between items-center px-4 py-3 bg-gradient-to-r from-blue-900/20 to-indigo-900/20 rounded-xl border border-blue-500/10">
        <div>
          <h4 className="text-blue-300 font-bold flex items-center gap-2">
            <span>🧠</span> Labyrinth Memoire QMD
          </h4>
          <p className="text-xs text-blue-300/60 font-mono mt-1">{memory.db_path} ({formatSize(memory.size || 0)})</p>
        </div>
        <div className="text-right">
          <div className="text-2xl font-bold text-white">{memory.stats.total_thoughts}</div>
          <div className="text-[10px] text-gray-400 uppercase tracking-wider">Pensées / Actions</div>
        </div>
      </div>

      <div className="relative pl-6 before:absolute before:inset-0 before:left-[11px] before:w-0.5 before:bg-gradient-to-b before:from-blue-500/50 before:to-transparent pt-2">
        {memory.timeline.length === 0 ? (
          <div className="text-gray-500 text-sm py-4">La mémoire existe mais elle est actuellement vide.</div>
        ) : (
          <div className="space-y-6">
            {memory.timeline.map((item: Record<string, any>, idx: number) => (
              <div key={idx} className="relative group">
                {/* Node dot */}
                <div className="absolute -left-[31px] top-1.5 w-4 h-4 rounded-full bg-surface-900 border-2 border-blue-500/50 group-hover:bg-blue-500 group-hover:shadow-[0_0_10px_rgba(59,130,246,0.6)] transition-all z-10"></div>
                
                {/* Content Card */}
                <div className="glass-card p-4 border border-surface-700/50 hover:border-blue-500/30 transition-colors">
                  <div className="flex items-start justify-between mb-2">
                    <span className="text-[10px] font-mono text-gray-500 bg-surface-800 px-2 py-0.5 rounded">
                      {item.timestamp || item.created_at || 'Inconnu'}
                    </span>
                    {(item.type || item.event_type || item.role) && (
                      <span className="text-[10px] uppercase font-bold text-indigo-300 bg-indigo-500/10 px-2 py-0.5 rounded">
                        {item.type || item.event_type || item.role}
                      </span>
                    )}
                  </div>
                  <pre className="text-sm text-gray-300 whitespace-pre-wrap font-sans leading-relaxed">
                    {item.content || item.message || JSON.stringify(item, null, 2)}
                  </pre>
                </div>
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

function AgentsTab() {
  const [agents, setAgents] = useState<OpenClawAgent[]>([]);
  const [loading, setLoading] = useState(true);
  const [expandedAgent, setExpandedAgent] = useState<string | null>(null);
  const [activeView, setActiveView] = useState<'identity' | 'memory'>('identity');

  const [deleting, setDeleting] = useState<string | null>(null);
  const [activeFile, setActiveFile] = useState<{agent: string, file: string} | null>(null);
  const [fileContent, setFileContent] = useState('');
  const [fileLoading, setFileLoading] = useState(false);
  const [saving, setSaving] = useState(false);
  const [isFullscreen, setIsFullscreen] = useState(false);

  const loadAgents = () => {
    setLoading(true);
    api.openclawAgents()
      .then(d => { setAgents(d.agents); setLoading(false); })
      .catch(() => setLoading(false));
  };

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

  const handleDelete = async (e: React.MouseEvent, name: string) => {
    e.stopPropagation();
    if (!confirm(`Voulez-vous vraiment supprimer l'agent "${name}" ?\n\n⚠️ Cette action supprimera définitivement son dossier de configuration.`)) return;
    setDeleting(name);
    try {
      await api.openclawDeleteAgent(name);
      if (expandedAgent === name) setExpandedAgent(null);
      loadAgents();
    } catch(err) {
      console.error(err);
      alert('Erreur lors de la suppression: ' + String(err));
    } finally {
      setDeleting(null);
    }
  };

  const openFile = async (agentName: string, filename: string) => {
    if (activeFile?.agent === agentName && activeFile?.file === filename) {
      setActiveFile(null); // toggle close
      setIsFullscreen(false);
      return;
    }
    setActiveFile({ agent: agentName, file: filename });
    setIsFullscreen(false);
    setFileLoading(true);
    try {
      const data = await api.openclawReadAgentFile(agentName, filename);
      setFileContent(data.content || '');
    } catch(err) {
      console.error(err);
      setFileContent('Erreur de chargement du fichier.');
    } finally {
      setFileLoading(false);
    }
  };

  const saveFile = async () => {
    if (!activeFile) return;
    setSaving(true);
    try {
      await api.openclawWriteAgentFile(activeFile.agent, activeFile.file, fileContent);
      loadAgents(); // refresh file sizes
      setActiveFile(null); // close the editor after saving
    } catch(err) {
      console.error(err);
      alert('Erreur lors de la sauvegarde: ' + String(err));
    } finally {
      setSaving(false);
    }
  };

  if (loading && agents.length === 0) return <LoadingSpinner />;
  if (agents.length === 0) return <EmptyState message="Aucun agent trouvé dans le répertoire agents/" />;

  return (
    <div className="space-y-4">
      {/* Agent count header */}
      <div className="glass-card p-4 flex items-center justify-between">
        <div className="flex items-center gap-3">
          <span className="text-lg">🤖</span>
          <span className="text-white font-semibold">{agents.length} agents</span>
          <span className="text-gray-500 text-sm hidden sm:inline">détectés dans le répertoire OpenClaw</span>
        </div>
        <button onClick={loadAgents} className="text-gray-400 hover:text-white transition-colors" title="Actualiser">🔄</button>
      </div>

      {/* Agent grid */}
      <div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
        {agents.map(agent => (
          <div
            key={agent.name}
            className={`glass-card overflow-hidden transition-all duration-300 ${
              expandedAgent === agent.name ? 'ring-1 ring-purple-500/30' : ''
            }`}
          >
            <div
              className={`p-5 cursor-pointer hover:bg-glass-hover transition-colors ${deleting === agent.name ? 'opacity-50 pointer-events-none' : ''}`}
              onClick={() => { 
                setExpandedAgent(expandedAgent === agent.name ? null : agent.name); 
                setActiveFile(null); 
                setIsFullscreen(false); 
                setActiveView('identity');
              }}
            >
              <div className="flex items-start justify-between">
                <div className="flex items-center gap-3">
                  <div className="w-10 h-10 rounded-xl bg-gradient-to-br from-amber-500/20 to-orange-600/10 border border-amber-500/20 flex items-center justify-center text-xl shrink-0">
                    🤖
                  </div>
                  <div className="min-w-0">
                    <h3 className="text-white font-semibold text-sm truncate pr-2">{agent.name}</h3>
                    <div className="flex items-center gap-2 mt-1 flex-wrap">
                      <span className="badge bg-surface-600 text-gray-300 text-[10px]">{agent.type}</span>
                      {agent.model && (
                        <span className="badge bg-purple-500/15 text-purple-300 text-[10px] truncate max-w-[150px]">{agent.model}</span>
                      )}
                      {agent.has_workspace && (
                        <span className="badge bg-green-500/15 text-green-300 text-[10px]" title="A un dossier workspace défini">ws ✓</span>
                      )}
                    </div>
                  </div>
                </div>
                <div className="flex items-center gap-2 shrink-0">
                  <button 
                    onClick={(e) => handleDelete(e, agent.name)}
                    className="p-1.5 rounded-lg text-gray-500 hover:text-red-400 hover:bg-red-400/10 transition-colors"
                    title="Supprimer l'agent"
                  >
                    🗑️
                  </button>
                  <span className="text-gray-600 text-sm ml-2 w-4 text-center">
                    {expandedAgent === agent.name ? '▲' : '▼'}
                  </span>
                </div>
              </div>
            </div>

            {/* Expanded details */}
            {expandedAgent === agent.name && (
              <div className="border-t border-glass-border p-5 bg-surface-900/40 space-y-6">
                
                {/* View Tabs */}
                <div className="flex gap-2 border-b border-surface-700/50 pb-3 -mx-2 px-2">
                  <button 
                    onClick={() => setActiveView('identity')}
                    className={`px-4 py-2 rounded-lg text-sm font-medium transition-all flex items-center gap-2 ${activeView === 'identity' ? 'bg-surface-800 text-white border border-surface-600 shadow-md' : 'text-gray-500 hover:text-gray-300 hover:bg-surface-800/50'}`}
                  >
                    <span>🗂️</span> Paramètres & Fichiers
                  </button>
                  <button 
                    onClick={() => setActiveView('memory')}
                    className={`px-4 py-2 rounded-lg text-sm font-medium transition-all flex items-center gap-2 ${activeView === 'memory' ? 'bg-indigo-900/30 text-indigo-300 border border-indigo-500/20 shadow-[0_0_15px_rgba(79,70,229,0.1)]' : 'text-gray-500 hover:text-indigo-400 hover:bg-indigo-900/10'}`}
                  >
                    <span>🧠</span> Mémoires d'agent
                  </button>
                </div>

                {activeView === 'memory' ? (
                  <AgentMemoryViewer agentName={agent.name} />
                ) : (
                  <>
                    {/* Agent Identity Files Manager */}
                    {agent.has_workspace && agent.identity_files && agent.identity_files.length > 0 && (
                      <div>
                        <h4 className="text-xs text-gray-400 font-bold uppercase tracking-wider mb-3 flex items-center gap-2">
                          <span>⚙️</span> Fichiers d'identité
                        </h4>
                        <div className="flex gap-2 flex-wrap mb-3">
                      {agent.identity_files.map(file => {
                        const isActive = activeFile?.agent === agent.name && activeFile?.file === file.name;
                        return (
                          <button
                            key={file.name}
                            onClick={() => openFile(agent.name, file.name)}
                            className={`px-3 py-1.5 rounded-lg text-xs font-mono transition-all ${
                              isActive 
                                ? 'bg-gradient-to-r from-purple-600 to-indigo-600 text-white shadow-[0_0_10px_rgba(147,51,234,0.3)]' 
                                : file.size > 0 
                                  ? 'bg-surface-800 text-gray-300 border border-surface-600 hover:border-purple-500/50 hover:bg-surface-700'
                                  : 'bg-surface-800 text-gray-600 border border-surface-700/50 opacity-60 hover:opacity-100 hover:text-gray-400'
                            }`}
                          >
                            {file.name}
                            {file.size > 0 && <span className="ml-1.5 opacity-60 text-[9px]">{formatSize(file.size)}</span>}
                          </button>
                        );
                      })}
                    </div>
                    
                    {/* Identity File Editor */}
                    {activeFile?.agent === agent.name && (
                      <div className={`border border-glass-border bg-[#282c34] overflow-hidden shadow-inner mt-4 animate-fade-in flex flex-col ${
                        isFullscreen ? 'fixed inset-0 w-screen h-screen z-[9999] m-0 p-0 rounded-none' : 'h-[500px] rounded-xl relative'
                      }`}>
                        <div className={`flex items-center justify-between px-3 py-2 bg-surface-900/80 border-b border-glass-border shrink-0 ${isFullscreen ? 'h-14 px-6' : ''}`}>
                          <span className="text-xs font-mono text-purple-300 truncate pr-4">workspace/{agent.name}/{activeFile.file}</span>
                          <div className="flex gap-2 shrink-0">
                            <button onClick={() => setIsFullscreen(!isFullscreen)} className="px-2 py-1 rounded text-[10px] text-gray-400 hover:bg-surface-700 hover:text-white transition-colors">
                              {isFullscreen ? '🗗 Réduire' : '⛶ Plein écran'}
                            </button>
                            <button onClick={() => { setActiveFile(null); setIsFullscreen(false); }} className="px-2 py-1 rounded text-[10px] text-gray-400 hover:bg-surface-700 hover:text-white transition-colors">
                              Fermer
                            </button>
                            <button onClick={saveFile} disabled={saving} className="px-3 py-1 rounded bg-purple-600/80 hover:bg-purple-500 text-white text-[10px] font-medium transition-colors">
                              {saving ? '...' : 'Sauvegarder'}
                            </button>
                          </div>
                        </div>
                        {fileLoading ? (
                          <div className="flex-1 flex items-center justify-center text-gray-500 text-sm animate-pulse">Chargement…</div>
                        ) : (
                          <div className="flex-1 overflow-hidden relative min-h-0 bg-[#282c34]">
                            <div className="absolute inset-0 custom-scrollbar [&_.cm-editor]:h-full [&_.cm-editor]:bg-transparent [&_.cm-scroller]:h-full [&_.cm-scroller]:overflow-auto [&_.cm-scroller]:font-mono [&_.cm-scroller]:text-xs pb-10">
                              <CodeMirror
                                value={fileContent}
                                height="100%"
                                theme={oneDark}
                                extensions={[markdown()]}
                                onChange={(val) => setFileContent(val)}
                                basicSetup={{ lineNumbers: true, foldGutter: false, highlightActiveLine: true, tabSize: 2 }}
                              />
                            </div>
                          </div>
                        )}
                      </div>
                    )}
                  </div>
                )}

                {/* System Prompt (Read-only overlay for old config style) */}
                {agent.system_prompt && !activeFile && (
                  <div>
                    <h4 className="text-xs text-gray-400 font-bold uppercase tracking-wider mb-2">Instructions principales</h4>
                    <div className="px-4 py-3 rounded-xl bg-surface-800/80 text-xs text-gray-300 font-mono whitespace-pre-wrap max-h-48 overflow-y-auto leading-relaxed custom-scrollbar border border-surface-700/50">
                      {agent.system_prompt}
                    </div>
                  </div>
                )}
                
                {/* Configuration (Read-only) */}
                {agent.config && !activeFile && activeView === 'identity' && (
                  <div>
                    <h4 className="text-xs text-gray-400 font-bold uppercase tracking-wider mb-2 flex justify-between items-center">
                      <span>Configuration JSON/YAML</span>
                      <span className="font-mono lowercase text-[10px] text-gray-500">{agent.config_files?.join(', ')}</span>
                    </h4>
                    <pre className="px-4 py-3 rounded-xl bg-surface-800/80 text-[11px] text-gray-400 font-mono whitespace-pre-wrap max-h-64 overflow-y-auto leading-relaxed custom-scrollbar border border-surface-700/50">
                      {JSON.stringify(agent.config, null, 2)}
                    </pre>
                  </div>
                )}
                  </>
                )}
              </div>
            )}
          </div>
        ))}
      </div>
    </div>
  );
}


// ═════════════════════════════════════════════════════════════════════════════════
// Tab 4 — Skills
// ═════════════════════════════════════════════════════════════════════════════════

function SkillsTab() {
  const [skills, setSkills] = useState<OpenClawSkill[]>([]);
  const [loading, setLoading] = useState(true);
  const [expandedSkill, setExpandedSkill] = useState<string | null>(null);

  useEffect(() => {
    api.openclawSkills()
      .then(d => { setSkills(d.skills); setLoading(false); })
      .catch(() => setLoading(false));
  }, []);

  if (loading) return <LoadingSpinner />;
  if (skills.length === 0) return <EmptyState message="Aucun skill trouvé" />;

  return (
    <div className="space-y-4">
      <div className="glass-card p-4 flex items-center gap-3">
        <span className="text-lg">🧩</span>
        <span className="text-white font-semibold">{skills.length} skills</span>
        <span className="text-gray-500 text-sm">disponibles</span>
      </div>

      <div className="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-4">
        {skills.map(skill => (
          <div
            key={`${skill.source}/${skill.name}`}
            className="glass-card overflow-hidden"
          >
            <div
              className="p-5 cursor-pointer hover:bg-glass-hover transition-colors"
              onClick={() => setExpandedSkill(expandedSkill === skill.name ? null : skill.name)}
            >
              <div className="flex items-start justify-between">
                <div className="flex items-center gap-3">
                  <div className="w-10 h-10 rounded-xl bg-gradient-to-br from-indigo-500/20 to-blue-600/10 border border-indigo-500/20 flex items-center justify-center text-xl">
                    🧩
                  </div>
                  <div>
                    <h3 className="text-white font-semibold text-sm">{skill.name}</h3>
                    <div className="flex items-center gap-2 mt-1">
                      <span className="badge bg-surface-600 text-gray-300 text-[10px]">{skill.type}</span>
                      <span className="text-[10px] text-gray-600 font-mono">{skill.source}</span>
                    </div>
                  </div>
                </div>
              </div>

              {skill.description_short && (
                <p className="text-xs text-gray-400 mt-3 leading-relaxed">{skill.description_short}</p>
              )}

              {skill.subdirs && skill.subdirs.length > 0 && (
                <div className="flex gap-1.5 mt-3 flex-wrap">
                  {skill.subdirs.map(d => (
                    <span key={d} className="px-2 py-0.5 rounded-md bg-surface-700 text-gray-400 text-[10px] font-mono">📁 {d}</span>
                  ))}
                </div>
              )}

              <div className="flex items-center gap-3 mt-3 text-[10px] text-gray-600">
                {skill.file_count != null && <span>{skill.file_count} fichiers</span>}
                {skill.size != null && <span>{formatSize(skill.size)}</span>}
              </div>
            </div>

            {expandedSkill === skill.name && skill.description && (
              <div className="border-t border-glass-border p-4 bg-surface-900/40">
                <h4 className="text-xs text-gray-500 uppercase tracking-wider mb-2">Description</h4>
                <pre className="text-xs text-gray-300 font-mono whitespace-pre-wrap max-h-48 overflow-y-auto leading-relaxed">
                  {skill.description}
                </pre>
              </div>
            )}
          </div>
        ))}
      </div>
    </div>
  );
}


// ═════════════════════════════════════════════════════════════════════════════════
// Tab 5 — Logs (Terminal style)
// ═════════════════════════════════════════════════════════════════════════════════

function LogsTab() {
  const [logs, setLogs] = useState<OpenClawLogs | null>(null);
  const [loading, setLoading] = useState(true);
  const [levelFilter, setLevelFilter] = useState<string>('');
  const [lineCount, setLineCount] = useState(200);
  const [autoRefresh, setAutoRefresh] = useState(false);
  const logEndRef = useRef<HTMLDivElement>(null);

  const fetchLogs = useCallback(async () => {
    try {
      const params: { lines: number; level?: string } = { lines: lineCount };
      if (levelFilter) params.level = levelFilter;
      const data = await api.openclawLogs(params);
      setLogs(data);
    } catch { /* ignore */ }
    setLoading(false);
  }, [lineCount, levelFilter]);

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

  useEffect(() => {
    if (!autoRefresh) return;
    const interval = setInterval(fetchLogs, 5000);
    return () => clearInterval(interval);
  }, [autoRefresh, fetchLogs]);

  useEffect(() => {
    if (logEndRef.current) {
      logEndRef.current.scrollIntoView({ behavior: 'smooth' });
    }
  }, [logs]);

  function getLineStyle(line: string): string {
    const upper = line.toUpperCase();
    if (upper.includes('ERROR') || upper.includes('FATAL') || upper.includes('PANIC')) return 'text-red-400';
    if (upper.includes('WARN')) return 'text-yellow-400';
    if (upper.includes('DEBUG') || upper.includes('TRACE')) return 'text-gray-600';
    if (upper.includes('INFO')) return 'text-green-300';
    return 'text-gray-400';
  }

  return (
    <div className="space-y-4">
      {/* Toolbar */}
      <div className="glass-card p-4 flex items-center gap-3 flex-wrap">
        <span className="text-lg">📟</span>
        <span className="text-white font-semibold text-sm">Gateway Logs</span>

        <div className="flex-1" />

        {/* Level filter */}
        <div className="flex gap-1">
          {['', 'INFO', 'WARNING', 'ERROR'].map(lvl => (
            <button
              key={lvl}
              onClick={() => setLevelFilter(lvl)}
              className={`px-3 py-1.5 rounded-lg text-xs font-medium transition-all ${
                levelFilter === lvl
                  ? 'bg-purple-500/20 text-purple-300 border border-purple-500/30'
                  : 'text-gray-500 hover:text-gray-300 bg-surface-700/50'
              }`}
            >
              {lvl || 'Tous'}
            </button>
          ))}
        </div>

        {/* Line count */}
        <select
          value={lineCount}
          onChange={e => setLineCount(Number(e.target.value))}
          className="input !w-auto !py-1.5 text-xs"
        >
          <option value={50}>50 lignes</option>
          <option value={200}>200 lignes</option>
          <option value={500}>500 lignes</option>
          <option value={1000}>1000 lignes</option>
        </select>

        {/* Auto-refresh toggle */}
        <button
          onClick={() => setAutoRefresh(!autoRefresh)}
          className={`px-3 py-1.5 rounded-lg text-xs font-medium transition-all ${
            autoRefresh
              ? 'bg-green-500/20 text-green-300 border border-green-500/30'
              : 'text-gray-500 bg-surface-700/50'
          }`}
        >
          {autoRefresh ? '⏸ Auto' : '▶ Auto'}
        </button>

        {/* Refresh button */}
        <button onClick={fetchLogs} className="btn btn-ghost text-xs !py-1.5">
          🔄 Refresh
        </button>
      </div>

      {/* Terminal */}
      {loading ? <LoadingSpinner /> : (
        <div className="rounded-2xl overflow-hidden border border-glass-border">
          {/* Terminal header */}
          <div className="flex items-center gap-3 px-4 py-2.5 bg-surface-800 border-b border-glass-border">
            <div className="flex gap-1.5">
              <span className="w-3 h-3 rounded-full bg-red-500/60"></span>
              <span className="w-3 h-3 rounded-full bg-yellow-500/60"></span>
              <span className="w-3 h-3 rounded-full bg-green-500/60"></span>
            </div>
            <span className="text-xs text-gray-500 font-mono flex-1">
              {logs?.log_path || 'gateway.log'}
            </span>
            {logs && (
              <span className="text-[10px] text-gray-600">
                {logs.showing} / {logs.total_lines} lignes
              </span>
            )}
          </div>

          {/* Terminal content */}
          <div className="p-4 max-h-[600px] overflow-y-auto font-mono text-xs leading-5"
            style={{ background: '#0a0e17' }}
          >
            {logs?.error && (
              <div className="text-red-400 mb-3 p-2 rounded-lg bg-red-500/10">{logs.error}</div>
            )}
            {(!logs?.lines || logs.lines.length === 0) ? (
              <div className="text-gray-600">Aucune ligne de log</div>
            ) : (
              logs.lines.map((line, i) => (
                <div key={i} className={`hover:bg-white/[0.02] px-1 rounded ${getLineStyle(line)}`}>
                  <span className="text-gray-700 select-none mr-3 inline-block w-10 text-right">{i + 1}</span>
                  {line}
                </div>
              ))
            )}
            <div ref={logEndRef} />
          </div>
        </div>
      )}
    </div>
  );
}


// ═════════════════════════════════════════════════════════════════════════════════
// Tab 6 — Models & Providers
// ═════════════════════════════════════════════════════════════════════════════════

function ModelsTab() {
  const [data, setData] = useState<OpenClawModels | null>(null);
  const [loading, setLoading] = useState(true);
  const [editing, setEditing] = useState(false);

  const fetchModels = () => {
    setLoading(true);
    api.openclawModels()
      .then(d => { setData(d); setLoading(false); })
      .catch(() => setLoading(false));
  };

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

  if (loading) return <LoadingSpinner />;
  if (!data || data.error) return <EmptyState message={data?.error || 'Impossible de charger les modèles'} />;

  return (
    <div className="space-y-6 animate-fade-in">
      {editing && <ConfigFileEditor onClose={() => setEditing(false)} onSave={() => { setEditing(false); fetchModels(); }} />}

      {/* Premium Header */}
      <div className="flex flex-col sm:flex-row items-start sm:items-center justify-between glass-card p-6 border-l-4 border-l-cyan-500 relative overflow-hidden group">
        <div className="absolute top-0 right-0 w-64 h-full bg-gradient-to-l from-cyan-500/10 to-transparent opacity-50 group-hover:opacity-100 transition-opacity"></div>
        <div className="relative z-10 mb-4 sm:mb-0">
          <h2 className="text-xl font-bold text-white flex items-center gap-3">
            <span>🧠</span> Intelligence Artificielle (LLMs & MCP)
          </h2>
          <p className="text-gray-400 text-sm mt-1.5 flex items-center gap-2">
            Fournisseurs, serveurs MCP et modèles configurés
          </p>
        </div>
        <div className="relative z-10 shrink-0">
          <button 
            onClick={() => setEditing(true)}
            className="px-5 py-2.5 rounded-xl bg-gradient-to-r from-cyan-600 to-blue-600 text-white text-sm font-semibold hover:from-cyan-500 hover:to-blue-500 transition-all shadow-[0_0_15px_rgba(6,182,212,0.3)] hover:scale-105 flex items-center gap-2"
          >
            <span>✏️</span> Configurer Modèles
          </button>
        </div>
      </div>

      {/* Providers Grid */}
      {data.providers.length > 0 && (
        <div className="glass-card overflow-hidden">
          <div className="p-5 bg-surface-800/50 border-b border-glass-border">
            <h2 className="text-base font-bold text-white flex items-center gap-2">
              <span className="text-cyan-400">🔌</span> Providers / MCP Servers
            </h2>
          </div>
          <div className="p-5 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
            {data.providers.map((p, i) => (
              <div key={i} className="p-5 rounded-xl bg-surface-900/60 border border-surface-700/50 hover:border-cyan-500/30 transition-all hover:bg-surface-800/80 group">
                <div className="flex items-center gap-3 mb-3 relative">
                  <div className="w-10 h-10 rounded-xl bg-gradient-to-br from-cyan-500/20 to-blue-600/10 border border-cyan-500/20 flex items-center justify-center text-lg shadow-inner group-hover:scale-110 transition-transform">
                    {p.type === 'mcp' ? '🧱' : '💬'}
                  </div>
                  <div className="flex-1 min-w-0">
                    <h3 className="text-white font-bold text-sm truncate pr-2" title={String(p.name || `Provider ${i + 1}`)}>
                      {String(p.name || `Provider ${i + 1}`)}
                    </h3>
                    <div className="flex items-center gap-2 mt-1">
                      {Boolean(p.type) && (
                        <span className="px-2 py-0.5 rounded text-[9px] uppercase tracking-wider font-bold bg-surface-700 text-gray-300">
                          {String(p.type)}
                        </span>
                      )}
                      {p.enabled !== undefined && (
                        <span className={`px-2 py-0.5 rounded text-[9px] uppercase tracking-wider font-bold ${p.enabled ? 'bg-emerald-500/20 text-emerald-300' : 'bg-red-500/20 text-red-300'}`}>
                          {p.enabled ? 'actif' : 'inactif'}
                        </span>
                      )}
                    </div>
                  </div>
                </div>
                {Boolean(p.model) && (
                  <div className="text-xs text-blue-300 font-mono mt-2 bg-blue-500/10 px-3 py-1.5 rounded-lg border border-blue-500/10 inline-block truncate max-w-full">
                    <span className="opacity-50 mr-1">modèle:</span> {String(p.model)}
                  </div>
                )}
                {Boolean(p.endpoint) && (
                  <div className="text-[11px] text-gray-500 font-mono mt-2 bg-surface-800 px-3 py-1.5 rounded-lg truncate max-w-full border border-surface-700">
                    {String(p.endpoint)}
                  </div>
                )}
              </div>
            ))}
          </div>
        </div>
      )}

      {/* Models Table */}
      {data.models.length > 0 && (
        <div className="glass-card overflow-hidden">
          <div className="p-5 bg-surface-800/50 border-b border-glass-border">
            <h2 className="text-base font-bold text-white flex items-center gap-2">
              <span className="text-purple-400">🤖</span> Modèles Configurés
            </h2>
          </div>
          <div className="overflow-x-auto">
            <table className="w-full text-sm">
              <thead className="bg-surface-900/80">
                <tr>
                  <th className="text-left text-[11px] text-gray-400 font-bold uppercase tracking-wider py-4 px-6 border-b border-surface-700/50 w-1/4">Identifiant Modèle</th>
                  <th className="text-left text-[11px] text-gray-400 font-bold uppercase tracking-wider py-4 px-6 border-b border-surface-700/50">Détails configuration (JSON)</th>
                </tr>
              </thead>
              <tbody className="divide-y divide-surface-700/50">
                {data.models.map((m, i) => (
                  <tr key={i} className="hover:bg-surface-800/40 transition-colors">
                    <td className="py-4 px-6 align-top">
                      <div className="flex items-center gap-3">
                        <span className="text-lg opacity-80">🏷️</span>
                        <span className="text-white font-bold bg-surface-800 px-3 py-1.5 rounded-lg border border-surface-600 shadow-sm inline-block">
                          {String(m.name || `Model ${i + 1}`)}
                        </span>
                      </div>
                    </td>
                    <td className="py-4 px-6">
                      <pre className="text-[11px] text-[#abb2bf] font-mono whitespace-pre-wrap leading-relaxed bg-[#1e222a] p-4 rounded-xl border border-surface-700 shadow-inner">
                        {JSON.stringify(m, null, 2)}
                      </pre>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      )}

      {/* Raw config keys */}
      {data.raw_keys && data.raw_keys.length > 0 && (
        <div className="glass-card p-5 flex items-center gap-4 flex-wrap">
          <h2 className="text-xs font-bold text-gray-500 uppercase tracking-wider flex items-center gap-2 shrink-0">
            <span>🔑</span> Clés racines détectées :
          </h2>
          <div className="flex gap-2 flex-wrap">
            {data.raw_keys.map(k => (
              <span key={k} className="px-2 py-1 rounded bg-surface-800 text-gray-400 text-[10px] font-mono border border-surface-700">{k}</span>
            ))}
          </div>
        </div>
      )}

      {data.providers.length === 0 && data.models.length === 0 && (
        <EmptyState message="Aucun modèle ou provider détecté dans la configuration" />
      )}
    </div>
  );
}


// ═════════════════════════════════════════════════════════════════════════════════
// Shared Components
// ═════════════════════════════════════════════════════════════════════════════════

function LoadingSpinner() {
  return (
    <div className="flex items-center justify-center h-48">
      <div className="text-center">
        <div className="text-3xl animate-spin-slow mb-2">🐙</div>
        <div className="text-gray-600 text-xs">Chargement…</div>
      </div>
    </div>
  );
}

function EmptyState({ message }: { message: string }) {
  return (
    <div className="glass-card p-12 text-center">
      <div className="text-4xl mb-3 opacity-40">🐙</div>
      <p className="text-gray-500 text-sm">{message}</p>
    </div>
  );
}

// ═════════════════════════════════════════════════════════════════════════════════
// Shared Config Editor Overlay
// ═════════════════════════════════════════════════════════════════════════════════

function ConfigFileEditor({ onClose, onSave }: { onClose: () => void, onSave: () => void }) {
  const [content, setContent] = useState('');
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);

  useEffect(() => {
    // Lock body scroll
    document.body.style.overflow = 'hidden';
    
    api.openclawReadFile('openclaw.json')
      .then(res => {
        setContent(res.pretty || res.content || '');
        setLoading(false);
      })
      .catch(err => {
        console.error(err);
        setContent('Erreur de chargement du fichier openclaw.json');
        setLoading(false);
      });

    return () => {
      // Restore scroll when unmounting
      document.body.style.overflow = '';
    };
  }, []);

  const handleSave = async () => {
    setSaving(true);
    try {
      await api.openclawWriteFile('openclaw.json', content);
      onSave();
    } catch (err) {
      console.error(err);
      alert('Erreur lors de la sauvegarde : ' + String(err));
    } finally {
      setSaving(false);
    }
  };

  return (
    <div className="fixed inset-0 w-screen h-screen z-[9999] m-0 p-0 rounded-none glass-card flex flex-col overflow-hidden border border-glass-border shadow-[0_40px_80px_rgb(0,0,0,0.9)] bg-surface-900/95 backdrop-blur-xl animate-fade-in">
      <div className="flex items-center justify-between px-6 py-4 bg-surface-800 border-b border-glass-border shrink-0 h-16">
        <div className="flex items-center gap-3">
          <div className="w-10 h-10 rounded-xl bg-gradient-to-br from-amber-500/20 to-orange-600/10 border border-amber-500/20 flex items-center justify-center text-xl">
            ✏️
          </div>
          <div>
            <h3 className="text-white font-bold text-base flex items-center gap-2">
              Édition directe
            </h3>
            <div className="text-xs text-gray-400 font-mono mt-0.5">openclaw.json</div>
          </div>
        </div>
        
        <div className="flex gap-3">
          <button 
            onClick={onClose} 
            disabled={saving}
            className="px-4 py-2 rounded-lg bg-surface-700 text-gray-300 text-sm font-medium hover:bg-surface-600 transition-colors"
          >
            Annuler
          </button>
          <button 
            onClick={handleSave} 
            disabled={saving}
            className={`px-6 py-2 rounded-lg bg-gradient-to-r from-emerald-600 to-teal-600 text-white text-sm font-bold transition-all shadow-[0_0_15px_rgba(16,185,129,0.4)] flex items-center gap-2 ${saving ? 'opacity-50 scale-95 cursor-wait' : 'hover:scale-105 hover:from-emerald-500 hover:to-teal-500'}`}
          >
            {saving ? 'Sauvegarde...' : '💾 Sauvegarder .json'}
          </button>
        </div>
      </div>

      <div className="flex-1 overflow-hidden relative bg-[#282c34]">
        {loading ? (
          <div className="absolute inset-0 flex items-center justify-center flex-col gap-4">
            <span className="text-4xl animate-spin-slow opacity-50">⚙️</span>
            <span className="text-gray-400 font-mono">Lecture de la configuration brute...</span>
          </div>
        ) : (
          <div className="h-full w-full absolute inset-0 [&_.cm-editor]:h-full [&_.cm-scroller]:h-full [&_.cm-scroller]:overflow-auto [&_.cm-scroller]:font-mono [&_.cm-scroller]:text-[13px] custom-scrollbar pb-10">
            <CodeMirror
              value={content}
              height="100%"
              theme={oneDark}
              extensions={[json()]}
              onChange={(val) => setContent(val)}
              basicSetup={{
                lineNumbers: true,
                foldGutter: true,
                highlightActiveLine: true,
                tabSize: 2,
              }}
            />
          </div>
        )}
      </div>
    </div>
  );
}



// ═════════════════════════════════════════════════════════════════════════════════
// Tab 7 — Filesystem (Arborescence)
// ═════════════════════════════════════════════════════════════════════════════════

function FilesystemTab() {
  const [tree, setTree] = useState<FileTreeNode[]>([]);
  const [treeLoading, setTreeLoading] = useState(true);
  const [selectedFile, setSelectedFile] = useState<ReadFileResult | null>(null);
  const [fileLoading, setFileLoading] = useState(false);
  const [editMode, setEditMode] = useState(false);
  const [editContent, setEditContent] = useState('');
  const [saving, setSaving] = useState(false);
  const [isFullscreen, setIsFullscreen] = useState(false);

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

  const loadTree = () => {
    setTreeLoading(true);
    api.openclawFilesystem()
      .then(d => { setTree(d.tree); setTreeLoading(false); })
      .catch(() => setTreeLoading(false));
  };

  const handleSelectFile = async (node: FileTreeNode) => {
    if (node.type !== 'file') return;
    setFileLoading(true);
    setEditMode(false);
    try {
      const data = await api.openclawReadFile(node.path);
      setSelectedFile(data);
      setEditContent(data.pretty || data.content || '');
    } catch (err) {
      console.error(err);
    } finally {
      setFileLoading(false);
    }
  };

  const handleSave = async () => {
    if (!selectedFile) return;
    setSaving(true);
    try {
      await api.openclawWriteFile(selectedFile.path, editContent);
      const data = await api.openclawReadFile(selectedFile.path);
      setSelectedFile(data);
      setEditMode(false);
    } catch (err) {
      console.error(err);
    } finally {
      setSaving(false);
    }
  };

  const getExtensions = () => {
    if (!selectedFile) return [];
    const lang = selectedFile.language;
    if (lang === 'json') return [json()];
    if (lang === 'markdown') return [markdown()];
    if (lang === 'yaml') return [yaml()];
    return [];
  };

  return (
    <div className="flex gap-6 h-[calc(100vh-250px)] min-h-[600px]">
      {/* Sidebar Tree */}
      <div className="glass-card w-1/3 p-4 flex flex-col border border-glass-border">
        <div className="flex items-center justify-between mb-4 px-2">
          <h2 className="text-lg font-bold text-white flex items-center gap-2">
            <span>📂</span> Arborescence
          </h2>
          <button onClick={loadTree} className="p-1.5 rounded-lg text-gray-400 hover:text-white hover:bg-surface-700 transition-colors" title="Actualiser">🔄</button>
        </div>
        <div className="flex-1 overflow-y-auto font-mono text-[13px] pr-2 custom-scrollbar">
          {treeLoading ? (
            <div className="text-gray-500 animate-pulse px-2">Chargement de l'arborescence…</div>
          ) : tree.length === 0 ? (
            <p className="text-gray-500 px-2">Aucun fichier trouvé</p>
          ) : (
            <div className="space-y-0.5">
              {tree.map(node => (
                <TreeNode key={node.path} node={node} depth={0} onSelect={handleSelectFile} />
              ))}
            </div>
          )}
        </div>
      </div>

      {/* Editor Panel */}
      <div className={isFullscreen 
        ? "fixed inset-0 w-screen h-screen z-[9999] m-0 p-0 rounded-none glass-card flex flex-col overflow-hidden border border-glass-border bg-surface-900 shadow-[0_30px_60px_rgb(0,0,0,0.9)] min-h-0" 
        : "glass-card w-2/3 flex flex-col overflow-hidden border border-glass-border shadow-[0_8px_30px_rgb(0,0,0,0.5)] min-h-0"
      }>
        {fileLoading ? (
          <div className="flex-1 flex items-center justify-center bg-surface-900/40">
            <div className="text-gray-400 flex flex-col items-center gap-3">
              <span className="text-3xl animate-spin-slow">⏳</span>
              <span className="text-sm tracking-wide">Ouverture du fichier…</span>
            </div>
          </div>
        ) : !selectedFile ? (
          <div className="flex-1 flex items-center justify-center text-gray-500 flex-col gap-4 bg-surface-900/40">
            <span className="text-5xl opacity-30 grayscale">📄</span>
            <p className="tracking-wide">Sélectionnez un fichier pour le visualiser</p>
          </div>
        ) : (
          <div className="flex flex-col h-full">
            {/* Editor Header */}
            <div className={`p-4 bg-surface-800 border-b border-glass-border flex items-center justify-between z-10 shrink-0 ${isFullscreen ? 'h-16 px-6' : ''}`}>
              <div className="min-w-0 pr-4">
                <h3 className="text-white font-medium flex items-center gap-2 text-base truncate">
                  <span className="text-xl">📄</span> {selectedFile.path.split('/').pop()}
                </h3>
                <div className="flex items-center gap-3 mt-1 text-[11px] text-gray-400 font-mono">
                  <span className="truncate max-w-[200px] md:max-w-xs" title={selectedFile.path}>{selectedFile.path}</span>
                  <span className="opacity-50">•</span>
                  <span>{formatSize(selectedFile.size)}</span>
                  <span className="opacity-50">•</span>
                  <span className="uppercase text-purple-300 bg-purple-500/10 px-1.5 py-0.5 rounded">{selectedFile.language}</span>
                </div>
              </div>
              <div className="flex gap-2 shrink-0">
                <button 
                  onClick={() => setIsFullscreen(!isFullscreen)} 
                  className="px-3 py-1.5 rounded-lg bg-surface-700 text-gray-300 text-sm hover:bg-surface-600 transition-colors flex items-center justify-center font-bold"
                  title={isFullscreen ? "Réduire" : "Plein écran"}
                >
                  {isFullscreen ? "🗗" : "⛶"}
                </button>
                {!selectedFile.binary && (
                  <>
                    {editMode ? (
                      <>
                        <button onClick={() => setEditMode(false)} disabled={saving} className="px-3.5 py-1.5 rounded-lg bg-surface-700 text-gray-300 text-sm hover:bg-surface-600 transition-colors">
                          Annuler
                        </button>
                        <button onClick={handleSave} disabled={saving} className={`px-4 py-1.5 rounded-lg bg-gradient-to-r from-emerald-600 to-teal-600 text-white text-sm font-medium hover:from-emerald-500 hover:to-teal-500 transition-all shadow-[0_0_12px_rgba(16,185,129,0.3)] flex items-center gap-2 ${saving ? 'opacity-50 cursor-not-allowed scale-95' : 'hover:scale-105'}`}>
                          {saving ? 'Sauvegarde…' : '💾 Sauvegarder'}
                        </button>
                      </>
                    ) : (
                      <button onClick={() => { setEditMode(true); setEditContent(selectedFile.pretty || selectedFile.content || ''); }} className="px-4 py-1.5 rounded-lg bg-gradient-to-r from-purple-600 to-indigo-600 text-white text-sm font-medium hover:from-purple-500 hover:to-indigo-500 transition-all shadow-[0_0_12px_rgba(147,51,234,0.3)] hover:scale-105 flex items-center gap-2">
                        <span>✏️</span> Modifier
                      </button>
                    )}
                  </>
                )}
              </div>
            </div>

            {/* Editor Body */}
            <div className="flex-1 overflow-hidden relative bg-[#282c34]">
              {selectedFile.binary ? (
                <div className="absolute inset-0 flex items-center justify-center text-gray-500 bg-surface-900/60">
                  <div className="text-center">
                    <div className="text-5xl mb-3 opacity-30">📦</div>
                    <p className="tracking-wide">Fichier binaire. Aperçu non disponible.</p>
                  </div>
                </div>
              ) : editMode ? (
                <div className="h-full w-full absolute inset-0 [&_.cm-editor]:h-full [&_.cm-scroller]:h-full [&_.cm-scroller]:overflow-auto [&_.cm-scroller]:font-mono [&_.cm-scroller]:text-[13px] pb-10">
                  <CodeMirror
                    value={editContent}
                    height="100%"
                    theme={oneDark}
                    extensions={getExtensions()}
                    onChange={(val) => setEditContent(val)}
                    basicSetup={{
                      lineNumbers: true,
                      foldGutter: true,
                      highlightActiveLine: true,
                      tabSize: 2,
                    }}
                  />
                </div>
              ) : (
                <div className="h-full overflow-y-auto w-full custom-scrollbar absolute inset-0">
                  <div className="p-4 min-h-full">
                    <pre className="text-[13px] text-[#abb2bf] font-mono whitespace-pre-wrap leading-relaxed">
                      {selectedFile.pretty || selectedFile.content}
                    </pre>
                  </div>
                </div>
              )}
            </div>
          </div>
        )}
      </div>
    </div>
  );
}
