import 'dart:async';
import 'dart:io';

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:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart' as sqflite_native;
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
import 'package:pyramid/core/auth_log.dart';
import 'package:pyramid/core/voip_manager.dart';

final matrixClientProvider = FutureProvider<Client>((ref) async {
  final DatabaseFactory factory;

  if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) {
    // Use the native sqflite plugin — Android/iOS have system SQLite built-in,
    // no .so loading required.
    factory = sqflite_native.databaseFactory;
  } else if (!kIsWeb) {
    sqfliteFfiInit();
    factory = databaseFactoryFfi;
  } else {
    throw UnsupportedError('Web not supported');
  }

  final appDir = await getApplicationSupportDirectory();
  final dbPath = p.join(appDir.path, 'pyramid.sqlite');

  final db = await factory.openDatabase(dbPath);
  
  // Optimization for Windows/FFI to prevent "database is locked" errors
  try {
    await db.execute('PRAGMA journal_mode=WAL');
    await db.execute('PRAGMA busy_timeout = 5000');
  } catch (e) {
    if (kDebugMode) debugPrint('Could not set PRAGMAs: $e');
  }

  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,
    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();
});
