import { useState, useEffect, createContext, useContext } from 'react';
import { Routes, Route, Navigate, useNavigate } from 'react-router-dom';
import { User, setOnTokenRefreshed } from './lib/api';
import { socketClient } from './lib/socket';
import Header from './components/Header';
import StatusBar from './components/StatusBar';
import Home from './pages/Home';
import ProjectManager from './pages/ProjectManager';
import SignIn from './pages/SignIn';
import ChatSessionView from './pages/ChatSessionView';
import DroneManager from './pages/DroneManager';
import Settings from './pages/Settings';

const TOKEN_KEY = 'dtp_auth_token';
const USER_KEY = 'dtp_user';
const PROJECT_KEY = 'dtp_current_project';

function getStoredUser(): User | null {
  try {
    const userData = localStorage.getItem(USER_KEY);
    return userData ? JSON.parse(userData) : null;
  } catch {
    return null;
  }
}

function setStoredUser(user: User | null) {
  if (user) {
    localStorage.setItem(USER_KEY, JSON.stringify(user));
  } else {
    localStorage.removeItem(USER_KEY);
  }
}

export function getStoredProject(): string | null {
  return localStorage.getItem(PROJECT_KEY);
}

export function setStoredProject(slug: string | null) {
  if (slug) {
    localStorage.setItem(PROJECT_KEY, slug);
  } else {
    localStorage.removeItem(PROJECT_KEY);
  }
}

interface AppContextType {
  user: User | null;
  updateUser: (user: User) => void;
  currentProject: string | null;
  setCurrentProject: (slug: string | null) => void;
  onSignOut: () => void;
  statusMessage: string;
  setStatusMessage: (message: string) => void;
}

export const AppContext = createContext<AppContextType | null>(null);

export function useAppContext(): AppContextType {
  const ctx = useContext(AppContext);
  if (!ctx) throw new Error('useAppContext must be used within App provider');
  return ctx;
}

export default function App() {
  const navigate = useNavigate();
  const [user, setUser] = useState<User | null>(null);
  const [currentProject, setCurrentProject] = useState<string | null>(null);
  const [loading, setLoading] = useState(true);
  const [statusMessage, setStatusMessage] = useState<string>('Ready.');

  useEffect(() => {
    const storedUser = getStoredUser();
    const storedToken = localStorage.getItem(TOKEN_KEY);
    const storedProject = localStorage.getItem(PROJECT_KEY);
    if (storedUser && storedToken) {
      setUser(storedUser);
      socketClient.connect(storedToken);
    }
    if (storedProject) {
      setCurrentProject(storedProject);
    }

    // Register callback so the socket client updates its JWT whenever
    // the API client refreshes the token. This ensures that future
    // socket reconnections use the new token instead of the expired one.
    setOnTokenRefreshed((newToken: string) => {
      socketClient.updateJwt(newToken);
    });

    setLoading(false);
  }, []);

  const handleSignInSuccess = (newUser: User, token: string) => {
    localStorage.setItem(TOKEN_KEY, token);
    setStoredUser(newUser);
    setUser(newUser);
    socketClient.connect(token);
  };

  const handleUpdateUser = (updatedUser: User) => {
    setStoredUser(updatedUser);
    setUser(updatedUser);
  };

  const handleSignOut = async () => {
    try {
      await fetch('/api/v1/auth/sign-out', {
        method: 'GET',
        credentials: 'include',
      });
    } catch {
      // Ignore errors — we're signing out regardless
    }
    localStorage.removeItem(TOKEN_KEY);
    localStorage.removeItem(PROJECT_KEY);
    setStoredUser(null);
    setUser(null);
    setCurrentProject(null);
    socketClient.disconnect();
    navigate('/');
  };

  const handleSetCurrentProject = (slug: string | null) => {
    setStoredProject(slug);
    setCurrentProject(slug);
  };

  if (loading) {
    return (
      <div className="h-screen flex items-center justify-center bg-bg-primary">
        <div className="text-text-muted">Loading...</div>
      </div>
    );
  }

  return (
    <AppContext.Provider value={{ user, updateUser: handleUpdateUser, currentProject, setCurrentProject: handleSetCurrentProject, onSignOut: handleSignOut, statusMessage, setStatusMessage }}>
        <div className="h-screen flex flex-col bg-bg-primary">
          <Header user={user} onSignOut={handleSignOut} />
          <main className="flex-1 flex overflow-hidden">
            <Routes>
              <Route path="/" element={<Home user={user} />} />
              <Route path="/projects" element={<ProjectManager user={user} />} />
              <Route path="/projects/new" element={<ProjectManager user={user} />} />
              <Route path="/projects/:slug" element={<ProjectManager user={user} />} />
              <Route path="/drones" element={<DroneManager user={user} />} />
              <Route path="/settings" element={user ? <Settings /> : <Navigate to="/sign-in" replace />} />
              <Route path="/projects/:projectId/chat-session/:sessionId" element={<ChatSessionView />} />
               <Route
                 path="/sign-in"
                 element={
                   user ? (
                     <Navigate to="/" replace />
                   ) : (
                     <SignIn onSuccess={handleSignInSuccess} />
                   )
                 }
               />
             </Routes>
          </main>
          <StatusBar statusMessage={statusMessage} projectSlug={currentProject} />
        </div>
    </AppContext.Provider>
  );
}