import 'package:get_it/get_it.dart';

import 'config/app_config.dart';
import 'data/services/bridge_service.dart';
import 'data/services/alarm_service.dart';
import 'data/services/coordination_service.dart';
import 'data/services/function_button_service.dart';
import 'data/services/state_service.dart';
import 'presentation/blocs/connection/connection_bloc.dart';
import 'presentation/blocs/camera/camera_bloc.dart';
import 'presentation/blocs/monitor/monitor_bloc.dart';
import 'presentation/blocs/ptz/ptz_bloc.dart';
import 'presentation/blocs/alarm/alarm_bloc.dart';
import 'presentation/blocs/lock/lock_bloc.dart';
import 'presentation/blocs/sequence/sequence_bloc.dart';
import 'presentation/blocs/wall/wall_bloc.dart';

final sl = GetIt.instance;

/// Initialize all dependencies
Future<void> initializeDependencies() async {
  // Config
  final config = await AppConfig.load();
  sl.registerSingleton<AppConfig>(config);

  // Services
  sl.registerLazySingleton<BridgeService>(() => BridgeService());
  sl.registerLazySingleton<AlarmService>(() => AlarmService());
  sl.registerLazySingleton<StateService>(() => StateService(
        bridgeService: sl<BridgeService>(),
        alarmService: sl<AlarmService>(),
      ));
  sl.registerLazySingleton<CoordinationService>(() => CoordinationService());
  sl.registerLazySingleton<FunctionButtonService>(() => FunctionButtonService(
        bridgeService: sl<BridgeService>(),
        coordinationService: sl<CoordinationService>(),
      ));

  // BLoCs
  sl.registerFactory<ConnectionBloc>(() => ConnectionBloc(
        bridgeService: sl<BridgeService>(),
        config: sl<AppConfig>(),
      ));

  sl.registerFactory<CameraBloc>(() => CameraBloc(
        bridgeService: sl<BridgeService>(),
        config: sl<AppConfig>(),
      ));

  sl.registerFactory<MonitorBloc>(() => MonitorBloc(
        stateService: sl<StateService>(),
        config: sl<AppConfig>(),
      ));

  sl.registerFactory<PtzBloc>(() => PtzBloc(
        bridgeService: sl<BridgeService>(),
        coordinationService: sl<CoordinationService>(),
      ));

  sl.registerFactory<AlarmBloc>(() => AlarmBloc(
        alarmService: sl<AlarmService>(),
        stateService: sl<StateService>(),
      ));

  sl.registerFactory<LockBloc>(() => LockBloc(
        coordinationService: sl<CoordinationService>(),
        keyboardId: sl<AppConfig>().keyboardId,
      ));

  sl.registerFactory<SequenceBloc>(() => SequenceBloc(
        coordinationService: sl<CoordinationService>(),
      ));

  sl.registerFactory<WallBloc>(() => WallBloc(
        bridgeService: sl<BridgeService>(),
      ));
}

/// Initialize services (call after dependencies are set up)
Future<void> initializeServices() async {
  final config = sl<AppConfig>();
  final bridgeService = sl<BridgeService>();
  final alarmService = sl<AlarmService>();
  final stateService = sl<StateService>();

  final coordinationService = sl<CoordinationService>();

  // Initialize services with config
  await bridgeService.initialize(config.servers);
  await alarmService.initialize(config.servers);
  await stateService.initialize();
  await coordinationService.initialize(config.coordinatorUrl, config.keyboardId);

  // Load function button config
  sl<FunctionButtonService>().loadConfig(config.functionButtons);

  // Wire reconnection callback: resync state when a bridge comes back online
  bridgeService.onReconnected = (serverId) {
    stateService.syncFromBridges();
  };

  // Connect to all bridges
  await bridgeService.connectAll();

  // Sync initial state
  await stateService.syncFromBridges();

  // Start periodic alarm sync
  alarmService.startPeriodicSync(
    Duration(seconds: config.alarmSyncIntervalSeconds),
  );

  // Connect to coordinator (non-blocking, auto-reconnects)
  coordinationService.connect();
}

/// Dispose all services
void disposeServices() {
  sl<CoordinationService>().dispose();
  sl<AlarmService>().dispose();
  sl<StateService>().dispose();
  sl<BridgeService>().dispose();
}
