import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { BehaviorSubject, Observable, tap, catchError, throwError } from 'rxjs'; import { Router } from '@angular/router'; @Injectable({ providedIn: 'root', }) export class AuthService { private baseUrl = location.hostname.endsWith('hf.space') ? 'https://pykara-py-match-backend.hf.space/api' : 'http://localhost:5000/api'; private isLoggedInSubject = new BehaviorSubject(false); private currentUserId = new BehaviorSubject(this.getUserIdFromStorage()); private userIdSubject = new BehaviorSubject(this.getUserIdFromStorage()); constructor(private http: HttpClient, private router: Router) { // Check if user is already logged in (from session) this.initializeAuthState(); } // Get user ID from storage with sessionStorage priority private getUserIdFromStorage(): number | null { const savedUserId = sessionStorage.getItem('user_id') || localStorage.getItem('user_id'); return savedUserId ? Number(savedUserId) : null; } setUserId(userId: number): void { // Use sessionStorage as primary sessionStorage.setItem('user_id', userId.toString()); // Update both BehaviorSubjects for consistency this.currentUserId.next(userId); this.userIdSubject.next(userId); this.isLoggedInSubject.next(true); console.log('🔐 AuthService - User ID set via setUserId:', userId); } getUserId(): number | null { // Prefer sessionStorage over localStorage const userId = sessionStorage.getItem('user_id') || localStorage.getItem('user_id'); return userId ? parseInt(userId, 10) : null; } private initializeAuthState(): void { const savedUserId = this.getUserIdFromStorage(); const savedUserData = sessionStorage.getItem('user_data') || localStorage.getItem('user_data'); if (savedUserId && savedUserData) { this.isLoggedInSubject.next(true); this.currentUserId.next(savedUserId); this.userIdSubject.next(savedUserId); console.log('🔐 AuthService initialized with user:', savedUserId); } else { console.log('🔐 AuthService initialized - no user logged in'); } } get isAuthenticated(): boolean { return this.isLoggedInSubject.value; } get userId(): number | null { return this.currentUserId.value; } get userId$(): Observable { return this.currentUserId.asObservable(); } /** SIGN UP */ signUp(name: string, email: string, password: string): Observable { return this.http.post(`${this.baseUrl}/signup`, { name, email, password }).pipe( tap((response: any) => { if (response.message && response.user_id) { this.setUserId(response.user_id); // Store user data in sessionStorage (primary) const userData = { user_id: response.user_id, name: name, email: email }; sessionStorage.setItem('user_id', response.user_id.toString()); sessionStorage.setItem('user_data', JSON.stringify(userData)); // Keep localStorage as fallback only localStorage.setItem('user_id', response.user_id.toString()); localStorage.setItem('user_name', name); console.log('✅ Signup successful, user auto-logged in:', response.user_id); } }), catchError((error) => { console.error('Signup error:', error); return throwError(() => error); }) ); } /** LOGIN */ login(email: string, password: string): Observable { return this.http.post(`${this.baseUrl}/login`, { email, password }).pipe( tap((response: any) => { if (response.message === 'Login successful.' && response.user_id) { this.setUserId(response.user_id); // Store user data in sessionStorage (primary) const userData = { user_id: response.user_id, name: response.name, email: response.email }; sessionStorage.setItem('user_id', response.user_id.toString()); sessionStorage.setItem('user_data', JSON.stringify(userData)); // Keep localStorage as fallback only localStorage.setItem('user_id', response.user_id.toString()); if (response.name) { localStorage.setItem('user_name', response.name); localStorage.setItem('userName', response.name); localStorage.setItem('name', response.name); } console.log('✅ Login successful, user ID:', response.user_id); } }), catchError((error) => { console.error('Login error:', error); return throwError(() => error); }) ); } /** LOGOUT - UPDATED: Remove page reload to preserve animations */ logout(): void { console.log('🔐 AuthService - Logging out user:', this.currentUserId.value); // Update BehaviorSubjects first this.isLoggedInSubject.next(false); this.currentUserId.next(null); this.userIdSubject.next(null); // Clear session storage sessionStorage.clear(); // Clear all session storage to be safe // Clear specific localStorage items localStorage.removeItem('user_id'); localStorage.removeItem('user_name'); localStorage.removeItem('userName'); localStorage.removeItem('name'); localStorage.removeItem('auth_token'); console.log('✅ Logout complete - all storage cleared'); // Only navigate, don't reload - let the component handle the UI state this.router.navigate(['/']); } // Alternative logout method that doesn't navigate at all logoutSilent(): void { console.log('🔐 AuthService - Silent logout for user:', this.currentUserId.value); // Update BehaviorSubjects first this.isLoggedInSubject.next(false); this.currentUserId.next(null); this.userIdSubject.next(null); // Clear session storage sessionStorage.clear(); // Clear specific localStorage items localStorage.removeItem('user_id'); localStorage.removeItem('user_name'); localStorage.removeItem('userName'); localStorage.removeItem('name'); localStorage.removeItem('auth_token'); console.log('✅ Silent logout complete - storage cleared without navigation'); } // Check if user is logged in (observable) get isLoggedIn$(): Observable { return this.isLoggedInSubject.asObservable(); } }