import React, { useEffect, useRef, useState, useCallback } from 'react';
import { Terminal } from 'xterm';
import { FitAddon } from '@xterm/addon-fit';
import { WebLinksAddon } from '@xterm/addon-web-links';
import 'xterm/css/xterm.css';
import {
  Terminal as TerminalIcon,
  Maximize2,
  Minimize2,
  X,
  RefreshCw,
  AlertCircle,
  FolderOpen,
  Plus
} from 'lucide-react';
import { useStudy } from '../context/StudyContext';
import { useClaudeTerminal } from '../context/ClaudeTerminalContext';

interface ClaudeTerminalProps {
  isExpanded?: boolean;
  onToggleExpand?: () => void;
  onClose?: () => void;
}

export const ClaudeTerminal: React.FC<ClaudeTerminalProps> = ({
  isExpanded = false,
  onToggleExpand,
  onClose
}) => {
  const { selectedStudy } = useStudy();
  const { setIsConnected: setGlobalConnected } = useClaudeTerminal();
  const terminalRef = useRef<HTMLDivElement>(null);
  const xtermRef = useRef<Terminal | null>(null);
  const fitAddonRef = useRef<FitAddon | null>(null);
  const wsRef = useRef<WebSocket | null>(null);
  const [isConnected, setIsConnectedLocal] = useState(false);
  const [isConnecting, setIsConnecting] = useState(false);
  const [_error, setError] = useState<string | null>(null);
  const [cliAvailable, setCliAvailable] = useState<boolean | null>(null);
  const [contextSet, setContextSet] = useState(false);
  const [settingContext, setSettingContext] = useState(false);

  // Sync local connection state to global context
  const setIsConnected = useCallback((connected: boolean) => {
    setIsConnectedLocal(connected);
    setGlobalConnected(connected);
  }, [setGlobalConnected]);

  // Check CLI availability
  useEffect(() => {
    fetch('/api/terminal/status')
      .then(res => res.json())
      .then(data => {
        setCliAvailable(data.available);
        if (!data.available) {
          setError(data.message);
        }
      })
      .catch(() => {
        setCliAvailable(false);
        setError('Could not check Claude Code CLI status');
      });
  }, []);

  // Initialize terminal
  useEffect(() => {
    if (!terminalRef.current || xtermRef.current) return;

    const term = new Terminal({
      cursorBlink: true,
      fontSize: 13,
      fontFamily: '"JetBrains Mono", "Fira Code", Consolas, monospace',
      theme: {
        background: '#0f172a',
        foreground: '#e2e8f0',
        cursor: '#60a5fa',
        cursorAccent: '#0f172a',
        selectionBackground: '#334155',
        black: '#1e293b',
        red: '#ef4444',
        green: '#22c55e',
        yellow: '#eab308',
        blue: '#3b82f6',
        magenta: '#a855f7',
        cyan: '#06b6d4',
        white: '#f1f5f9',
        brightBlack: '#475569',
        brightRed: '#f87171',
        brightGreen: '#4ade80',
        brightYellow: '#facc15',
        brightBlue: '#60a5fa',
        brightMagenta: '#c084fc',
        brightCyan: '#22d3ee',
        brightWhite: '#f8fafc',
      },
      allowProposedApi: true,
    });

    const fitAddon = new FitAddon();
    const webLinksAddon = new WebLinksAddon();

    term.loadAddon(fitAddon);
    term.loadAddon(webLinksAddon);
    term.open(terminalRef.current);

    // Initial fit
    setTimeout(() => fitAddon.fit(), 0);

    xtermRef.current = term;
    fitAddonRef.current = fitAddon;

    // Welcome message
    term.writeln('\x1b[1;36m╔══════════════════════════════════════════════════════════╗\x1b[0m');
    term.writeln('\x1b[1;36m║\x1b[0m  \x1b[1;37mClaude Code Terminal\x1b[0m                                     \x1b[1;36m║\x1b[0m');
    term.writeln('\x1b[1;36m║\x1b[0m  \x1b[90mFull Claude Code experience in the Atomizer dashboard\x1b[0m   \x1b[1;36m║\x1b[0m');
    term.writeln('\x1b[1;36m╚══════════════════════════════════════════════════════════╝\x1b[0m');
    term.writeln('');

    if (cliAvailable === false) {
      term.writeln('\x1b[1;31mError:\x1b[0m Claude Code CLI not found.');
      term.writeln('Install with: \x1b[1;33mnpm install -g @anthropic-ai/claude-code\x1b[0m');
    } else {
      term.writeln('\x1b[90mClick "Connect" to start a Claude Code session.\x1b[0m');
      term.writeln('\x1b[90mClaude will have access to CLAUDE.md and .claude/ skills.\x1b[0m');
    }
    term.writeln('');

    return () => {
      term.dispose();
      xtermRef.current = null;
    };
  }, [cliAvailable]);

  // Handle resize
  useEffect(() => {
    const handleResize = () => {
      if (fitAddonRef.current) {
        fitAddonRef.current.fit();
        // Send resize to backend
        if (wsRef.current?.readyState === WebSocket.OPEN && xtermRef.current) {
          wsRef.current.send(JSON.stringify({
            type: 'resize',
            cols: xtermRef.current.cols,
            rows: xtermRef.current.rows
          }));
        }
      }
    };

    window.addEventListener('resize', handleResize);
    // Also fit when expanded state changes
    setTimeout(handleResize, 100);

    return () => window.removeEventListener('resize', handleResize);
  }, [isExpanded]);

  // Connect to terminal WebSocket
  const connect = useCallback(() => {
    if (!xtermRef.current || wsRef.current?.readyState === WebSocket.OPEN) return;

    setIsConnecting(true);
    setError(null);

    // Let backend determine the working directory (ATOMIZER_ROOT)
    // Pass study_id as parameter so we can inform Claude about the context
    const studyParam = selectedStudy?.id ? `?study_id=${selectedStudy.id}` : '';

    const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
    const ws = new WebSocket(`${protocol}//${window.location.host}/api/terminal/claude${studyParam}`);

    ws.onopen = () => {
      setIsConnected(true);
      setIsConnecting(false);
      xtermRef.current?.clear();
      xtermRef.current?.writeln('\x1b[1;32mConnected to Claude Code\x1b[0m');
      if (selectedStudy?.id) {
        xtermRef.current?.writeln(`\x1b[90mStudy: \x1b[1;33m${selectedStudy.id}\x1b[0m \x1b[90m- Click "Set Context" to initialize\x1b[0m`);
      }
      xtermRef.current?.writeln('');

      // Send initial resize
      if (xtermRef.current) {
        ws.send(JSON.stringify({
          type: 'resize',
          cols: xtermRef.current.cols,
          rows: xtermRef.current.rows
        }));
      }
    };

    ws.onmessage = (event) => {
      try {
        const message = JSON.parse(event.data);

        switch (message.type) {
          case 'output':
            xtermRef.current?.write(message.data);
            break;
          case 'started':
            xtermRef.current?.writeln(`\x1b[90m${message.message}\x1b[0m`);
            break;
          case 'exit':
            xtermRef.current?.writeln('');
            xtermRef.current?.writeln(`\x1b[33mClaude Code exited with code ${message.code}\x1b[0m`);
            setIsConnected(false);
            break;
          case 'error':
            xtermRef.current?.writeln(`\x1b[1;31mError: ${message.message}\x1b[0m`);
            setError(message.message);
            break;
        }
      } catch (e) {
        // Raw output
        xtermRef.current?.write(event.data);
      }
    };

    ws.onerror = () => {
      setError('WebSocket connection error');
      setIsConnecting(false);
    };

    ws.onclose = () => {
      setIsConnected(false);
      setIsConnecting(false);
      xtermRef.current?.writeln('');
      xtermRef.current?.writeln('\x1b[90mDisconnected from Claude Code\x1b[0m');
    };

    // Handle terminal input
    const disposable = xtermRef.current.onData((data) => {
      if (ws.readyState === WebSocket.OPEN) {
        ws.send(JSON.stringify({ type: 'input', data }));
      }
    });

    wsRef.current = ws;

    return () => {
      disposable.dispose();
    };
  }, [selectedStudy]);

  // Disconnect
  const disconnect = useCallback(() => {
    if (wsRef.current) {
      wsRef.current.send(JSON.stringify({ type: 'stop' }));
      wsRef.current.close();
      wsRef.current = null;
    }
    setIsConnected(false);
    setContextSet(false);
  }, []);

  // Set study context - sends context message to Claude silently
  const setStudyContext = useCallback(() => {
    if (!wsRef.current || wsRef.current.readyState !== WebSocket.OPEN) return;

    setSettingContext(true);

    let contextMessage: string;
    if (selectedStudy?.id) {
      // Existing study context
      contextMessage =
        `You are helping with Atomizer optimization. ` +
        `First read: .claude/skills/00_BOOTSTRAP.md for task routing. ` +
        `Then follow the Protocol Execution Framework. ` +
        `Study context: Working on "${selectedStudy.id}" at studies/${selectedStudy.id}/. ` +
        `Use atomizer conda env. Acknowledge briefly.`;
    } else {
      // No study selected - offer to create new study
      contextMessage =
        `You are helping with Atomizer optimization. ` +
        `First read: .claude/skills/00_BOOTSTRAP.md for task routing. ` +
        `No study is currently selected. ` +
        `Read .claude/skills/guided-study-wizard.md and help the user create a new optimization study. ` +
        `Use atomizer conda env. Start the guided wizard by asking what they want to optimize.`;
    }

    wsRef.current.send(JSON.stringify({ type: 'input', data: contextMessage + '\n' }));

    // Mark as done after Claude has had time to process
    setTimeout(() => {
      setSettingContext(false);
      setContextSet(true);
    }, 500);
  }, [selectedStudy]);

  // Cleanup on unmount
  useEffect(() => {
    return () => {
      if (wsRef.current) {
        wsRef.current.close();
      }
    };
  }, []);

  return (
    <div className={`flex flex-col bg-dark-800 rounded-xl border border-dark-600 overflow-hidden ${
      isExpanded ? 'fixed inset-4 z-50' : 'h-full'
    }`}>
      {/* Header */}
      <div className="px-4 py-3 border-b border-dark-600 flex items-center justify-between bg-dark-800">
        <div className="flex items-center gap-2">
          <div className="w-8 h-8 bg-gradient-to-br from-primary-500 to-primary-700 rounded-lg flex items-center justify-center">
            <TerminalIcon className="w-4 h-4 text-white" />
          </div>
          <div>
            <span className="font-medium text-white">Claude Code</span>
            {selectedStudy && (
              <span className="ml-2 text-xs bg-dark-700 px-2 py-0.5 rounded text-dark-300">
                {selectedStudy.id}
              </span>
            )}
          </div>
          {/* Connection status indicator */}
          <div className={`w-2 h-2 rounded-full ml-2 ${
            isConnected ? 'bg-green-500' : 'bg-dark-500'
          }`} />
        </div>

        <div className="flex items-center gap-1">
          {/* Connect/Disconnect button */}
          <button
            onClick={isConnected ? disconnect : connect}
            disabled={isConnecting || cliAvailable === false}
            className={`px-3 py-1.5 text-sm rounded-lg transition-colors flex items-center gap-2 ${
              isConnected
                ? 'bg-red-600/20 text-red-400 hover:bg-red-600/30'
                : 'bg-green-600/20 text-green-400 hover:bg-green-600/30'
            } disabled:opacity-50 disabled:cursor-not-allowed`}
          >
            {isConnecting ? (
              <RefreshCw className="w-3 h-3 animate-spin" />
            ) : null}
            {isConnected ? 'Disconnect' : 'Connect'}
          </button>

          {/* Set Context button - works for both existing study and new study creation */}
          <button
            onClick={setStudyContext}
            disabled={!isConnected || settingContext || contextSet}
            className={`px-3 py-1.5 text-sm rounded-lg transition-colors flex items-center gap-2 ${
              contextSet
                ? 'bg-green-600/20 text-green-400'
                : !isConnected
                  ? 'bg-dark-600 text-dark-400'
                  : selectedStudy?.id
                    ? 'bg-primary-600/20 text-primary-400 hover:bg-primary-600/30'
                    : 'bg-yellow-600/20 text-yellow-400 hover:bg-yellow-600/30'
            } disabled:opacity-50 disabled:cursor-not-allowed`}
            title={
              !isConnected
                ? 'Connect first to set context'
                : contextSet
                  ? 'Context already set'
                  : selectedStudy?.id
                    ? `Set context to study: ${selectedStudy.id}`
                    : 'Start guided study creation wizard'
            }
          >
            {settingContext ? (
              <RefreshCw className="w-3 h-3 animate-spin" />
            ) : selectedStudy?.id ? (
              <FolderOpen className="w-3 h-3" />
            ) : (
              <Plus className="w-3 h-3" />
            )}
            {contextSet ? 'Context Set' : selectedStudy?.id ? 'Set Context' : 'New Study'}
          </button>

          {onToggleExpand && (
            <button
              onClick={onToggleExpand}
              className="p-2 text-dark-400 hover:text-white hover:bg-dark-700 rounded-lg transition-colors"
            >
              {isExpanded ? <Minimize2 className="w-4 h-4" /> : <Maximize2 className="w-4 h-4" />}
            </button>
          )}
          {onClose && (
            <button
              onClick={onClose}
              className="p-2 text-dark-400 hover:text-white hover:bg-dark-700 rounded-lg transition-colors"
            >
              <X className="w-4 h-4" />
            </button>
          )}
        </div>
      </div>

      {/* CLI not available warning */}
      {cliAvailable === false && (
        <div className="px-4 py-3 bg-yellow-900/20 border-b border-yellow-800/30 flex items-center gap-2">
          <AlertCircle className="w-4 h-4 text-yellow-500" />
          <span className="text-yellow-400 text-sm">
            Claude Code CLI not found. Install with: npm install -g @anthropic-ai/claude-code
          </span>
        </div>
      )}

      {/* Terminal */}
      <div className="flex-1 p-2 bg-[#0f172a]">
        <div ref={terminalRef} className="h-full" />
      </div>

      {/* Footer */}
      <div className="px-4 py-2 border-t border-dark-600 bg-dark-800">
        <p className="text-xs text-dark-500 text-center">
          Claude Code has access to CLAUDE.md instructions and .claude/ skills for Atomizer optimization
        </p>
      </div>
    </div>
  );
};

export default ClaudeTerminal;
