import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:flutter_vodozemac/flutter_vodozemac.dart' as vod;
import 'package:matrix/encryption/utils/key_verification.dart';
import 'package:matrix/matrix.dart';
import 'package:pyramid/core/app_database.dart';
import 'package:pyramid/core/auth_log.dart';
import 'package:pyramid/core/soft_logout_guard.dart';
// Kompositions-Punkt: Einzige Stelle außerhalb des call_signaling-Moduls,
// die die Implementierung (statt der Fassade) kennen darf – sie erzeugt sie.
import 'package:pyramid/features/call_signaling/voip_manager.dart';

final matrixClientProvider = FutureProvider<Client>((ref) async {
  // Factory-Wahl, Verschlüsselung (SQLCipher), Migration und PRAGMAs stecken
  // komplett in der Storage-Fassade — siehe docs/SQLCIPHER_MIGRATION.md.
  final db = await AppDatabase.open();

  final sdkDb = await MatrixSdkDatabase.init('pyramid', database: db);

  final client = Client(
    'Pyramid',
    database: sdkDb,
    // Custom State-Events, die beim App-Start mit aus der DB geladen werden
    // müssen — sonst sind Space-Banner & Voice-Presence nach Neustart leer,
    // bis der jeweilige Raum vollständig nachgeladen wird.
    importantStateEvents: {
      'io.pyramid.space.banner',
      'io.pyramid.voice.presence',
    },
    verificationMethods: {
      KeyVerificationMethod.numbers,
      KeyVerificationMethod.emoji,
      KeyVerificationMethod.qrShow,
    },
    logLevel: kReleaseMode ? Level.warning : Level.verbose,
    // Ohne eigenen Handler eskaliert das SDK jeden fehlgeschlagenen
    // Token-Refresh (auch bloße Netzwerkfehler!) zu logout()+clear() —
    // Session und Krypto-Schlüssel wären weg. Siehe soft_logout_guard.dart.
    onSoftLogout: guardedSoftLogoutRefresh,
    nativeImplementations: NativeImplementationsIsolate(
      compute,
      vodozemacInit: () => vod.init(),
    ),
  );

  // Persistiert Warnungen/Fehler des SDK sowie jeden Login-Status-Wechsel,
  // damit ein unerwarteter Logout (z. B. Soft-Logout vom Server) auch nach
  // einem App-Neustart noch nachvollziehbar ist (ROADMAP M1, Uta-Logout-Bug).
  Logs().onLog = (event) {
    if (event.level.index <= Level.warning.index) {
      unawaited(AuthLog.write('[SDK ${event.level.name}] ${event.toFormattedString()}'));
    }
  };
  client.onLoginStateChanged.stream.listen((state) {
    unawaited(AuthLog.write('LoginState -> ${state.name}'));
  });

  await client.init(
    waitForFirstSync: false,
    waitUntilLoadCompletedLoaded: false,
  );

  // Re-use or create singleton instance
  try {
    PyramidVoipManager.instance.client; 
  } catch (_) {
    PyramidVoipManager(client);
  }
  
  return client;
});

final secureStorageProvider = Provider<FlutterSecureStorage>((ref) {
  return const FlutterSecureStorage();
});
