/// BLoC pour la gestion des logs et du monitoring
library logs_monitoring_bloc;

import 'package:dio/dio.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:injectable/injectable.dart';
import 'package:equatable/equatable.dart';
import '../../../../core/utils/logger.dart';
import '../../data/repositories/logs_monitoring_repository.dart';
import '../../data/models/system_log_model.dart';
import '../../data/models/system_metrics_model.dart';
import '../../data/models/system_alert_model.dart';

// Events
abstract class LogsMonitoringEvent extends Equatable {
  @override
  List<Object?> get props => [];
}

class SearchLogs extends LogsMonitoringEvent {
  final String? level;
  final String? source;
  final String? searchQuery;
  final String? timeRange;
  SearchLogs({this.level, this.source, this.searchQuery, this.timeRange});
  @override
  List<Object?> get props => [level, source, searchQuery, timeRange];
}

class LoadMetrics extends LogsMonitoringEvent {}

class LoadAlerts extends LogsMonitoringEvent {}

class AcknowledgeAlert extends LogsMonitoringEvent {
  final String alertId;
  AcknowledgeAlert(this.alertId);
  @override
  List<Object?> get props => [alertId];
}

// States
abstract class LogsMonitoringState extends Equatable {
  @override
  List<Object?> get props => [];
}

class LogsMonitoringInitial extends LogsMonitoringState {}

class LogsMonitoringLoading extends LogsMonitoringState {}

class LogsLoaded extends LogsMonitoringState {
  final List<SystemLogModel> logs;
  LogsLoaded(this.logs);
  @override
  List<Object?> get props => [logs];
}

class MetricsLoaded extends LogsMonitoringState {
  final SystemMetricsModel metrics;
  MetricsLoaded(this.metrics);
  @override
  List<Object?> get props => [metrics];
}

class AlertsLoaded extends LogsMonitoringState {
  final List<SystemAlertModel> alerts;
  AlertsLoaded(this.alerts);
  @override
  List<Object?> get props => [alerts];
}

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

class LogsMonitoringError extends LogsMonitoringState {
  final String error;
  LogsMonitoringError(this.error);
  @override
  List<Object?> get props => [error];
}

// Bloc
@injectable
class LogsMonitoringBloc extends Bloc<LogsMonitoringEvent, LogsMonitoringState> {
  final LogsMonitoringRepository _repository;

  LogsMonitoringBloc(this._repository) : super(LogsMonitoringInitial()) {
    on<SearchLogs>(_onSearchLogs);
    on<LoadMetrics>(_onLoadMetrics);
    on<LoadAlerts>(_onLoadAlerts);
    on<AcknowledgeAlert>(_onAcknowledgeAlert);
  }

  Future<void> _onSearchLogs(SearchLogs event, Emitter<LogsMonitoringState> emit) async {
    emit(LogsMonitoringLoading());
    try {
      final logs = await _repository.searchLogs(
        level: event.level,
        source: event.source,
        searchQuery: event.searchQuery,
        timeRange: event.timeRange,
      );
      emit(LogsLoaded(logs));
    } catch (e, st) {
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      AppLogger.error('LogsMonitoringBloc: searchLogs échoué', error: e, stackTrace: st);
      emit(LogsMonitoringError('Erreur: ${e.toString()}'));
    }
  }

  Future<void> _onLoadMetrics(LoadMetrics event, Emitter<LogsMonitoringState> emit) async {
    emit(LogsMonitoringLoading());
    try {
      final metrics = await _repository.getMetrics();
      emit(MetricsLoaded(metrics));
    } catch (e, st) {
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      AppLogger.error('LogsMonitoringBloc: loadMetrics échoué', error: e, stackTrace: st);
      emit(LogsMonitoringError('Erreur: ${e.toString()}'));
    }
  }

  Future<void> _onLoadAlerts(LoadAlerts event, Emitter<LogsMonitoringState> emit) async {
    emit(LogsMonitoringLoading());
    try {
      final alerts = await _repository.getAlerts();
      emit(AlertsLoaded(alerts));
    } catch (e, st) {
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      AppLogger.error('LogsMonitoringBloc: loadAlerts échoué', error: e, stackTrace: st);
      emit(LogsMonitoringError('Erreur: ${e.toString()}'));
    }
  }

  Future<void> _onAcknowledgeAlert(AcknowledgeAlert event, Emitter<LogsMonitoringState> emit) async {
    emit(LogsMonitoringLoading());
    try {
      await _repository.acknowledgeAlert(event.alertId);
      final alerts = await _repository.getAlerts();
      emit(AlertsLoaded(alerts));
      emit(LogsMonitoringSuccess('Alerte acquittée'));
    } catch (e, st) {
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      AppLogger.error('LogsMonitoringBloc: acknowledgeAlert échoué', error: e, stackTrace: st);
      emit(LogsMonitoringError('Erreur: ${e.toString()}'));
    }
  }
}
