import { useState, useEffect, useCallback } from 'react'; import { useStore } from '@nanostores/react'; import { toast } from 'react-toastify'; import Cookies from 'js-cookie'; import type { GitLabConnection } from '~/types/GitLab'; import { useGitLabAPI } from './useGitLabAPI'; import { gitlabConnectionStore, gitlabConnection, isGitLabConnected } from '~/lib/stores/gitlabConnection'; export interface ConnectionState { isConnected: boolean; isLoading: boolean; isConnecting: boolean; connection: GitLabConnection | null; error: string | null; } export interface UseGitLabConnectionReturn extends ConnectionState { connect: (token: string, gitlabUrl?: string) => Promise; disconnect: () => void; refreshConnection: () => Promise; testConnection: () => Promise; refreshStats: () => Promise; } const STORAGE_KEY = 'gitlab_connection'; export function useGitLabConnection(): UseGitLabConnectionReturn { const connection = useStore(gitlabConnection); const isConnected = useStore(isGitLabConnected); const [error, setError] = useState(null); const [isLoading, setIsLoading] = useState(true); const [isConnecting, setIsConnecting] = useState(false); // Create API instance - will update when connection changes useGitLabAPI( connection?.token ? { token: connection.token, baseUrl: connection.gitlabUrl || 'https://gitlab.com' } : { token: '', baseUrl: 'https://gitlab.com' }, ); // Load saved connection on mount useEffect(() => { loadSavedConnection(); }, []); const loadSavedConnection = useCallback(async () => { setIsLoading(true); setError(null); try { // Check if connection already exists in store (likely from initialization) if (connection?.user) { setIsLoading(false); return; } // Load saved connection from localStorage const savedConnection = localStorage.getItem(STORAGE_KEY); if (savedConnection) { const parsed = JSON.parse(savedConnection); if (parsed.user && parsed.token) { // Update the store with saved connection gitlabConnectionStore.setGitLabUrl(parsed.gitlabUrl || 'https://gitlab.com'); gitlabConnectionStore.setToken(parsed.token); // Test the connection to make sure it's still valid await refreshConnectionData(parsed); } } setIsLoading(false); } catch (error) { console.error('Error loading saved connection:', error); setError('Failed to load saved connection'); setIsLoading(false); // Clean up corrupted data localStorage.removeItem(STORAGE_KEY); } }, [connection]); const refreshConnectionData = useCallback(async (connection: GitLabConnection) => { if (!connection.token) { return; } try { // Make direct API call instead of using hook const baseUrl = connection.gitlabUrl || 'https://gitlab.com'; const response = await fetch(`${baseUrl}/api/v4/user`, { headers: { 'Content-Type': 'application/json', 'PRIVATE-TOKEN': connection.token, }, }); if (!response.ok) { throw new Error(`API error: ${response.status}`); } // const userData = (await response.json()) as GitLabUserResponse; await response.json(); // Parse response but don't store - data handled by store /* * Update connection with user data - unused variable removed * const updatedConnection: GitLabConnection = { * ...connection, * user: userData, * }; */ gitlabConnectionStore.setGitLabUrl(baseUrl); gitlabConnectionStore.setToken(connection.token); } catch (error) { console.error('Error refreshing connection data:', error); } }, []); const connect = useCallback(async (token: string, gitlabUrl = 'https://gitlab.com') => { if (!token.trim()) { setError('Token is required'); return; } setIsConnecting(true); setError(null); try { console.log('Calling GitLab store connect method...'); // Use the store's connect method which handles everything properly const result = await gitlabConnectionStore.connect(token, gitlabUrl); if (!result.success) { throw new Error(result.error || 'Connection failed'); } console.log('GitLab connection successful, now fetching stats...'); // Fetch stats after successful connection try { const statsResult = await gitlabConnectionStore.fetchStats(true); if (statsResult.success) { console.log('GitLab stats fetched successfully:', statsResult.stats); } else { console.error('Failed to fetch GitLab stats:', statsResult.error); } } catch (statsError) { console.error('Failed to fetch GitLab stats:', statsError); // Don't fail the connection if stats fail } toast.success('Connected to GitLab successfully!'); } catch (error) { console.error('Failed to connect to GitLab:', error); const errorMessage = error instanceof Error ? error.message : 'Failed to connect to GitLab'; setError(errorMessage); toast.error(`Failed to connect: ${errorMessage}`); throw error; } finally { setIsConnecting(false); } }, []); const disconnect = useCallback(() => { // Clear localStorage localStorage.removeItem(STORAGE_KEY); // Clear all GitLab-related cookies Cookies.remove('gitlabToken'); Cookies.remove('gitlabUsername'); Cookies.remove('gitlabUrl'); // Reset store gitlabConnectionStore.disconnect(); setError(null); toast.success('Disconnected from GitLab'); }, []); const refreshConnection = useCallback(async () => { if (!connection?.token) { throw new Error('No connection to refresh'); } setIsLoading(true); setError(null); try { await refreshConnectionData(connection); } catch (error) { console.error('Error refreshing connection:', error); setError('Failed to refresh connection'); throw error; } finally { setIsLoading(false); } }, [connection, refreshConnectionData]); const testConnection = useCallback(async (): Promise => { if (!connection?.token) { return false; } try { const baseUrl = connection.gitlabUrl || 'https://gitlab.com'; const response = await fetch(`${baseUrl}/api/v4/user`, { headers: { 'Content-Type': 'application/json', 'PRIVATE-TOKEN': connection.token, }, }); return response.ok; } catch (error) { console.error('Connection test failed:', error); return false; } }, [connection]); const refreshStats = useCallback(async () => { if (!connection?.token) { throw new Error('No connection to refresh stats'); } try { const statsResult = await gitlabConnectionStore.fetchStats(true); if (!statsResult.success) { throw new Error(statsResult.error || 'Failed to refresh stats'); } } catch (error) { console.error('Error refreshing GitLab stats:', error); throw error; } }, [connection]); return { isConnected, isLoading, isConnecting, connection, error, connect, disconnect, refreshConnection, testConnection, refreshStats, }; }