import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:injectable/injectable.dart';
import '../../data/models/user.dart';
import '../../data/models/user_role.dart';
import '../../data/datasources/keycloak_auth_service.dart';
import '../../data/datasources/permission_engine.dart';
import '../../../../core/storage/dashboard_cache_manager.dart';

// === ÉVÉNEMENTS ===
abstract class AuthEvent extends Equatable {
  const AuthEvent();
  @override
  List<Object?> get props => [];
}

class AuthLoginRequested extends AuthEvent {
  final String email;
  final String password;
  const AuthLoginRequested(this.email, this.password);
  @override
  List<Object?> get props => [email, password];
}

class AuthLogoutRequested extends AuthEvent { const AuthLogoutRequested(); }
class AuthStatusChecked extends AuthEvent { const AuthStatusChecked(); }
class AuthTokenRefreshRequested extends AuthEvent { const AuthTokenRefreshRequested(); }

// === ÉTATS ===
abstract class AuthState extends Equatable {
  const AuthState();
  @override
  List<Object?> get props => [];
}

class AuthInitial extends AuthState {}
class AuthLoading extends AuthState {}
class AuthUnauthenticated extends AuthState {}

class AuthAuthenticated extends AuthState {
  final User user;
  final UserRole effectiveRole;
  final List<String> effectivePermissions;
  final String accessToken;

  const AuthAuthenticated({
    required this.user,
    required this.effectiveRole,
    required this.effectivePermissions,
    required this.accessToken,
  });

  @override
  List<Object?> get props => [user, effectiveRole, effectivePermissions, accessToken];
}

class AuthError extends AuthState {
  final String message;
  const AuthError(this.message);
  @override
  List<Object?> get props => [message];
}

// === BLOC ===
@lazySingleton
class AuthBloc extends Bloc<AuthEvent, AuthState> {
  final KeycloakAuthService _authService;

  AuthBloc(this._authService) : super(AuthInitial()) {
    on<AuthLoginRequested>(_onLoginRequested);
    on<AuthLogoutRequested>(_onLogoutRequested);
    on<AuthStatusChecked>(_onStatusChecked);
    on<AuthTokenRefreshRequested>(_onTokenRefreshRequested);
  }

  Future<void> _onLoginRequested(AuthLoginRequested event, Emitter<AuthState> emit) async {
    emit(AuthLoading());
    try {
      final user = await _authService.login(event.email, event.password);
      if (user != null) {
        final permissions = await PermissionEngine.getEffectivePermissions(user);
        final token = await _authService.getValidToken();
        await DashboardCacheManager.invalidateForRole(user.primaryRole);
        
        emit(AuthAuthenticated(
          user: user,
          effectiveRole: user.primaryRole,
          effectivePermissions: permissions,
          accessToken: token ?? '',
        ));
      } else {
        emit(const AuthError('Identifiants incorrects.'));
      }
    } catch (e) {
      emit(AuthError('Erreur de connexion: $e'));
    }
  }

  Future<void> _onLogoutRequested(AuthLogoutRequested event, Emitter<AuthState> emit) async {
    emit(AuthLoading());
    await _authService.logout();
    await DashboardCacheManager.clear();
    emit(AuthUnauthenticated());
  }

  Future<void> _onStatusChecked(AuthStatusChecked event, Emitter<AuthState> emit) async {
    final tokenValid = await _authService.getValidToken();
    final isAuth = tokenValid != null;
    if (!isAuth) {
      emit(AuthUnauthenticated());
      return;
    }
    final user = await _authService.getCurrentUser();
    if (user == null) {
      emit(AuthUnauthenticated());
      return;
    }
    final permissions = await PermissionEngine.getEffectivePermissions(user);
    final token = await _authService.getValidToken();
    emit(AuthAuthenticated(
      user: user,
      effectiveRole: user.primaryRole,
      effectivePermissions: permissions,
      accessToken: token ?? '',
    ));
  }

  Future<void> _onTokenRefreshRequested(AuthTokenRefreshRequested event, Emitter<AuthState> emit) async {
    if (state is AuthAuthenticated) {
      final newToken = await _authService.refreshToken();
      final success = newToken != null;
      if (success) {
        add(AuthStatusChecked());
      } else {
        add(AuthLogoutRequested());
      }
    }
  }
}
