import 'package:app_gaslieferung/bloc/authentication/auth_event.dart';
import 'package:app_gaslieferung/bloc/authentication/auth_state.dart';
import 'package:app_gaslieferung/bloc/message_wrapper/message_bloc.dart';
import 'package:app_gaslieferung/bloc/message_wrapper/message_event.dart';
import 'package:app_links/app_links.dart';
import 'package:bloc/bloc.dart';
import 'package:flutter/cupertino.dart';
import 'package:url_launcher/url_launcher.dart';

import '../../exceptions/login.dart';
import '../../util/login.dart';

class AuthBloc extends Bloc<AuthEvent, AuthState> {
  final _appLinks = AppLinks();
  final MessageBloc msgBloc;
  final String url;

  AuthBloc({required this.url, required this.msgBloc}) : super(UnauthenticatedState()) {
    on<AuthLoginEvent>(_onLoginEvent);
    on<AuthLogoutEvent>(_onLogoutEvent);
    on<AuthFailedEvent>(_onFailedEvent);
    on<AuthLoginSuccessEvent>(_onLoginSuccessEvent);

    _initDeepLinks();
  }

  void _initDeepLinks() async {
    // Listen to the stream if any further deeplink is coming in.
    _appLinks.uriLinkStream.listen((uri) {
      _handleDeepLink(uri);
    });
  }

  /// Handle Deeplink if login request is coming in.
  void _handleDeepLink(Uri uri) {
    if (state is UnauthenticatedState) {
      try {
        add(AuthLoginSuccessEvent(getSessionIdFromUrl(uri)));
      } on LoginInvalidUrlException catch (e) {
        msgBloc.add(MessageShow(message: e.toString()));
      } on LoginNoSessionIdException catch (e) {
        msgBloc.add(MessageShow(message: e.toString()));
      } catch (e, st) {
        debugPrint("Fehler beim Login. Stacktrace: $st");
        debugPrint("Fehler beim Login. Message: $e");

        add(
          AuthFailedEvent(
            message:
            "Es ist ein unbekannter Fehler aufgetreten. Versuchen Sie es später erneut oder wenden Sie sich an die Zentrale.",
          ),
        );
      }
    } else {
      // TODO: handle message if user is already logged in
      debugPrint("NOT STATE");
      debugPrint("$state");
    }
  }

  void _onLoginSuccessEvent(
    AuthLoginSuccessEvent event,
    Emitter<AuthState> emit,
  ) {
    emit(AuthenticatedState(sessionId: event.sessionId));
  }

  void _onLoginEvent(AuthLoginEvent event, Emitter<AuthState> emit) async {
    await launchUrl(
      Uri.parse(url),
      mode: LaunchMode.externalApplication,
    );
  }

  void _onLogoutEvent(AuthLogoutEvent event, Emitter<AuthState> emit) {

  }

  void _onFailedEvent(AuthFailedEvent event, Emitter<AuthState> emit) {
    emit(UnauthenticatedState());
  }
}
