import React, { useState, useEffect, useCallback, useRef } from 'react';
import { Routes, Route, useNavigate, useLocation, useParams } from 'react-router-dom';
import { Menu } from 'lucide-react';
import Sidebar from './components/Sidebar';
import MainChat from './components/MainChat';
import ChatInput from './components/ChatInput';
import MessageBubble from './components/MessageBubble';
import ForkPanel from './components/ForkPanel';
import Settings from './pages/Settings';
import ExamHistory from './components/ExamHistory';
import FlashcardReview from './components/FlashcardReview';
import CalendarHeatmap from './components/CalendarHeatmap';
import RoadmapVisual from './components/RoadmapVisual';
import PomodoroTimer from './components/PomodoroTimer';
import MultiPdfCompare from './components/MultiPdfCompare';
import AutoForkPrompt from './components/AutoForkPrompt';
import ExamPanel from './components/ExamPanel';
import StudyBuddyPanel from './components/StudyBuddyPanel';
import { ToastProvider, useToast } from './components/Toast';
import { ReactionsProvider } from './context/ReactionsContext';
import { useMediaQuery } from './hooks/useMediaQuery';
import useChat from './hooks/useChat';
import usePdfs from './hooks/usePdfs';
import useProgress from './hooks/useProgress';
import useExams from './hooks/useExams';
import useFlashcards from './hooks/useFlashcards';
import useStudySessions from './hooks/useStudySessions';
import useExam from './hooks/useExam';
import useStudyBuddy from './hooks/useStudyBuddy';
import {
  getConversations,
  createConversation,
  updateConversation,
  getModels,
  forkConversation,
  mergeConversation,
  getNotes,
  shareConversation,
  getSharedConversation,
  generateExam,
} from './lib/api';
import './App.css';

function ToastBridge({ onReady }) {
  const { error } = useToast();
  useEffect(() => { onReady(error); }, [onReady, error]);
  return null;
}

function BuddyRouteWrapper({ onJoin, buddyHook, shareToken, onShare }) {
  const { token } = useParams();
  useEffect(() => {
    if (token) {
      onJoin(token);
    }
  }, [token, onJoin]);
  return (
    <StudyBuddyPanel
      conversation={buddyHook.conversation}
      messages={buddyHook.messages}
      roleLabel={buddyHook.roleLabel}
      counterpartLabel={buddyHook.counterpartLabel}
      onShare={onShare}
      shareToken={shareToken}
      onJoin={onJoin}
      loading={buddyHook.loading}
    />
  );
}

export default function App() {
  const [conversaciones, setConversaciones] = useState([]);
  const [conversationActiva, setConversationActiva] = useState(null);
  const [forkActivo, setForkActivo] = useState(null);
  const [modelos, setModelos] = useState([]);
  const [modeloSeleccionado, setModeloSeleccionado] = useState(null);
  const [notas, setNotas] = useState([]);
  const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
  const [forkWidth, setForkWidth] = useState(320);
  const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false);
  const [hasLoadedConversations, setHasLoadedConversations] = useState(false);
  const [hasLoadedPdfs, setHasLoadedPdfs] = useState(false);
  const [pendingPrompt, setPendingPrompt] = useState('');
  const toastError = useRef(null);
  const searchInputRef = useRef(null);
  const handleToastReady = useCallback((fn) => { toastError.current = fn; }, []);

  const [activeExam, setActiveExam] = useState(null);
  const [buddyToken, setBuddyToken] = useState(null);
  const [shareToken, setShareToken] = useState(null);

  const isMobile = useMediaQuery('(max-width: 767px)');
  const navigate = useNavigate();
  const location = useLocation();

  const pdfsHook = usePdfs();
  const progressHook = useProgress();
  const examsHook = useExams();
  const flashcardsHook = useFlashcards();
  const sessionsHook = useStudySessions();
  const chatHook = useChat({
    conversationId: conversationActiva?.id ?? null,
    onProgressUpdate: progressHook.updateExercise,
    onStudySession: (date, minutes) => sessionsHook.recordSession(date, minutes),
    onAutoFork: ({ topic }) => {
      console.log('[App] auto-fork suggested:', topic);
    },
    onDifficultyChanged: ({ level }) => {
      console.log('[App] difficulty changed:', level);
    },
  });

  const examHook = useExam(activeExam);
  const buddyHook = useStudyBuddy(buddyToken);

  // Load initial data
  useEffect(() => {
    let mounted = true;

    async function load() {
      try {
        const [models, convs, notesList] = await Promise.all([
          getModels(),
          getConversations(),
          getNotes(),
        ]);
        if (!mounted) return;
        setModelos(models);
        setConversaciones(convs);
        setNotas(notesList);
        const defaultModel = models.find((m) => m.is_default_main) || models[0] || null;
        setModeloSeleccionado(defaultModel);
        // Load PDFs and progress
        pdfsHook.refresh();
        progressHook.refresh();
        examsHook.refresh();
        flashcardsHook.refresh();
        setHasLoadedConversations(true);
        setHasLoadedPdfs(true);
      } catch (err) {
        console.error('[App] load error:', err.message);
        toastError.current?.('Error al cargar los datos. Verifica que el servidor esté funcionando.');
      }
    }

    load();
    return () => { mounted = false; };
  }, []);

  // Load messages when active conversation changes
  useEffect(() => {
    if (!conversationActiva) return;
    chatHook.setActiveId(conversationActiva.id);
  }, [conversationActiva?.id]);

  // Auto-close mobile sidebar when resizing to desktop
  useEffect(() => {
    if (!isMobile) {
      setMobileSidebarOpen(false);
    }
  }, [isMobile]);

  // Global keyboard shortcuts
  useEffect(() => {
    function handleKeyDown(e) {
      const tag = e.target?.tagName;
      const isInput = tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || e.target?.isContentEditable;
      const ctrlOrMeta = e.ctrlKey || e.metaKey;

      if (ctrlOrMeta) {
        if (isInput && e.key !== 'Enter') return;
        switch (e.key.toLowerCase()) {
          case 'n':
            e.preventDefault();
            handleNewConversation();
            break;
          case 'k':
            e.preventDefault();
            searchInputRef.current?.focus();
            break;
          case 'enter':
            e.preventDefault();
            window.dispatchEvent(new CustomEvent('studyos:send-message'));
            break;
          default:
            break;
        }
      } else if (e.key === 'Escape') {
        if (forkActivo) {
          setForkActivo(null);
        }
      }
    }
    document.addEventListener('keydown', handleKeyDown);
    return () => document.removeEventListener('keydown', handleKeyDown);
  }, [forkActivo, handleNewConversation]);

  // Listen for search result navigation: select conversation
  useEffect(() => {
    function handleSelectConversation(e) {
      const { id } = e.detail || {};
      if (!id) return;
      const conv = conversaciones.find((c) => c.id === id);
      if (conv) {
        setConversationActiva(conv);
        setForkActivo(null);
      }
    }
    window.addEventListener('studyos:select-conversation', handleSelectConversation);
    return () => window.removeEventListener('studyos:select-conversation', handleSelectConversation);
  }, [conversaciones]);

  const handleSelectConversation = useCallback((conv) => {
    setConversationActiva(conv);
    setForkActivo(null);
  }, []);

  const handleNewConversation = useCallback(async () => {
    try {
      const conv = await createConversation({
        title: 'Nueva conversación',
        model_id: modeloSeleccionado?.id ?? null,
      });
      setConversaciones((prev) => [conv, ...prev]);
      setConversationActiva(conv);
      setForkActivo(null);
    } catch (err) {
      console.error('[App] new conversation error:', err.message);
    }
  }, [modeloSeleccionado]);

  const handleFork = useCallback(async (topic) => {
    if (!conversationActiva) return;
    try {
      const fork = await forkConversation(conversationActiva.id, {
        topic,
        model_id: modeloSeleccionado?.id ?? null,
      });
      setConversaciones((prev) => [fork, ...prev]);
      setForkActivo(fork);
    } catch (err) {
      console.error('[App] fork error:', err.message);
    }
  }, [conversationActiva, modeloSeleccionado]);

  const handleMergeFork = useCallback(async () => {
    if (!forkActivo) return;
    try {
      await mergeConversation(forkActivo.id);
      setForkActivo(null);
      // Refresh conversations list (sidebar needs fresh data)
      const convs = await getConversations();
      setConversaciones(convs);
      // Refresh messages of parent conversation
      if (conversationActiva) {
        chatHook.setActiveId(conversationActiva.id);
      }
    } catch (err) {
      console.error('[App] merge error:', err.message);
    }
  }, [forkActivo, conversationActiva, chatHook]);

  const handleCloseFork = useCallback(() => {
    setForkActivo(null);
  }, []);

  const handleAutoForkAccept = useCallback(() => {
    if (chatHook.autoForkPrompt?.topic) {
      handleFork(chatHook.autoForkPrompt.topic);
      chatHook.setAutoForkPrompt(null);
    }
  }, [chatHook.autoForkPrompt, handleFork, chatHook]);

  const handleAutoForkDismiss = useCallback(() => {
    chatHook.setAutoForkPrompt(null);
  }, [chatHook]);

  const handleShareConversation = useCallback(async () => {
    if (!conversationActiva) return;
    try {
      const data = await shareConversation(conversationActiva.id, 'compañero');
      setShareToken(data.token);
    } catch (err) {
      console.error('[App] share error:', err.message);
    }
  }, [conversationActiva]);

  const handleJoinBuddy = useCallback(async (token) => {
    if (!token) return;
    try {
      setBuddyToken(token);
      navigate(`/buddy/${token}`);
    } catch (err) {
      console.error('[App] join buddy error:', err.message);
    }
  }, [navigate]);

  const handleGenerateExam = useCallback(async (topic, pdfIds, numQuestions, durationSeconds) => {
    try {
      const data = await generateExam({
        conversation_id: conversationActiva?.id ?? null,
        topic,
        pdf_ids: pdfIds,
        num_questions: numQuestions,
        duration_seconds: durationSeconds,
      });
      setActiveExam(data);
      navigate(`/exam/${data.id}`);
    } catch (err) {
      console.error('[App] generate exam error:', err.message);
    }
  }, [conversationActiva, navigate]);

  const handleRenameConversation = useCallback(async (id, title) => {
    try {
      await updateConversation(id, { title });
    } catch (err) {
      console.error('[App] rename conversation error:', err.message);
    }
    setConversaciones((prev) =>
      prev.map((c) => (c.id === id ? { ...c, title } : c))
    );
    if (conversationActiva?.id === id) {
      setConversationActiva((prev) => (prev ? { ...prev, title } : prev));
    }
  }, [conversationActiva]);

  const handleRoadmapFork = useCallback((topic) => {
    setPendingPrompt(`Explica ${topic} en detalle`);
    setConversationActiva(null);
    navigate('/');
  }, [navigate]);

  const mainConvs = conversaciones.filter((c) => c.type === 'main');

  const isHome = location.pathname === '/';

  const appContent = (
    <div className="app-layout">
      {isMobile && isHome && (
        <button
          className="hamburger-btn"
          onClick={() => setMobileSidebarOpen((s) => !s)}
          title="Toggle sidebar"
          style={{ position: 'absolute', top: 10, left: 10, zIndex: 35 }}
        >
          <Menu size={20} />
        </button>
      )}
      <Sidebar
        collapsed={sidebarCollapsed}
        onToggle={() => setSidebarCollapsed((s) => !s)}
        pdfs={pdfsHook.pdfs}
        progress={progressHook.progress}
        conversations={mainConvs}
        activeConversation={conversationActiva}
        notes={notas}
        onSelectConversation={handleSelectConversation}
        onNewConversation={handleNewConversation}
        onUploadPdf={pdfsHook.uploadPdf}
        onReorderPdf={pdfsHook.reorderPdf}
        onDeletePdf={pdfsHook.deletePdf}
        onResetTopic={progressHook.resetTopic}
        onNavigateSettings={() => navigate('/settings')}
        onNavigate={navigate}
        hasLoadedConversations={hasLoadedConversations}
        hasLoadedPdfs={hasLoadedPdfs}
        isMobileOpen={mobileSidebarOpen}
        onClose={() => setMobileSidebarOpen(false)}
        searchInputRef={searchInputRef}
        dueCount={flashcardsHook.dueCount}
      />
      <main className="app-main">
        <Routes>
          <Route
            path="/"
            element={
              <>
                <MainChat
                  conversation={conversationActiva}
                  modelo={modeloSeleccionado}
                  modelos={modelos}
                  onModelChange={setModeloSeleccionado}
                  onFork={handleFork}
                  messages={chatHook.messages}
                  isStreaming={chatHook.isStreaming}
                  MessageBubbleComponent={MessageBubble}
                  onRenameConversation={handleRenameConversation}
                />
                <AutoForkPrompt
                  topic={chatHook.autoForkPrompt?.topic}
                  onAccept={handleAutoForkAccept}
                  onDismiss={handleAutoForkDismiss}
                />
                <ChatInput
                  onSend={(text, pdfIds, attachments) =>
                    chatHook.sendMessage(text, pdfIds, attachments)
                  }
                  isStreaming={chatHook.isStreaming}
                  availablePdfs={pdfsHook.pdfs}
                  prefillText={pendingPrompt}
                />
              </>
            }
          />
          <Route path="/settings" element={<Settings />} />
          <Route path="/exams" element={<ExamHistory exams={examsHook.exams} onDelete={examsHook.remove} onRefresh={examsHook.refresh} onGenerate={handleGenerateExam} />} />
          <Route path="/exam/:id" element={<ExamPanel exam={activeExam} useExamHook={examHook} />} />
          <Route path="/flashcards" element={<FlashcardReview cards={flashcardsHook.cards} queue={flashcardsHook.queue} onRefresh={flashcardsHook.fetchNext} onMarkSeen={flashcardsHook.markSeen} onUpdate={flashcardsHook.update} onDelete={flashcardsHook.remove} />} />
          <Route path="/heatmap" element={<CalendarHeatmap heatmapData={sessionsHook.heatmapData} onRefresh={sessionsHook.heatmap} />} />
          <Route path="/roadmap" element={<RoadmapVisual onForkTopic={handleRoadmapFork} />} />
          <Route path="/timer" element={<PomodoroTimer />} />
          <Route path="/compare" element={<MultiPdfCompare />} />
          <Route path="/buddy/:token" element={<BuddyRouteWrapper
            onJoin={handleJoinBuddy}
            buddyHook={buddyHook}
            shareToken={shareToken}
            onShare={handleShareConversation}
          />} />
        </Routes>
      </main>
      <ForkPanel
        forkId={forkActivo?.id ?? null}
        forkTitle={forkActivo?.title || ''}
        onClose={handleCloseFork}
        onMerge={handleMergeFork}
        width={forkWidth}
        onResize={setForkWidth}
      />
    </div>
  );

  return (
    <ToastProvider>
      <ToastBridge onReady={handleToastReady} />
      <ReactionsProvider>
        {appContent}
      </ReactionsProvider>
    </ToastProvider>
  );
}
