import React, { useState, useEffect, useRef } from 'react';
import { X, Copy, Check, Terminal, HardHat, Search, Wand2, CheckCircle2, ArrowLeft, Play, Send, MessageSquare, Sparkles, Loader2, History, FileCode, Plus, Minus } from 'lucide-react';
import { generateCodeWithAgents, AgentStatus, generateCodePatches, applyPatches, DEFAULT_MODEL } from '../services/geminiService';

import { Node, Edge } from 'reactflow';

interface Message {
  role: 'user' | 'assistant';
  content: string;
  summary?: string;
  files_changed?: string[];
}

interface PatchHistory {
  id: string;
  timestamp: Date;
  summary: string;
  files_changed: string[];
  patches: { search: string, replace: string }[];
}

interface CodeViewerProps {
  nodes: Node[];
  edges: Edge[];
  promptText: string;
  isOpen: boolean;
  onClose: () => void;
  isLoading: boolean;
}

const CodeViewer: React.FC<CodeViewerProps> = ({ nodes, edges, promptText, isOpen, onClose, isLoading }) => {
  const [copied, setCopied] = useState(false);
  const [viewMode, setViewMode] = useState<'prompt' | 'building' | 'code'>('prompt');
  
  const [finalCode, setFinalCode] = useState('');
  const [agentStatus, setAgentStatus] = useState<AgentStatus>('idle');
  const [agentMessage, setAgentMessage] = useState('');

  // Chat State
  const [messages, setMessages] = useState<Message[]>([]);
  const [inputValue, setInputValue] = useState('');
  const [isChatting, setIsChatting] = useState(false);
  const chatEndRef = useRef<HTMLDivElement>(null);

  // History & Diff State
  const [patchHistory, setPatchHistory] = useState<PatchHistory[]>([]);
  const [isHistoryOpen, setIsHistoryOpen] = useState(false);
  const [selectedHistoryId, setSelectedHistoryId] = useState<string | null>(null);

  const scrollToBottom = () => {
    chatEndRef.current?.scrollIntoView({ behavior: "smooth" });
  };

  useEffect(() => {
    scrollToBottom();
  }, [messages]);

  // Reset state when opening/closing or changing input
  useEffect(() => {
    if (isOpen) {
      setViewMode('prompt');
      setFinalCode('');
      setAgentStatus('idle');
      setMessages([]);
      setIsChatting(false);
      setPatchHistory([]);
      setIsHistoryOpen(false);
      setSelectedHistoryId(null);
    }
  }, [isOpen, promptText]);

  const handleSendMessage = async () => {
    if (!inputValue.trim() || isChatting) return;

    const userMsg = inputValue.trim();
    setInputValue('');
    setMessages(prev => [...prev, { role: 'user', content: userMsg }]);
    setIsChatting(true);

    try {
        const patchResult = await generateCodePatches(finalCode, userMsg, DEFAULT_MODEL);
        const updatedCode = applyPatches(finalCode, patchResult.patches);
        
        const newPatch: PatchHistory = {
            id: Date.now().toString(),
            timestamp: new Date(),
            summary: patchResult.summary,
            files_changed: patchResult.files_changed,
            patches: patchResult.patches
        };

        setPatchHistory(prev => [newPatch, ...prev]);
        setFinalCode(updatedCode);
        setMessages(prev => [...prev, { 
            role: 'assistant', 
            content: patchResult.reasoning || "I've applied the requested changes to the code.",
            summary: patchResult.summary,
            files_changed: patchResult.files_changed
        }]);
    } catch (error) {
        setMessages(prev => [...prev, { 
            role: 'assistant', 
            content: "Sorry, I encountered an error while trying to apply those changes." 
        }]);
    } finally {
        setIsChatting(false);
    }
  };

  const handleCopy = (text: string) => {
    navigator.clipboard.writeText(text);
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  };

  const handleBuildWithAgents = async () => {
    setViewMode('building');
    setAgentStatus('architect');
    setAgentMessage('Initializing agents...');

    try {
        const result = await generateCodeWithAgents(nodes, edges, promptText, (status, msg) => {
            setAgentStatus(status);
            setAgentMessage(msg);
        });
        setFinalCode(result.code);
        
        // Add initial evaluation/patches to chat
        if (result.evaluation) {
            const initialMsgs: Message[] = [
                { 
                    role: 'assistant', 
                    content: `I've completed the initial build. Here's my self-evaluation:
- Score: ${result.evaluation.score}/100
- Missing Components: ${result.evaluation.missing_components.length > 0 ? result.evaluation.missing_components.join(', ') : 'None'}
- Potential Bugs: ${result.evaluation.bugs.length > 0 ? result.evaluation.bugs.join(', ') : 'None'}`
                }
            ];

            if (result.initialPatches) {
                const patchHistoryItem: PatchHistory = {
                    id: 'initial-auto-fix',
                    timestamp: new Date(),
                    summary: result.initialPatches.summary,
                    files_changed: result.initialPatches.files_changed,
                    patches: result.initialPatches.patches
                };
                setPatchHistory([patchHistoryItem]);
                
                initialMsgs.push({
                    role: 'assistant',
                    content: `I've automatically applied some improvements to address the evaluation findings.`,
                    summary: result.initialPatches.summary,
                    files_changed: result.initialPatches.files_changed
                });
            } else if (result.autoFixError) {
                initialMsgs.push({
                    role: 'assistant',
                    content: `I attempted to auto-fix the issues, but the auto-fixer failed: ${result.autoFixError}`
                });
            } else if (result.evaluation.score < 90 && result.evaluation.improvement_tasks.length > 0) {
                initialMsgs.push({
                    role: 'assistant',
                    content: `I skipped auto-fixing because patching was not successful or no patches were applied.`
                });
            }
            setMessages(initialMsgs);
        }

        // Small delay to show completion state
        setTimeout(() => {
            setViewMode('code');
        }, 1000);
    } catch (error) {
        setAgentStatus('error');
        setAgentMessage('Generation failed. Please try again.');
        setTimeout(() => setViewMode('prompt'), 2000);
    }
  };

  const getStepStatus = (step: AgentStatus, current: AgentStatus) => {
    const order = ['idle', 'architect', 'critic', 'refiner', 'evaluator', 'patcher', 'complete'];
    const stepIdx = order.indexOf(step);
    const currentIdx = order.indexOf(current);
    
    if (current === 'error') return 'text-slate-500';
    if (currentIdx > stepIdx) return 'text-emerald-400';
    if (currentIdx === stepIdx) return 'text-blue-400 animate-pulse';
    return 'text-slate-600';
  };

  const renderAgentStep = (step: AgentStatus, icon: React.ReactNode, label: string) => {
      const statusColor = getStepStatus(step, agentStatus);
      const isCurrent = agentStatus === step;
      const order = ['architect', 'critic', 'refiner', 'evaluator', 'patcher', 'complete'];
      const isDone = order.indexOf(agentStatus) > order.indexOf(step);

      return (
        <div className={`flex items-center gap-3 p-4 rounded-lg border border-slate-800 ${isCurrent ? 'bg-slate-800/50 border-blue-500/30' : 'bg-slate-900'}`}>
            <div className={`${statusColor} transition-colors duration-300`}>
                {isDone ? <CheckCircle2 size={24} /> : icon}
            </div>
            <div className="flex-1">
                <div className={`font-semibold text-sm ${isCurrent ? 'text-blue-200' : 'text-slate-400'}`}>{label}</div>
                {isCurrent && (
                     <div className="text-xs text-slate-500 mt-1">{agentMessage}</div>
                )}
            </div>
            {isCurrent && <div className="w-2 h-2 rounded-full bg-blue-400 animate-ping" />}
        </div>
      );
  };

  if (!isOpen) return null;

  return (
    <div className="absolute inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm p-4 md:p-8">
      <div className="bg-slate-900 w-full max-w-5xl h-[85vh] rounded-xl border border-slate-700 shadow-2xl flex flex-col overflow-hidden animate-in fade-in zoom-in duration-200">
        
        {/* Header */}
        <div className="flex items-center justify-between px-6 py-4 border-b border-slate-800 bg-slate-800/50">
          <h2 className="text-lg font-bold text-white flex items-center gap-2">
            {viewMode === 'prompt' && <span className="text-blue-400">Architecture Prompt</span>}
            {viewMode === 'building' && <span className="text-purple-400 flex items-center gap-2"><HardHat size={18}/> Agents Building...</span>}
            {viewMode === 'code' && <span className="text-emerald-400 flex items-center gap-2"><Terminal size={18}/> Final Code</span>}
            
            {isLoading && <span className="text-xs text-blue-400 animate-pulse ml-2">Building...</span>}
          </h2>
          
          <div className="flex items-center gap-3">
             {viewMode === 'code' && (
               <button 
                  onClick={() => setViewMode('prompt')}
                  className="flex items-center gap-2 px-3 py-1.5 bg-slate-800 hover:bg-slate-700 rounded text-xs font-medium text-slate-300 transition-colors border border-slate-700"
                >
                  <ArrowLeft size={14} /> Back to Prompt
                </button>
             )}

            {viewMode !== 'building' && (
              <div className="flex items-center gap-2">
                {viewMode === 'code' && (
                  <button 
                    onClick={() => setIsHistoryOpen(!isHistoryOpen)}
                    className={`flex items-center gap-2 px-3 py-1.5 rounded text-xs font-medium transition-colors border ${isHistoryOpen ? 'bg-blue-600 border-blue-500 text-white' : 'bg-slate-800 hover:bg-slate-700 text-slate-300 border-slate-700'}`}
                  >
                    <History size={14} />
                    Change Logs
                  </button>
                )}
                <button 
                  onClick={() => handleCopy(viewMode === 'code' ? finalCode : promptText)}
                  className="flex items-center gap-2 px-3 py-1.5 bg-slate-800 hover:bg-slate-700 rounded text-xs font-medium text-slate-300 transition-colors border border-slate-700"
                >
                  {copied ? <Check size={14} className="text-emerald-400"/> : <Copy size={14} />}
                  {copied ? 'Copied' : 'Copy'}
                </button>
              </div>
            )}
            
            {viewMode === 'prompt' && !isLoading && (
              <button 
                onClick={handleBuildWithAgents}
                className="flex items-center gap-2 px-3 py-1.5 bg-purple-600 hover:bg-purple-500 rounded text-xs font-medium text-white transition-colors shadow-lg shadow-purple-500/20"
              >
                <Play size={14} fill="currentColor" />
                Build with Agents (Beta)
              </button>
            )}
            
            <button onClick={onClose} className="text-slate-400 hover:text-white transition-colors ml-2">
              <X size={20} />
            </button>
          </div>
        </div>

        {/* Content */}
        <div className="flex-1 overflow-hidden bg-[#0d1117] relative">
          
          {/* View: Loading Prompt */}
          {isLoading && viewMode === 'prompt' && (
            <div className="h-full flex flex-col items-center justify-center space-y-4">
              <div className="w-12 h-12 border-4 border-blue-500/30 border-t-blue-500 rounded-full animate-spin"></div>
              <p className="text-slate-400 text-sm animate-pulse">Refining architecture prompt...</p>
            </div>
          )}

          {/* View: Prompt Text */}
          {!isLoading && viewMode === 'prompt' && (
             <div className="h-full overflow-auto p-6 font-mono text-sm text-slate-300 leading-relaxed whitespace-pre-wrap">
               {promptText}
             </div>
          )}

          {/* View: Agents Building */}
          {viewMode === 'building' && (
             <div className="h-full flex flex-col items-center justify-center p-8">
                 <div className="w-full max-w-md space-y-3">
                    {renderAgentStep('architect', <HardHat size={24} />, "Coder Agent: Writing Implementation")}
                    {renderAgentStep('critic', <Search size={24} />, "Reviewer Agent: Analyzing Logic")}
                    {renderAgentStep('refiner', <Wand2 size={24} />, "Polisher Agent: Finalizing Code")}
                    {renderAgentStep('evaluator', <CheckCircle2 size={24} />, "Evaluator Agent: Verifying Requirements")}
                    {renderAgentStep('patcher', <Terminal size={24} />, "Patcher Agent: Auto-fixing bugs")}
                 </div>
                 {agentStatus === 'complete' && (
                     <div className="mt-8 text-emerald-400 font-bold animate-bounce">
                         Done! Loading code...
                     </div>
                 )}
             </div>
          )}

          {/* View: Final Code */}
          {viewMode === 'code' && (
            <div className="flex h-full overflow-hidden">
              <div className="flex-1 overflow-auto p-6 font-mono text-sm leading-relaxed whitespace-pre-wrap text-blue-100 selection:bg-blue-500/30">
                {finalCode}
              </div>
              
              {/* History/Diff Overlay */}
              {isHistoryOpen && (
                <div className="absolute inset-0 z-40 bg-slate-950 flex flex-col animate-in slide-in-from-right duration-300">
                  <div className="flex items-center justify-between p-4 border-b border-slate-800 bg-slate-900">
                    <div className="flex items-center gap-3">
                      <History size={18} className="text-blue-400" />
                      <h3 className="font-bold text-slate-200">Change Logs</h3>
                    </div>
                    <button onClick={() => setIsHistoryOpen(false)} className="text-slate-400 hover:text-white">
                      <X size={20} />
                    </button>
                  </div>
                  
                  <div className="flex-1 flex overflow-hidden">
                    {/* History List */}
                    <div className="w-64 border-r border-slate-800 overflow-y-auto p-2 space-y-2 bg-slate-900/50">
                      {patchHistory.length === 0 ? (
                        <div className="text-center py-10 text-slate-500 text-xs">No changes yet.</div>
                      ) : (
                        patchHistory.map((h) => (
                          <button 
                            key={h.id}
                            onClick={() => setSelectedHistoryId(h.id)}
                            className={`w-full text-left p-3 rounded-lg border transition-all ${selectedHistoryId === h.id ? 'bg-blue-600/20 border-blue-500/50' : 'bg-slate-800/50 border-slate-700 hover:bg-slate-800'}`}
                          >
                            <div className="text-xs font-bold text-slate-200 truncate">{h.summary}</div>
                            <div className="text-[10px] text-slate-500 mt-1">{h.timestamp.toLocaleTimeString()}</div>
                          </button>
                        ))
                      )}
                    </div>
                    
                    {/* Diff Viewer */}
                    <div className="flex-1 overflow-y-auto p-6 bg-[#0d1117]">
                      {selectedHistoryId ? (
                        <div className="space-y-6">
                          {patchHistory.find(h => h.id === selectedHistoryId)?.patches.map((p, i) => (
                            <div key={i} className="border border-slate-800 rounded-lg overflow-hidden">
                              <div className="bg-slate-800 px-4 py-2 text-xs font-mono text-slate-300 border-b border-slate-700 flex items-center gap-2">
                                <FileCode size={14} />
                                Patch {i + 1}
                              </div>
                              <div className="font-mono text-xs overflow-x-auto">
                                <div className="bg-red-900/20 p-4 border-b border-red-900/30 relative">
                                  <Minus size={12} className="absolute left-1 top-4 text-red-500" />
                                  <div className="text-red-200 opacity-70 line-through whitespace-pre">{p.search}</div>
                                </div>
                                <div className="bg-emerald-900/20 p-4 relative">
                                  <Plus size={12} className="absolute left-1 top-4 text-emerald-500" />
                                  <div className="text-emerald-200 whitespace-pre">{p.replace}</div>
                                </div>
                              </div>
                            </div>
                          ))}
                        </div>
                      ) : (
                        <div className="h-full flex flex-col items-center justify-center text-slate-500">
                          <History size={48} className="opacity-20 mb-4" />
                          <p>Select a change log to view the diff.</p>
                        </div>
                      )}
                    </div>
                  </div>
                </div>
              )}

              {/* Chat Sidebar */}
              <div className="w-80 border-l border-slate-800 bg-slate-900/50 flex flex-col">
                <div className="p-4 border-b border-slate-800 flex items-center gap-2 text-slate-300 font-semibold text-sm">
                  <MessageSquare size={16} className="text-blue-400" />
                  AI Assistant
                </div>
                
                <div className="flex-1 overflow-y-auto p-4 space-y-4 scrollbar-thin scrollbar-thumb-slate-800">
                  {messages.length === 0 && (
                    <div className="text-center py-8">
                      <Sparkles className="mx-auto text-slate-700 mb-2" size={32} />
                      <p className="text-xs text-slate-500">Ask me to modify the code or add features.</p>
                    </div>
                  )}
                  {messages.map((msg, i) => (
                    <div key={i} className={`flex flex-col ${msg.role === 'user' ? 'items-end' : 'items-start'}`}>
                      <div className={`max-w-[90%] p-3 rounded-lg text-xs leading-relaxed ${
                        msg.role === 'user' 
                          ? 'bg-blue-600 text-white rounded-tr-none' 
                          : 'bg-slate-800 text-slate-300 rounded-tl-none border border-slate-700'
                      }`}>
                        {msg.content}
                        
                        {msg.role === 'assistant' && msg.summary && (
                          <div className="mt-3 pt-3 border-t border-slate-700 space-y-2">
                             <div className="flex items-center gap-2 text-[10px] font-bold text-emerald-400 uppercase tracking-wider">
                               <CheckCircle2 size={10} />
                               Update Complete
                             </div>
                             <div className="text-slate-200 font-medium">{msg.summary}</div>
                             {msg.files_changed && msg.files_changed.length > 0 && (
                               <div className="flex items-center gap-1.5 text-[10px] text-slate-500">
                                 <FileCode size={10} />
                                 {msg.files_changed.length} file{msg.files_changed.length > 1 ? 's' : ''} changed
                               </div>
                             )}
                          </div>
                        )}
                      </div>
                    </div>
                  ))}
                  {isChatting && (
                    <div className="flex items-center gap-2 text-slate-500 text-xs animate-pulse">
                      <Loader2 size={12} className="animate-spin" />
                      Applying patches...
                    </div>
                  )}
                  <div ref={chatEndRef} />
                </div>
                
                <div className="p-4 border-t border-slate-800">
                  <div className="relative">
                    <input 
                      type="text"
                      value={inputValue}
                      onChange={(e) => setInputValue(e.target.value)}
                      onKeyDown={(e) => e.key === 'Enter' && handleSendMessage()}
                      placeholder="Request changes..."
                      className="w-full bg-slate-950 border border-slate-700 rounded-lg pl-3 pr-10 py-2 text-xs text-slate-200 focus:outline-none focus:border-blue-500 transition-colors"
                    />
                    <button 
                      onClick={handleSendMessage}
                      disabled={!inputValue.trim() || isChatting}
                      className="absolute right-2 top-1/2 -translate-y-1/2 text-slate-500 hover:text-blue-400 disabled:opacity-50 disabled:hover:text-slate-500 transition-colors"
                    >
                      <Send size={16} />
                    </button>
                  </div>
                </div>
              </div>
            </div>
          )}

        </div>
      </div>
    </div>
  );
};

export default CodeViewer;