import 'dart:developer';

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hub/features/local/index.dart';
import 'package:hub/features/menu/index.dart';
import 'package:hub/features/module/data/index.dart';
import 'package:hub/features/notification/index.dart';
import 'package:hub/features/storage/index.dart';
import 'package:hub/flutter_flow/index.dart';

import 'package:hub/shared/utils/dialog_util.dart';
import 'package:rxdart/rxdart.dart';

class LocalsRepositoryImpl implements LocalsRepository {
  final LocalsRemoteDataSource remoteDataSource = LocalsRemoteDataSourceImpl();
  final LocalsLocalDataSourceImpl localDataSource = LocalsLocalDataSourceImpl();

  static final license = BehaviorSubject<LicenseStatus>();
  static get stream => license.stream;

  @override
  Future<void> validateLocal(BuildContext context) async {
    return await remoteDataSource.linkLocal(context);
  }

  @override
  Future<bool> update(BuildContext context) async {
    LocalsRepositoryImpl.license.add(false);
    final bool response = await _handleLocal(context);
    LocalsRepositoryImpl.license.add(response);
    return response;
  }

  @override
  Future<bool> fetch(BuildContext context) async {
    return await _handleProperty(context);
  }

  Future<void> select(BuildContext context) async {
    await unselect();
    await update(context);
  }

  Future<void> unselect() async {
    await StorageHelper().set(ProfileStorageKey.clientUUID.key, '');
    await StorageHelper().set(ProfileStorageKey.clientName.key, '');
    await StorageHelper().set(ProfileStorageKey.ownerName.key, '');
  }

  Future<void> check(BuildContext context) async {
    final String? cliUUID =
        await StorageHelper().get(ProfileStorageKey.clientUUID.key);
    final String? ownerUUID =
        await StorageHelper().get(ProfileStorageKey.ownerUUID.key);
    final bool haveCli = cliUUID != null && cliUUID.isNotEmpty;
    final bool haveOwner = ownerUUID != null && ownerUUID.isNotEmpty;
    if (!haveCli && !haveOwner) {
      log('No client or owner selected');
      await update(context);
      await FirebaseMessagingService().updateDeviceToken();
    }
  }

  Future<bool> _handleLocal(BuildContext context) async {
    bool response = false;
    final bool isUnselected = await remoteDataSource.checkLocals(context);
    if (!isUnselected) {
      log('_handleLocal -> No local selected');
      while (!response) {
        try {
          response = await remoteDataSource.processLocals(context);
          if (!response) {
            await _handleUpdateError(context);
          }
        } catch (e, s) {
          log('Error updating locals: $e', stackTrace: s);
          await _handleUpdateError(context);
        }
      }
    } else {
      log('_handleLocal -> Local selected');

      return true;
    }

    return response;
  }

  Future<bool> _handleProperty(BuildContext context) async {
    bool response = false;
    try {
      response = await remoteDataSource.processProperty(context);
      if (!response) {
        await _handleUpdateError(context);
      }
    } catch (e, s) {
      log('Error updating locals: $e', stackTrace: s);
      await _handleUpdateError(context);
    }
    return response;
  }

  Future<void> _handleUpdateError(BuildContext context) async {
    await StorageHelper().set(ProfileStorageKey.clientUUID.key, '');
    const String errorMsg = 'Erro ao atualizar locais';
    await DialogUtil.error(context, errorMsg);
  }

  Future<void> _notifyBlocs(BuildContext context) async {
    context.read<LocalProfileBloc>().add(LocalProfileEvent());
    context.read<MenuBloc>().add(MenuEvent());
  }

  @override
  Future<void> unlinkLocal(BuildContext context) async {
    final bool response = await remoteDataSource.detachLocal(context);
    if (!response) return;
    await unselect();
    context.pop();
    context.go('/homePage', extra: {'update': update});
    await update(context);
  }
}
