import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';

/// Tracks the user's authentication state so the [GoRouter] can decide
/// whether to allow access to protected routes (such as the groups
/// flow) or redirect to the sign-in screen.
///
/// The router is wired to refresh whenever [notifyListeners] is called,
/// which means any place that mutates the auth state (login, logout,
/// registration completion) just has to call [refresh] to keep the
/// navigation layer in sync.
class AuthState extends ChangeNotifier {
  /// SharedPreferences key used to persist the auth token returned by
  /// the backend after a successful sign-in.
  static const String _tokenKey = 'token';

  bool _isLoggedIn = false;
  bool _initialized = false;

  /// The route the user originally tried to visit before being sent to
  /// the sign-in screen. After a successful login, the redirect logic
  /// reads and clears this so the user lands where they were heading.
  String? _intendedRoute;

  bool get isLoggedIn => _isLoggedIn;

  String? get intendedRoute => _intendedRoute;

  /// Loads the current auth state from disk. Safe to call multiple
  /// times; subsequent calls just re-read the token value.
  Future<void> initialize() async {
    final prefs = await SharedPreferences.getInstance();
    _update(prefs.getString(_tokenKey) != null);
    _initialized = true;
  }

  /// Re-reads the auth state from disk and notifies listeners if it
  /// has changed. Call this from places that mutate the persisted
  /// token (e.g. after the login API call or after the user logs out).
  Future<void> refresh() async {
    final prefs = await SharedPreferences.getInstance();
    _update(prefs.getString(_tokenKey) != null);
  }

  void _update(bool loggedIn) {
    if (_isLoggedIn == loggedIn) return;
    _isLoggedIn = loggedIn;
    // NOTE: we intentionally do NOT clear _intendedRoute here.  The
    // router's redirect callback reads it on the next build frame via
    // [consumeIntendedRoute], which is responsible for clearing it
    // after it has been consumed.
    notifyListeners();
  }

  /// Called by the router's redirect callback when a protected route
  /// is hit by an unauthenticated user. Stores the route the user was
  /// trying to visit and returns the sign-in path the router should
  /// navigate to.
  String? requireAuth(String attemptedRoute) {
    if (_isLoggedIn) return null;
    // Avoid stacking redirects when the user is already on the
    // sign-in / sign-up screens.
    if (attemptedRoute.startsWith('/onboarding/')) return null;
    _intendedRoute = attemptedRoute;
    return '/onboarding/landing';
  }

  /// Returns the previously captured intended route so the router can
  /// navigate the user there after a successful sign-in. The value is
  /// consumed (cleared) once read to avoid loops.
  String? consumeIntendedRoute() {
    if (!_isLoggedIn) return null;
    final route = _intendedRoute;
    _intendedRoute = null;
    return route;
  }
}

/// Global singleton so widgets and the router can share the same
/// instance without needing to plumb a provider through the app.
final AuthState authState = AuthState();

/// Whether the auth state has finished its first read from disk.
/// The router waits for this before evaluating auth-gated redirects
/// so we don't briefly bounce users to the sign-in screen on cold
/// start before their persisted token has been loaded.
bool get isAuthInitialized => authState._initialized;
