import React, { useState, useEffect } from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import io from 'socket.io-client';

import client from './shared/api/client';
import { checkSetup, getProfile, logout } from './shared/api/authApi';
import { LoadingSpinner } from './shared/components';
import AppProviders from './app/AppProviders';
import AppRoutes from './app/routes';

import './styles/base/App.css';

function AppContent() {
  const [isAuthenticated, setIsAuthenticated] = useState(false);
  const [setupComplete, setSetupComplete] = useState(null);
  const [socket, setSocket] = useState(null);
  const [loading, setLoading] = useState(true);

  const forceLogout = React.useCallback(() => {
    localStorage.removeItem('token');
    setIsAuthenticated(false);
  }, []);

  // Global interceptor any 401/403 kicks the user back to login
  useEffect(() => {
    const interceptorId = client.interceptors.response.use(
      (response) => response,
      (error) => {
        if (error.response?.status === 401 || error.response?.status === 403) {
          forceLogout();
        }
        return Promise.reject(error);
      }
    );
    return () => client.interceptors.response.eject(interceptorId);
  }, [forceLogout]);

  useEffect(() => {
    // Check if setup is complete and validate any stored token
    const loadSetupStatus = async () => {
      try {
        const response = await checkSetup();
        // If we get a 200 response, setup is required
        if (response.status === 200) {
          setSetupComplete(false);
        }
      } catch (err) {
        if (err.response?.status === 400) {
          // 400 means setup is already complete
          setSetupComplete(true);
        } else {
          // Assume setup is complete if we can't reach the endpoint
          setSetupComplete(true);
        }
      } finally {
        setLoading(false);
      }
    };

    // Validate the stored token against the server before trusting it
    const validateToken = async () => {
      const token = localStorage.getItem('token');
      if (!token) return;
      try {
        await getProfile();
        setIsAuthenticated(true);
      } catch {
        // Token is expired, revoked, or invalid, clear it
        localStorage.removeItem('token');
        setIsAuthenticated(false);
      }
    };

    loadSetupStatus();
    validateToken();

    // Initialize WebSocket connection in production the frontend is served
    // from the same origin as the backend, so no URL is needed.
    const backendUrl = process.env.REACT_APP_BACKEND_URL || undefined;
    const newSocket = io(backendUrl || window.location.origin, {
      reconnection: true,
      reconnectionDelay: 1000,
      reconnectionDelayMax: 5000,
      reconnectionAttempts: 5,
    });

    newSocket.on('connect', () => {
      console.log('Connected to server');
    });

    setSocket(newSocket);

    return () => newSocket.close();
  }, []);

  const handleLogin = (token) => {
    localStorage.setItem('token', token);
    setIsAuthenticated(true);
  };

  const handleLogout = async () => {
    try {
      const token = localStorage.getItem('token');
      if (token) {
        await logout();
      }
    } catch (err) {
      // Logout even if the API call fails
      console.error('Logout API error:', err);
    }
    forceLogout();
  };

  const handleSetupComplete = () => {
    setSetupComplete(true);
  };

  if (loading) {
    return (
      <div className="loading-page">
        <LoadingSpinner size="large" text="Initializing status page..." />
      </div>
    );
  }

  return (
    <Router>
      <AppRoutes
        socket={socket}
        isAuthenticated={isAuthenticated}
        setupComplete={setupComplete}
        onLogin={handleLogin}
        onLogout={handleLogout}
        onSetupComplete={handleSetupComplete}
      />
    </Router>
  );
}

function App() {
  return (
    <AppProviders>
      <AppContent />
    </AppProviders>
  );
}

export default App;
