/**
 * BroCode Main Application
 */

import React, { useState, useEffect } from 'react';
import { Box, Text, useInput, useApp } from 'ink';
import TextInput from 'ink-text-input';
import { version, Agent, ConfigManager, Logger, type AgentConfig } from '@michaelnkomo/core';
import { 
  simpleFileTagging as fileTagging, 
  simpleAutocompleteManager as autocompleteManager,
  detectFileTagging,
  renderAutocompletePopup 
} from './utils/simple-file-tagging.js';

interface AppProps {
  args: string[];
}

const App: React.FC<AppProps> = ({ args: _args }) => {
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [agent, setAgent] = useState<Agent | null>(null);
  const [input, setInput] = useState('');
  const [messages, setMessages] = useState<Array<{ role: string; content: string }>>([]);
  const [isProcessing, setIsProcessing] = useState(false);
  const [showAutocomplete, setShowAutocomplete] = useState(false);
  const [autocompleteResults, setAutocompleteResults] = useState<any[]>([]);
  const [selectedAutocompleteIndex, setSelectedAutocompleteIndex] = useState(0);
  const [cursorPosition, setCursorPosition] = useState(0);
  const { exit } = useApp();

  // Initialize config and agent
  useEffect(() => {
    const init = async () => {
      try {
        // Load configuration
        const configManager = await ConfigManager.load();
        const config = configManager.getAll();

        // Validate API key
        if (!config.apiKey || config.apiKey === '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') {
          setError(
            'NVIDIA API key not configured.\n\n' +
            'Please set NVIDIA_API_KEY in your environment or create ~/.brocode/config.json\n\n' +
            'Get your API key at: https://build.nvidia.com/meta/llama-3_1-70b-instruct'
          );
          setIsLoading(false);
          return;
        }

        // Create logger
        const logger = new Logger({
          verbose: config.verbose,
          debug: config.debug,
          logToFile: true,
          component: 'cli',
        });

        // Create agent config
        const agentConfig: AgentConfig = {
          apiKey: config.apiKey!,
          apiUrl: config.apiUrl!,
          model: config.model,
          temperature: config.temperature,
          top_p: config.top_p,
          max_tokens: config.max_tokens,
        };

        // Initialize agent
        const agentInstance = new Agent(agentConfig, logger);
        setAgent(agentInstance);
        setIsLoading(false);

        // Show welcome message
        setMessages([
          {
            role: 'system',
            content: `Welcome to BroCode v${version}! 🚀\n\nI'm your AI coding companion. I can:\n• Create complete projects (FastAPI, Express, React, Django, Go, Rust, etc.)\n• Write and edit code files\n• Execute file operations\n• And much more!\n\nType your request or 'exit' to quit.`,
          },
        ]);
      } catch (err) {
        setError(`Failed to initialize: ${(err as Error).message}`);
        setIsLoading(false);
      }
    };

    init();
  }, []);

  // Handle input changes for autocomplete
  const handleInputChange = async (value: string) => {
    setInput(value);
    
    // Check if user is typing file tags
    if (detectFileTagging(value)) {
      const autocompleteState = await autocompleteManager.handleInput(value, value.length);
      
      setShowAutocomplete(autocompleteState.shouldShowAutocomplete);
      setAutocompleteResults(autocompleteState.results);
      setSelectedAutocompleteIndex(autocompleteState.selectedIndex);
    } else {
      setShowAutocomplete(false);
      setAutocompleteResults([]);
    }
  };

  useInput((input, key) => {
    if (key.escape || (key.ctrl && input === 'c')) {
      if (showAutocomplete) {
        // Hide autocomplete first
        setShowAutocomplete(false);
        return;
      }
      exit();
    }

    // Handle autocomplete navigation
    if (showAutocomplete) {
      if (key.upArrow) {
        autocompleteManager.navigateResults('up');
        setSelectedAutocompleteIndex(autocompleteManager.getState().selectedIndex);
        return;
      }
      
      if (key.downArrow) {
        autocompleteManager.navigateResults('down');
        setSelectedAutocompleteIndex(autocompleteManager.getState().selectedIndex);
        return;
      }
      
      if (key.return) {
        const result = autocompleteManager.selectResult(input, cursorPosition);
        if (result) {
          setInput(result.text);
          setCursorPosition(result.cursorPosition);
        }
        setShowAutocomplete(false);
        return;
      }
    }
  });

  // Handle message submission with file context
  const handleSubmit = async (value: string) => {
    if (!value.trim() || !agent || isProcessing) return;

    // Hide autocomplete when submitting
    setShowAutocomplete(false);

    const userMessage = value.trim();
    setInput('');

    // Check for exit command
    if (userMessage.toLowerCase() === 'exit' || userMessage.toLowerCase() === 'quit') {
      exit();
      return;
    }

    // Parse file tags and build context
    const { cleanInput, fileTags } = fileTagging.parseFileTags(userMessage);
    let contextualInput = cleanInput;

    if (fileTags.length > 0) {
      const fileContext = await fileTagging.buildFileContext(fileTags);
      contextualInput = fileContext + '\n\n**USER REQUEST:**\n' + cleanInput;
    }

    // Add user message to display (show original input)
    setMessages((prev) => [...prev, { role: 'user', content: userMessage }]);
    setIsProcessing(true);

    try {
      // Send contextual input (with file contents) to the agent
      const response = await agent.chat(contextualInput);

      // Add AI response to display
      setMessages((prev) => [...prev, { role: 'assistant', content: response }]);
    } catch (err) {
      setMessages((prev) => [
        ...prev,
        { role: 'error', content: `Error: ${(err as Error).message}` },
      ]);
    } finally {
      setIsProcessing(false);
    }
  };

  // Render loading state
  if (isLoading) {
    return (
      <Box flexDirection="column" padding={1}>
        <Text bold color="cyan">
           BroCode v{version}
        </Text>
        <Text color="yellow">Initializing...</Text>
      </Box>
    );
  }

  // Render error state
  if (error) {
    return (
      <Box flexDirection="column" padding={1}>
        <Text bold color="cyan">
           BroCode v{version}
        </Text>
        <Box marginTop={1}>
          <Text color="red">{error}</Text>
        </Box>
      </Box>
    );
  }

  // Render main chat interface
  return (
    <Box flexDirection="column" padding={1}>
      <Text bold color="cyan">
         BroCode v{version}
      </Text>
      <Text color="gray" dimColor>
        Press ESC or Ctrl+C to exit
      </Text>

      {/* Message history */}
      <Box flexDirection="column" marginTop={1} marginBottom={1}>
        {messages.map((msg, idx) => (
          <Box key={idx} flexDirection="column" marginBottom={1}>
            {msg.role === 'system' && (
              <Box>
                <Text color="gray">{msg.content}</Text>
              </Box>
            )}
            {msg.role === 'user' && (
              <Box>
                <Text bold color="green">
                  You: 
                </Text>
                <Text> {msg.content}</Text>
              </Box>
            )}
            {msg.role === 'assistant' && (
              <Box>
                <Text bold color="cyan">
                  BroCode: 
                </Text>
                <Text> {msg.content}</Text>
              </Box>
            )}
            {msg.role === 'error' && (
              <Box>
                <Text color="red">{msg.content}</Text>
              </Box>
            )}
          </Box>
        ))}
      </Box>

      {/* Input field */}
      <Box flexDirection="column">
        {isProcessing ? (
          <Text color="yellow"> BroCode is thinking...</Text>
        ) : (
          <>
            <Text color="cyan">
               Type your message (use @ to tag files, Ctrl+C to exit):
            </Text>
            
            {/* Autocomplete popup */}
            {showAutocomplete && autocompleteResults.length > 0 && (
              <Box marginY={1}>
                <Text color="yellow">
                  {renderAutocompletePopup(autocompleteResults, selectedAutocompleteIndex)}
                </Text>
              </Box>
            )}
            
            <Box>
              <Text bold color="green">You: </Text>
              <TextInput 
                value={input} 
                onChange={handleInputChange} 
                onSubmit={handleSubmit}
                placeholder="What would you like me to help you with? Use @filename to include files"
              />
            </Box>
            
            {/* File tag hint */}
            {detectFileTagging(input) && !showAutocomplete && (
              <Text color="gray" dimColor>
                💡 Tip: Use @ to tag files for context (e.g., @src/App.tsx)
              </Text>
            )}
          </>
        )}
      </Box>
    </Box>
  );
};

export default App;
