import React, { useEffect, useState, useRef } from 'react';
import { getNodeStreamUrl } from '../../services/apiService';
import { Terminal } from '@xterm/xterm';
import { FitAddon } from '@xterm/addon-fit';
import '@xterm/xterm/css/xterm.css';

// Sub-component for each terminal window to encapsulate Xterm.js logic
const TerminalNodeItem = ({ nodeId, stats, onMount, onUnmount, nodeConfig, isAIProcessing, thoughtHistory = [] }) => {
    const terminalRef = useRef(null);
    const xtermRef = useRef(null);
    const fitAddonRef = useRef(null);
    const [isDetailsExpanded, setIsDetailsExpanded] = useState(false);

    const sandbox = nodeConfig?.skill_config?.shell?.sandbox || {};
    const mode = sandbox.mode || 'PASSIVE';
    const isStrict = mode === 'STRICT';

    // UI Feedback: boundary color & pulse logic
    const borderClass = isStrict
        ? (isAIProcessing ? 'border-red-500/80 ring-1 ring-red-500/40 animate-[pulse-red_2s_infinite]' : 'border-red-900/50')
        : (isAIProcessing ? 'border-blue-500/80 ring-1 ring-blue-500/40 animate-[pulse-blue_2s_infinite]' : 'border-blue-900/50');

    const statusDotClass = isStrict ? 'bg-rose-500' : 'bg-blue-500';

    useEffect(() => {
        const xterm = new Terminal({
            theme: {
                background: '#030712',
                foreground: '#e6edf3',
                cursor: isAIProcessing ? '#388bfd' : '#22c55e',
                selectionBackground: '#388bfd',
            },
            fontSize: 12,
            fontFamily: 'Menlo, Monaco, "Courier New", monospace',
            cursorBlink: isAIProcessing,
            cursorStyle: 'block',
            convertEol: true,
            scrollback: 1000,
            disableStdin: true,
            scrollOnOutput: true,
        });

        const fitAddon = new FitAddon();
        xterm.loadAddon(fitAddon);
        xterm.open(terminalRef.current);
        setTimeout(() => fitAddon.fit(), 10);

        xtermRef.current = xterm;
        fitAddonRef.current = fitAddon;
        onMount(nodeId, xterm);

        const observer = new ResizeObserver(() => fitAddon.fit());
        if (terminalRef.current) observer.observe(terminalRef.current);

        return () => {
            observer.disconnect();
            onUnmount(nodeId);
            xterm.dispose();
        };
    }, [nodeId]);

    const latestThought = thoughtHistory.length > 0 ? thoughtHistory[thoughtHistory.length - 1] : null;

    return (
        <div className={`flex-1 flex flex-col min-w-0 border-r last:border-r-0 transition-all duration-700 ${borderClass}`}>
            <div className={`bg-gray-900/80 px-3 py-1.5 border-b border-gray-800 flex justify-between items-center text-[9px] font-bold group relative overflow-hidden`}>
                <div className={`absolute inset-0 opacity-5 pointer-events-none bg-gradient-to-r ${isStrict ? 'from-rose-500' : 'from-blue-500'} to-transparent`}></div>
                <div className="flex items-center gap-2 relative z-10">
                    <span className={`w-1.5 h-1.5 rounded-full ${statusDotClass} ${isAIProcessing ? 'animate-pulse' : ''}`}></span>
                    <span className="text-gray-200 tracking-wider truncate max-w-[80px]">{nodeId}</span>
                    <button
                        onClick={() => setIsDetailsExpanded(!isDetailsExpanded)}
                        className={`text-[8px] uppercase tracking-tighter px-1.5 py-0.5 rounded flex items-center gap-1 transition-colors hover:bg-white/10 ${isStrict ? 'bg-rose-950/50 text-rose-400 border border-rose-900/50' : 'bg-blue-950/50 text-blue-400 border border-blue-900/50'}`}
                    >
                        {mode}
                        <span className={`text-[7px] transform transition-transform duration-200 ${isDetailsExpanded ? 'rotate-180' : ''}`}>▼</span>
                    </button>
                </div>
                <div className="flex space-x-3 text-gray-400 font-mono relative z-10">
                    <span title="CPU Usage">C: <span className="text-emerald-400">{stats?.cpu_usage_percent?.toFixed(1) || '0.0'}%</span></span>
                    <span title="Memory Usage">M: <span className="text-emerald-400">{stats?.memory_usage_percent?.toFixed(1) || '0.0'}%</span></span>
                </div>
            </div>

            <div className="flex-1 overflow-hidden bg-[#030712] relative p-1">
                <div ref={terminalRef} className="w-full h-full" />

                {/* Internal Reasoning Details Panel */}
                <div className={`absolute left-0 right-0 bottom-0 bg-gray-950/95 backdrop-blur-2xl border-t border-white/10 transition-all duration-500 z-50 overflow-hidden flex flex-col shadow-[0_-10px_40px_rgba(0,0,0,0.5)] ${isDetailsExpanded ? 'h-3/5 opacity-100' : 'h-0 opacity-0 pointer-events-none'}`}>
                    <div className="px-3 py-2 bg-gray-900/80 flex justify-between items-center border-b border-white/5 sticky top-0 z-10">
                        <span className="text-[8px] uppercase tracking-[0.2em] font-black text-blue-400 flex items-center gap-2">
                            <div className="w-1.5 h-1.5 bg-blue-500 rounded-full animate-pulse shadow-[0_0_8px_rgba(59,130,246,0.5)]"></div>
                            Autonomous Analysis Trace
                        </span>
                        <button onClick={() => setIsDetailsExpanded(false)} className="text-gray-500 hover:text-white transition-colors p-1">
                            <svg className="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2.5} d="M6 18L18 6M6 6l12 12" />
                            </svg>
                        </button>
                    </div>
                    <div className="flex-1 overflow-y-auto p-4 space-y-3 scrollbar-thin scrollbar-thumb-gray-800 scroll-smooth">
                        {thoughtHistory.length === 0 ? (
                            <div className="flex flex-col items-center justify-center h-full opacity-30 select-none">
                                <div className="text-[8px] uppercase tracking-widest font-bold mb-2">Idle Monitoring</div>
                                <div className="text-[10px] italic">Waiting for agentic activity...</div>
                            </div>
                        ) : (
                            thoughtHistory.map((t, i) => (
                                <div key={i} className="flex gap-3 animate-in fade-in slide-in-from-bottom-2 duration-700 ease-out fill-mode-forwards">
                                    <div className="text-[8px] font-mono select-none mt-1 opacity-50 tabular-nums">
                                        {new Date(t.time * 1000).toLocaleTimeString([], { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' })}
                                    </div>
                                    <div className={`text-[10px] leading-relaxed font-medium break-words overflow-wrap-anywhere flex-1 ${t.type === 'mesh_observation' ? 'text-amber-500 italic' : 'text-gray-200'}`}>
                                        {t.type === 'mesh_observation' && '⚠️ '}
                                        {t.thought}
                                    </div>
                                </div>
                            ))
                        )}
                    </div>
                </div>

                {/* Minimalist Live Analysis Notice (Non-intrusive when collapsed) */}
                {isAIProcessing && latestThought && !isDetailsExpanded && (
                    <div className="absolute top-2 right-2 flex items-center gap-2 animate-in fade-in duration-700 pointer-events-none">
                        <div className="bg-blue-500/10 backdrop-blur-md border border-blue-500/20 rounded px-2 py-0.5 flex items-center gap-2 shadow-xl">
                            <span className="flex h-1.5 w-1.5 relative">
                                <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-blue-400 opacity-75"></span>
                                <span className="relative inline-flex rounded-full h-1.5 w-1.5 bg-blue-500"></span>
                            </span>
                            <span className="text-[8px] text-blue-400/90 font-bold tracking-tight truncate max-w-[120px]">{latestThought.thought}</span>
                        </div>
                    </div>
                )}

                {isAIProcessing && !latestThought && !isDetailsExpanded && (
                    <div className="absolute top-1 right-2 pointer-events-none opacity-40">
                        <span className="flex h-2 w-2">
                            <span className={`${isStrict ? 'bg-rose-400' : 'bg-blue-400'} animate-ping absolute inline-flex h-full w-full rounded-full opacity-75`}></span>
                            <span className={`relative inline-flex rounded-full h-2 w-2 ${isStrict ? 'bg-rose-500' : 'bg-blue-500'}`}></span>
                        </span>
                    </div>
                )}
            </div>

            <style dangerouslySetInnerHTML={{
                __html: `
                @keyframes pulse-red {
                    0%, 100% { border-color: rgba(244, 63, 94, 0.4); box-shadow: 0 0 5px rgba(244, 63, 94, 0.1); }
                    50% { border-color: rgba(244, 63, 94, 0.8); box-shadow: 0 0 15px rgba(244, 63, 94, 0.3); }
                }
                @keyframes pulse-blue {
                    0%, 100% { border-color: rgba(59, 130, 246, 0.4); box-shadow: 0 0 5px rgba(59, 130, 246, 0.1); }
                    50% { border-color: rgba(59, 130, 246, 0.8); box-shadow: 0 0 15px rgba(59, 130, 246, 0.3); }
                }
            `}} />
        </div>
    );
};

const MultiNodeConsole = ({ attachedNodeIds, nodes, isAIProcessing, isExpanded, onToggleExpand }) => {
    const [nodeStats, setNodeStats] = useState({}); // node_id -> stats object
    const [nodeHistory, setNodeHistory] = useState({}); // node_id -> array of {time, thought}
    const [connected, setConnected] = useState(false);
    const wsRef = useRef(null);
    const xtermsRef = useRef({});

    useEffect(() => {
        if (!attachedNodeIds || attachedNodeIds.length === 0) return;

        let reconnectTimer;
        let isClosing = false;

        const connect = () => {
            if (isClosing) return;
            const ws = new WebSocket(getNodeStreamUrl());
            wsRef.current = ws;

            ws.onopen = () => setConnected(true);

            ws.onmessage = (event) => {
                if (isClosing) return;
                try {
                    const msg = JSON.parse(event.data);
                    if (msg.node_id && !attachedNodeIds.includes(msg.node_id)) return;

                    if ((msg.event === 'mesh_heartbeat' || msg.event === 'heartbeat')) {
                        if (msg.data?.stats) setNodeStats(prev => ({ ...prev, [msg.node_id]: msg.data.stats }));
                        if (msg.data?.nodes) msg.data.nodes.forEach(n => setNodeStats(prev => ({ ...prev, [n.node_id]: n.stats })));
                        return;
                    }

                    // Handle Sub-Agent Thoughts & Mesh Observations
                    if (msg.event === 'subagent_thought' || msg.event === 'mesh_observation') {
                        setNodeHistory(prev => {
                            const nodeHistory = prev[msg.node_id] || [];
                            const content = msg.event === 'mesh_observation' ? msg.data.message : msg.data;
                            // Avoid exact duplicates back-to-back
                            if (nodeHistory.length > 0 && nodeHistory[nodeHistory.length - 1].thought === content) return prev;
                            const newEntry = { time: Date.now() / 1000, thought: content, type: msg.event };
                            return { ...prev, [msg.node_id]: [...nodeHistory, newEntry] };
                        });
                        return;
                    }

                    const xterm = xtermsRef.current[msg.node_id];
                    if (xterm) {
                        switch (msg.event) {
                            case 'task_assigned':
                                if (msg.data.command) {
                                    if (msg.data.command.includes('__CORTEX_FIN_SH_')) break;
                                    if (msg.data.command.startsWith('!RAW:')) {
                                        xterm.write(`\x1b[38;5;36m${msg.data.command.slice(5)}\x1b[0m\r\n`);
                                    } else {
                                        xterm.write(`\x1b[38;5;33m\x1b[1m$ ${msg.data.command}\x1b[0m\r\n`);
                                    }
                                    // NEW: Clear thought history when a new bash command starts to maintain relevance
                                    setNodeHistory(prev => ({ ...prev, [msg.node_id]: [] }));
                                }
                                break;
                            case 'task_stdout':
                            case 'skill_event':
                                let data = msg.event === 'skill_event' ? (msg.data?.data || msg.data?.terminal_out) : msg.data;
                                if (data && typeof data === 'string') {
                                    const stealthData = data.replace(/.*__CORTEX_FIN_SH_.*[\r\n]*/g, '');
                                    if (stealthData) xterm.write(stealthData);
                                } else if (data) xterm.write(data);
                                break;
                        }
                        // Always scroll to bottom on new output
                        xterm.scrollToBottom();
                    }
                } catch (e) { }
            };

            ws.onclose = () => {
                if (!isClosing) {
                    setConnected(false);
                    reconnectTimer = setTimeout(connect, 3000);
                }
            };
        };

        connect();

        return () => {
            isClosing = true;
            if (wsRef.current) wsRef.current.close();
            clearTimeout(reconnectTimer);
        };
    }, [JSON.stringify(attachedNodeIds)]);

    const handleMount = (nodeId, xterm) => { xtermsRef.current[nodeId] = xterm; };
    const handleUnmount = (nodeId) => { delete xtermsRef.current[nodeId]; };

    if (!attachedNodeIds || attachedNodeIds.length === 0) return null;

    return (
        <div className={`flex flex-col h-full bg-gray-950 text-gray-300 font-mono border-t border-gray-800 transition-colors duration-500`}>
            <div className={`bg-amber-500/10 border-b border-amber-500/20 px-4 py-1.5 flex justify-between items-center overflow-hidden shrink-0 z-10`} id="ai-terminal-notice">
                <span className="text-[10px] font-black uppercase tracking-tighter text-amber-500 flex items-center gap-2">
                    <svg className={`w-3.5 h-3.5 shrink-0 ${isAIProcessing ? 'animate-bounce' : ''}`} fill="none" viewBox="0 0 24 24" stroke="currentColor">
                        <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2.5} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
                    </svg>
                    {isAIProcessing ? 'AI Agent actively controlling node terminals...' : 'Terminal Surfaced to AI :: Context Synchronized'}
                </span>
                <span className="text-[9px] text-amber-600 font-bold uppercase tracking-widest opacity-60 hidden md:inline font-mono">
                    OBSERVATION_MODE
                </span>
            </div>

            <div className="flex bg-gray-950 border-b border-gray-800 px-4 py-1.5 justify-between items-center shrink-0">
                <span className="flex items-center text-[10px] font-black tracking-[0.2em] text-gray-500">
                    <span className={`w-1.5 h-1.5 rounded-full mr-2.5 ${connected ? 'bg-emerald-500' : 'bg-red-500'} ${isAIProcessing && connected ? 'animate-ping shadow-[0_0_8px_#10b981]' : ''}`}></span>
                    NODE_EXECUTION_SWARM
                </span>
                <div className="flex gap-4 items-center">
                    {onToggleExpand && (
                        <button
                            onClick={onToggleExpand}
                            className="p-1 text-gray-400 hover:text-white transition-colors bg-gray-900/50 hover:bg-gray-800 rounded border border-gray-700"
                            title={isExpanded ? "Restore Size" : "Maximize Console"}
                        >
                            <svg className="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                                {isExpanded ? (
                                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2.5} d="M19 9l-7 7-7-7" />
                                ) : (
                                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2.5} d="M5 15l7-7 7 7" />
                                )}
                            </svg>
                        </button>
                    )}
                    <span className="text-gray-600 uppercase tracking-widest text-[8px] font-bold">Attached: {attachedNodeIds.length}</span>
                    <span className="text-gray-500 uppercase tracking-widest text-[9px] font-bold py-0.5 px-2 rounded-full border border-gray-800 bg-gray-950/50">Live Stream</span>
                </div>
            </div>

            <div className="flex flex-1 overflow-hidden divide-x divide-gray-800">
                {attachedNodeIds.map(nodeId => (
                    <TerminalNodeItem
                        key={nodeId}
                        nodeId={nodeId}
                        stats={nodeStats[nodeId]}
                        onMount={handleMount}
                        onUnmount={handleUnmount}
                        nodeConfig={nodes?.find(n => n.node_id === nodeId)}
                        isAIProcessing={isAIProcessing}
                        thoughtHistory={nodeHistory[nodeId]}
                    />
                ))}
            </div>
        </div>
    );
};

export default MultiNodeConsole;
