import 'dart:developer';

import 'package:flutter/material.dart';
import 'package:hub/flutter_flow/nav/nav.dart';
import 'package:hub/shared/utils/dialog_util.dart';
import 'package:hub/shared/utils/storage_util.dart';

import '../../../backend/api_requests/api_calls.dart';
import '../../../components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart';
import '../../../flutter_flow/flutter_flow_util.dart';
import '../../utils/log_util.dart';
import '../../utils/snackbar_util.dart';
import '../authentication/authentication_service.dart';

class LocalizationService {


  static Future<void> checkLocals(BuildContext context) async {
    try {
      final GetLocalsCall callback = PhpGroup.getLocalsCall;
      var response = await callback.call();
      final bool isError = response.jsonBody['error'];

      if (isError) {
        _handleError(context, response.jsonBody['error_msg']);
        return;
      }

      final List<dynamic> locals = response.jsonBody['locais'] ?? [];
      final bool isEmpty = locals.isEmpty;
      final bool isActive = locals.where((local) => local['CLU_STATUS'] != 'B').isNotEmpty;
      final bool isEnable = !isEmpty && isActive;

      if (isEnable) {
        StorageUtil().haveLocal = true;
        StorageUtil().isLogged = true;
        await WidgetsBinding.instance.endOfFrame;
        StorageUtil().cliUUID = '';
        StorageUtil().ownerUUID = '';
        StorageUtil().context?.go('/homePage');
      }
    } catch (e, s) {
      log(e.toString(), stackTrace: s);
    }
  }
  static Future<bool> processLocals(BuildContext context) async {
    try {
      await StorageUtil().ensureInitialization();
      final GetLocalsCall callback = PhpGroup.getLocalsCall;
      final ApiCallResponse response = await callback.call();
      final bool isError = response.jsonBody['error'];

      if (isError) {
        final String errorMsg = response.jsonBody['error_msg'];
        _handleError(context, errorMsg);
        return false;
      }

      final List<dynamic> locals = response.jsonBody['locais'].toList() ?? [];
      _logLocalsStatus(locals);

      final bool isActive = _isActive(locals);
      final bool isInactived = _isInactived(locals);
      final bool isPending = _isPending(locals);
      final bool isUnique = locals.length == 1;
      final bool isBlocked = locals.where((local) => local['CLU_STATUS'] == 'B').isNotEmpty;
      final bool isEnabled = isUnique && isActive;
      final bool isDisabled = isUnique && isBlocked;
      final bool isUnselected = _isUnselected();
      final bool isSelected = _isSelected(isInactived);
      final bool isUnavailable = isPending && isUnselected && isUnique;
      final bool isAvailable = _isAvailable();

      if (isDisabled) {
        AuthenticationService.signOut(context);
        return true;
      } else if (isUnavailable) {
        return await _handleUnavailable(context, locals);
      } else if (isEnabled) {
        return await _handleEnabled(context, locals[0]);
      } else if (isUnselected) {
        log('() => isUnselected');
        return await selectLocal(context);
      } else if (isSelected) {
        log('() => isSelected');
        return await processData(context);
      } else if (isAvailable) {
        log('() => isAvailable');
        return await processData(context);
      }  else {
        if  (!isUnique && !isActive)      log('() => not unique and not active');
        if  (!isUnique && isInactived)    log('() => not unique and inactived');
        if  (!isUnique && isPending)      log('() => not unique and pending');
        if  (!isUnique && isBlocked)      log('() => not unique and blocked');
                                          log('() => else');
        return await selectLocal(context);
      }
    } catch (e, s) {
      log('() => stack: $s');
      log('() => catch: $e', stackTrace: s);
      // return await selectLocal(context);
      final String errorMsg = FFLocalizations.of(context).getVariableText(
        enText: 'Error getting locals, verify your connection',
        ptText: 'Erro ao obter locais, verifique sua conexão',
      );
      DialogUtil.error(context, errorMsg).whenComplete(() => selectLocal(context));
      return false;
    }
  }
  static Future<bool> processData(BuildContext context) async {
    try {
      await StorageUtil().ensureInitialization();
      final GetDadosCall callback = PhpGroup.getDadosCall;
      var response = await callback.call();
      final bool error = response.jsonBody['error'];

      if (error == true || error == 'true') {
        final String errorMsg = response.jsonBody['error_msg'];
        DialogUtil.error(context, errorMsg).whenComplete(() => selectLocal(context));
        return false;
      }
      else {
        _updateStorageUtil(response.jsonBody);
        return true;
      }
    } catch (e, s) {
      log('() => stack processData: $s');
      log('() => error processData: $e', stackTrace: s);
      final String errorMsg = FFLocalizations.of(context).getVariableText(
        enText: 'Error getting data, verify your connection',
        ptText: 'Erro ao obter dados, verifique sua conexão',
      );
      DialogUtil.error(context, errorMsg).whenComplete(() => selectLocal(context));
      return false;
    }
  }
  static Future<bool> selectLocal(BuildContext context) async {
    return await showModalBottomSheet(
      isScrollControlled: true,
      backgroundColor: Colors.transparent,
      enableDrag: false,
      isDismissible: false,
      showDragHandle: false,
      useSafeArea: true,
      context: context,
      builder: (context) => PopScope(
        canPop: false,
        child: Padding(
          padding: MediaQuery.viewInsetsOf(context),
          child: const BottomArrowLinkedLocalsComponentWidget(),
        ),
      ),
    ).then((_) async => await processData(context));
  }
  static Future<void> unlinkLocal(BuildContext context) async {
    String content;
    try {
      content = FFLocalizations.of(context).getVariableText(
        enText: 'Device unlinked successfully',
        ptText: 'Dispositivo desvinculado com sucesso',
      );

      await PhpGroup.resopndeVinculo.call(tarefa: 'I').then((value) {
        if (value.jsonBody['error'] == false) {
          StorageUtil().cliName = '';
          StorageUtil().cliUUID = '';
          context.pop();
          context.go(
            '/homePage',
            extra: <String, dynamic>{
              kTransitionInfoKey: const TransitionInfo(
                hasTransition: true,
                transitionType: PageTransitionType.scale,
                alignment: Alignment.bottomCenter,
              ),
            },
          );
          SnackBarUtil.showSnackBar(context, content);
        }
      }).catchError((err, stack) {
        context.pop();
        content = FFLocalizations.of(context).getVariableText(
          enText: 'Error unlinking device',
          ptText: 'Erro ao desvincular dispositivo',
        );
        SnackBarUtil.showSnackBar(context, content, isError: true);
      });
    } catch (err, stack) {
      context.pop();
      log(err.toString(), stackTrace: stack);
      content = FFLocalizations.of(context).getVariableText(
        enText: 'Error unlinking device',
        ptText: 'Erro ao desvincular dispositivo',
      );
      SnackBarUtil.showSnackBar(context, content, isError: true);
    }
  }

  static void _handleError(BuildContext context, String errorMsg) {
    AuthenticationService.signOut(context);
    DialogUtil.error(context, errorMsg);
    LogUtil.requestAPIFailed('getLocals.php', '{devUUID: ${StorageUtil().devUUID}, cliUUID: ${StorageUtil().userUUID}}', 'Get Locals', errorMsg, StackTrace.current);
  }
  static Future<bool> _handleUnavailable(BuildContext context, List<dynamic> locals) async {
    log('() => isUnavailable');
    try {
      StorageUtil().cliUUID = locals[0]['CLI_ID'];
      StorageUtil().ownerUUID = locals[0]['CLU_OWNER_ID'];
      StorageUtil().cliName = locals[0]['CLI_NOME'];
      var response = await PhpGroup.resopndeVinculo.call(tarefa: 'A');
      if (response.jsonBody['error'] == true) {
        StorageUtil().cliUUID = '';
        StorageUtil().cliName = '';
        StorageUtil().ownerUUID = '';
        return false;
      }
      if (response.jsonBody['error'] == false) return await processData(context).then((value) => value);
    } catch (e, s) {
      DialogUtil.errorDefault(context);
      LogUtil.requestAPIFailed('responderVinculo.php', '', 'Responder Vínculo', e, s);
      return false;
    }
    return false;
  }
  static Future<bool> _handleEnabled(BuildContext context, dynamic local) async {
    log('() => isEnabled');
    StorageUtil().cliName = local['CLI_NOME'];
    StorageUtil().userName = local['USU_NOME'];
    StorageUtil().cliUUID = local['CLI_ID'];
    StorageUtil().ownerUUID = local['CLU_OWNER_ID'];
    return await processData(context);
  }

  static void _logLocalsStatus(List<dynamic> locals) {
    for (var local in locals) {
      final String status = local['CLU_STATUS'];
      log('() => CLU_STATUS: $status');
    }
  }
  static bool _isActive(List<dynamic> locals) {
    return locals.where((local) => local['CLU_STATUS'] == 'A').isNotEmpty;
  }
  static bool _isInactived(List<dynamic> locals) {
    return locals.where((local) => local['CLI_ID'] != StorageUtil().cliUUID && local['CLU_STATUS'] == 'A').isNotEmpty;
  }
  static bool _isPending(List<dynamic> locals) {
    return locals.where((local) => local['CLU_STATUS'] != 'B' && local['CLU_STATUS'] != 'A').isNotEmpty;
  }
  static bool _isUnselected() {
    return StorageUtil().cliUUID.isEmpty && StorageUtil().cliName.isEmpty && StorageUtil().ownerUUID.isEmpty;
  }
  static bool _isSelected(bool isInactived) {
    return StorageUtil().cliUUID.isNotEmpty && StorageUtil().cliName.isNotEmpty && isInactived;
  }
  static bool _isAvailable() {
    return StorageUtil().cliUUID.isNotEmpty && StorageUtil().cliName.isNotEmpty;
  }
  static void _updateStorageUtil(Map<String, dynamic> jsonBody) {
    StorageUtil().whatsapp = jsonBody['whatsapp'] ?? false;
    StorageUtil().provisional = jsonBody['provisional'] ?? false;
    StorageUtil().pets = jsonBody['pet'] ?? false;
    StorageUtil().petAmountRegister = jsonBody['petAmountRegister'].toString().isEmpty ? '0' : jsonBody['petAmountRegister'].toString();
    StorageUtil().userName = jsonBody['visitado']['VDO_NOME'];
  }


}