import 'dart:io';

import 'package:common/storage/common_preferences.dart';
import 'package:common/utils/env_utils.dart';
import 'package:flutter/services.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:msal_auth/msal_auth.dart';

import '../gen/assets.gen.dart';

const _msalChannel = MethodChannel('msal_auth');

class MSALService {
  final scopes = dotenv.ENTRA_SCOPES.split(',');
  final authorityUrl = dotenv.ENTRA_ID_AUTHORITY_URL;
  final clientId = dotenv.ENTRA_ID_CLIENT_ID;
  final redirect = dotenv.ENTRA_ID_REDIRECT_URL;

  late final SingleAccountPca msAuth;
  final _preferences = CommonPreferences();

  MSALService();

  Future<void> init() async {
    try {
      await _preferences.init();
      final configFilePath = switch (appFlavor?.toLowerCase()) {
        "develop" => "packages/common/${Assets.msal.msalConfigDev}",
        "stage" => "packages/common/${Assets.msal.msalConfigStage}",
        "prod" => "packages/common/${Assets.msal.msalConfigProd}",
        _ => throw Exception("Missing config file for flavor $appFlavor"),
      };
      msAuth = await SingleAccountPca.create(
        clientId: clientId,
        androidConfig: AndroidConfig(configFilePath: configFilePath, redirectUri: redirect),
        appleConfig: AppleConfig(
          authorityType: AuthorityType.aad,
          broker: Broker.webView,
          authority: authorityUrl,
        ),
      );
      // if (Platform.isIOS) await _clearStaleAccounts();
    } catch (e) {
      print("qqq msauth init=$e");
    }
  }

  /// Removes all cached accounts from the MSAL keychain cache.
  /// This prevents the "Multiple accounts found in cache" error
  /// that breaks SingleAccountPca on iOS.
  Future<void> _clearStaleAccounts() async {
    try {
      final result = await _msalChannel.invokeMethod('getAccounts');
      if (result is List && result.length > 1) {
        for (final account in result) {
          final id = (account as Map)['id'] as String?;
          if (id != null) {
            try {
              await _msalChannel.invokeMethod('removeAccount', id);
            } catch (_) {}
          }
        }
      }
    } catch (e) {
      print('qqq _clearStaleAccounts: $e');
    }
  }

  Future<void> openAuth(Prompt prompt) async {
    try {
      await msAuth.acquireToken(
        scopes: scopes,
        prompt: prompt,
        customWebViewConfig: const CustomWebViewConfig(),
        authority: authorityUrl,
      );
      await _preferences.setIsLoggedIn(true);
    } catch (e) {
      await logout();
      rethrow;
    }
  }

  Future<String> acquireTokenSilent() async {
    try {
      final response = await msAuth.acquireTokenSilent(scopes: scopes, authority: authorityUrl);
      await _preferences.setIsLoggedIn(true);
      return response.accessToken;
    } catch (e) {
      await logout();
      rethrow;
    }
  }

  Future<void> logout() async {
    await _preferences.setIsLoggedIn(false);
    try {
      await _clearStaleAccounts();
      await msAuth.signOut();
    } catch (e) {
      // Ignore sign-out errors
    }
  }

  bool get isLoggedIn => _preferences.isLoggedIn;
}