import { memo, useCallback, useMemo, useRef, useState } from 'react';
import { MessageList } from './MessageList';
import { ChatInput } from './ChatInput';
import { StatusBar } from './StatusBar';
import { PermissionDialog } from './PermissionDialog';
import { HelpDialog } from './HelpDialog';
import { useSessionManager } from '../contexts/SessionContext';
import { Bot } from 'lucide-react';

// Wrapper to compute placeholder inside and prevent parent re-renders from affecting input
const MemoizedChatInput = memo(function MemoizedChatInput({
  onSend, onStop, disabled, isProcessing, sessionId, connected, active
}) {
  const placeholder = !connected
    ? 'Connecting...'
    : !active
      ? 'Start session to begin'
      : 'Type your message...';

  return (
    <ChatInput
      onSend={onSend}
      onStop={onStop}
      disabled={disabled}
      isProcessing={isProcessing}
      sessionId={sessionId}
      placeholder={placeholder}
    />
  );
}, (prevProps, nextProps) => {
  // Custom comparison - only re-render if these specific props change
  return (
    prevProps.disabled === nextProps.disabled &&
    prevProps.isProcessing === nextProps.isProcessing &&
    prevProps.sessionId === nextProps.sessionId &&
    prevProps.connected === nextProps.connected &&
    prevProps.active === nextProps.active &&
    prevProps.onSend === nextProps.onSend &&
    prevProps.onStop === nextProps.onStop
  );
});

// Welcome screen when no messages
const WelcomeScreen = memo(function WelcomeScreen({ session, onStart }) {
  const hostName = session.host.charAt(0).toUpperCase() + session.host.slice(1);
  const projectName = session.project.split('/').pop() || session.project;

  return (
    <div className="flex-1 min-h-0 flex items-center justify-center p-8">
      <div className="text-center text-dark-500 max-w-md">
        <Bot className="w-16 h-16 mx-auto mb-4 opacity-50" />
        <h2 className="text-xl font-semibold mb-2 text-dark-300">
          {hostName}: {projectName}
        </h2>
        <p className="text-sm mb-6">
          {session.active
            ? 'Session is active. Start chatting with Claude.'
            : 'Click "Start Session" in the sidebar or press the button below to begin.'}
        </p>
        {!session.active && (
          <button
            onClick={onStart}
            disabled={!session.connected}
            className={`
              px-6 py-3 rounded-lg font-medium transition-colors
              ${session.connected
                ? 'bg-green-600 hover:bg-green-500 text-white'
                : 'bg-dark-700 text-dark-500 cursor-not-allowed'}
            `}
          >
            {session.connected ? 'Start Session' : 'Connecting...'}
          </button>
        )}
      </div>
    </div>
  );
});

// Error banner
const ErrorBanner = memo(function ErrorBanner({ error, onClear }) {
  if (!error) return null;

  return (
    <div className="bg-red-900/50 border-b border-red-800 px-4 py-2 flex justify-between items-center flex-shrink-0">
      <span className="text-red-200 text-sm">{error}</span>
      <button
        onClick={onClear}
        className="text-red-400 hover:text-red-300 text-lg leading-none"
      >
        ×
      </button>
    </div>
  );
});

// Use a separate hook that memoizes everything to prevent unnecessary re-renders
function useMemoizedSession(sessionId) {
  const {
    sessions,
    sessionMessages,
    startClaudeSession,
    stopClaudeSession,
    sendMessage,
    stopGeneration,
    clearMessages,
    setCompacting,
    changePermissionMode,
    respondToPermission,
  } = useSessionManager();

  const session = sessions[sessionId];
  const messages = sessionMessages[sessionId] || [];

  // Memoize the combined session object
  const sessionWithMessages = useMemo(() => {
    return session ? { ...session, messages } : null;
  }, [session, messages]);

  // Memoize all action functions - use individual functions as deps, not the whole manager
  const actions = useMemo(() => ({
    start: () => startClaudeSession(sessionId),
    stop: () => stopClaudeSession(sessionId),
    send: (msg, attachments) => sendMessage(sessionId, msg, attachments),
    stopGeneration: () => stopGeneration(sessionId),
    clearMessages: () => clearMessages(sessionId),
    setCompacting: (value) => setCompacting(sessionId, value),
    changePermissionMode: (mode) => changePermissionMode(sessionId, mode),
    respondToPermission: (reqId, allow) => respondToPermission(sessionId, reqId, allow),
  }), [sessionId, startClaudeSession, stopClaudeSession, sendMessage, stopGeneration, clearMessages, setCompacting, changePermissionMode, respondToPermission]);

  return { session: sessionWithMessages, ...actions };
}

export const ChatPanel = memo(function ChatPanel({ sessionId }) {
  const {
    session,
    start,
    stop,
    send,
    stopGeneration,
    clearMessages,
    setCompacting,
    changePermissionMode,
    respondToPermission,
  } = useMemoizedSession(sessionId);

  const [showHelp, setShowHelp] = useState(false);

  const handleClearError = useCallback(() => {
    // We'd need to add this to the session context
    // For now, errors auto-clear on next action
  }, []);

  // Use refs for callbacks to keep them stable across re-renders
  const sendRef = useRef(send);
  sendRef.current = send;
  const stopGenerationRef = useRef(stopGeneration);
  stopGenerationRef.current = stopGeneration;

  // Refs for slash command handlers
  const clearMessagesRef = useRef(clearMessages);
  clearMessagesRef.current = clearMessages;
  const setCompactingRef = useRef(setCompacting);
  setCompactingRef.current = setCompacting;
  const setShowHelpRef = useRef(setShowHelp);
  setShowHelpRef.current = setShowHelp;

  // These callbacks never change identity, preventing ChatInput re-renders
  const handleSendMessage = useCallback((message, attachments = []) => {
    const trimmed = message.trim();

    // Handle slash commands locally
    if (trimmed.startsWith('/')) {
      const [cmd, ...args] = trimmed.slice(1).split(' ');
      const arg = args.join(' ');

      switch (cmd.toLowerCase()) {
        case 'clear':
          clearMessagesRef.current();
          return;

        case 'help':
          // Show help dialog
          setShowHelpRef.current(true);
          return;

        case 'compact':
          // Set compacting state immediately, then send to Claude
          setCompactingRef.current(true);
          sendRef.current('/compact' + (arg ? ' ' + arg : ''), []);
          return;

        case 'new':
        case 'export':
        case 'scroll':
        case 'info':
        case 'history':
          // TODO: Implement these
          alert(`/${cmd} is not yet implemented`);
          return;

        default:
          // Unknown command - send to Claude as-is (might be a Claude command)
          break;
      }
    }

    if (trimmed || attachments.length > 0) {
      sendRef.current(message, attachments);
    }
  }, []);

  const handleStopGeneration = useCallback(() => {
    stopGenerationRef.current();
  }, []);

  if (!session) {
    return (
      <div className="flex-1 flex items-center justify-center text-dark-500">
        Session not found
      </div>
    );
  }

  const hasMessages = session.messages && session.messages.length > 0;

  return (
    <div className="flex flex-col h-full bg-dark-950">
      {/* Error Banner */}
      <ErrorBanner error={session.error} onClear={handleClearError} />

      {/* Messages or Welcome */}
      {hasMessages || session.active ? (
        <MessageList
          messages={session.messages || []}
          isProcessing={session.isProcessing}
          onSendMessage={handleSendMessage}
          hostId={session.host}
        />
      ) : (
        <WelcomeScreen session={session} onStart={start} />
      )}

      {/* Status Bar */}
      <StatusBar
        sessionStats={session.stats}
        isProcessing={session.isProcessing}
        connected={session.connected}
        permissionMode={session.permissionMode}
        controlInitialized={session.controlInitialized}
        onChangeMode={(mode) => changePermissionMode(mode)}
      />

      {/* Input - memoized props to prevent re-renders during streaming */}
      <MemoizedChatInput
        onSend={handleSendMessage}
        onStop={handleStopGeneration}
        disabled={!session.active}
        isProcessing={session.isProcessing}
        sessionId={session.claudeSessionId}
        connected={session.connected}
        active={session.active}
      />

      {/* Permission Dialog */}
      <PermissionDialog
        permission={session.pendingPermission}
        onAllow={(requestId) => respondToPermission(requestId, true)}
        onDeny={(requestId) => respondToPermission(requestId, false)}
      />

      {/* Help Dialog */}
      <HelpDialog open={showHelp} onClose={() => setShowHelp(false)} />
    </div>
  );
});
