import 'dart:developer';

// import 'package:hub/components/organisms/bottom_arrow_linked_locals/bottom_arrow_linked_locals_component_widget.dart';
import 'package:hub/backend/api_requests/api_calls.dart';
import 'package:hub/backend/api_requests/api_manager.dart';
import 'package:hub/components/molecular_components/option_selection_modal/option_selection_modal_widget.dart';
import 'package:hub/components/molecular_components/throw_exception/throw_exception_widget.dart';
import 'package:hub/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart';
import 'package:hub/custom_code/actions/get_dev_u_u_i_d.dart';
import 'package:hub/flutter_flow/flutter_flow_theme.dart';
import 'package:hub/flutter_flow/flutter_flow_util.dart';
import 'package:hub/flutter_flow/nav/nav.dart';

import 'package:flutter/material.dart';
import 'package:hub/flutter_flow/random_data_util.dart';
import 'package:hub/pages/home_page/home_page_model.dart';
import 'package:hub/shared/utils/dialog_util.dart';
import 'package:qr_flutter/qr_flutter.dart';

import 'package:url_launcher/url_launcher.dart';

import '../shared/utils/log_util.dart';

Future<void> openTermsOfUse(BuildContext context) async {
  log('openTermsOfUse');
  final Uri url = Uri.parse('https://freaccess.com.br/pp/');
  if (!await launchUrl(url)) {
    throw Exception('Could not launch $url');
  }
}

Future repeatVisitScheduleAction(
  BuildContext context, {
  List<dynamic>? visitorJsonList,
  String? visitorStrList,
  String? visitStartDateStr,
  String? visitEndDateStr,
  String? visitReasonStr,
  String? visitLevelStr,
  bool? visitTempBol,
  String? visitObsStr,
}) async {
  context.pushNamed(
    'scheduleCompleteVisitPage',
    queryParameters: {
      'visitStartDateStr': serializeParam(
        visitStartDateStr,
        ParamType.String,
      ),
      'visitEndDateStr': serializeParam(
        visitEndDateStr,
        ParamType.String,
      ),
      'visitReasonStr': serializeParam(
        visitReasonStr,
        ParamType.String,
      ),
      'visitLevelStr': serializeParam(
        visitLevelStr,
        ParamType.String,
      ),
      'visitTempBol': serializeParam(
        visitTempBol,
        ParamType.bool,
      ),
      'visitObsStr': serializeParam(
        visitObsStr,
        ParamType.String,
      ),
      'visitorStrList': serializeParam(
        visitorStrList,
        ParamType.String,
      ),
      'visitorJsonList': serializeParam(
        visitorJsonList,
        ParamType.JSON,
        isList: true,
      ),
    }.withoutNulls,
    extra: <String, dynamic>{
      kTransitionInfoKey: const TransitionInfo(
        hasTransition: true,
        transitionType: PageTransitionType.fade,
      ),
    },
  );
}

Future<Color> manageStatusColorAction(
  BuildContext context, {
  required String? visitStatusStr,
}) async {
  log('visitStatusStr: $visitStatusStr');
  if (visitStatusStr == 'A') {
    return FlutterFlowTheme.of(context).success;
  } else if ((visitStatusStr == 'C') ||
      (visitStatusStr == 'F') ||
      (visitStatusStr == 'B') ||
      (visitStatusStr == 'I')) {
    return FlutterFlowTheme.of(context).error;
  }

  return FlutterFlowTheme.of(context).warning;
}

Future singInLoginAction(
  BuildContext context, {
  String? emailAdress,
  String? password,
}) async {
  try {
    String? devUUID;
    ApiCallResponse? loginCall;

    await Future.wait([
      Future(() async {
        FFAppState().email = emailAdress!;
      }),
      Future(() async {
        FFAppState().passwd = password!;
      }),
    ]);

    if ((FFAppState().email != '') && (FFAppState().passwd != '')) {
      devUUID = await getDevUUID();

      FFAppState().devUUID = devUUID!;

      loginCall = await PhpGroup.loginCall.call(
        email: FFAppState().email,
        password: FFAppState().passwd,
        uuid: FFAppState().devUUID,
        type: FFAppState().device,
        description: randomString(
          10,
          10,
          true,
          false,
          false,
        ),
      );

      if (PhpGroup.loginCall.error((loginCall.jsonBody ?? '')) == false) {
        FFAppState().userUUID = PhpGroup.loginCall.userUUID(
          (loginCall.jsonBody ?? ''),
        )!;

        FFAppState().createdAt = dateTimeFormat(
          'd/M/y H:mm:ss',
          getCurrentTimestamp,
          locale: FFLocalizations.of(context).languageCode,
        );

        FFAppState().updatedAt = '00/00/0000 00:00:00';

        FFAppState().status =
            PhpGroup.loginCall.userStatus((loginCall.jsonBody ?? ''))!;

        FFAppState().userDevUUID =
            PhpGroup.loginCall.userDeviceId((loginCall.jsonBody ?? ''))!;

        FFAppState().name =
            PhpGroup.loginCall.userName((loginCall.jsonBody ?? ''))!;

        FFAppState().serialNumber = await getSerialNumber() ?? '';

        FFAppState().isLogged = true;

        await toggleHomePage(context);
      } else {
        if (PhpGroup.loginCall.msg((loginCall?.jsonBody ?? '')) == null) {
          DialogUtil.errorDefault(context);
        } else {
          DialogUtil.error(context,
              PhpGroup.loginCall.msg((loginCall?.jsonBody ?? '')).toString());
        }

        FFAppState().deleteEmail();
        FFAppState().email = '';

        FFAppState().deletePasswd();
        FFAppState().passwd = '';

        FFAppState().update(() {});
      }
    }

    return;
  } catch (e, s) {
    DialogUtil.errorDefault(context);
    LogUtil.requestAPIFailed(
        'login.php', emailAdress.toString(), "Login", e, s);
  }
}

Future<bool> signUpRegisterAction(
  BuildContext context, {
  required String? name,
  String? passwd,
  required String? email,
  String? device,
}) async {
  ApiCallResponse? registerCall;

  if ((email != null && email != '') &&
      (passwd != null && passwd != '') &&
      (name != null && name != '')) {
    registerCall = await PhpGroup.registerCall.call(
      name: name,
      password: passwd,
      email: email,
      token: randomString(
        36,
        36,
        false,
        false,
        true,
      ),
      uuid: randomString(
        36,
        36,
        false,
        false,
        true,
      ),
      tipo: device,
      descricao: randomString(
        36,
        36,
        true,
        false,
        false,
      ),
    );

    if (PhpGroup.registerCall.error(
          (registerCall.jsonBody ?? ''),
        ) ==
        false) {
      return true;
    }

    await showDialog(
      context: context,
      builder: (alertDialogContext) {
        return AlertDialog(
          title: const Text('Error'),
          content: Text('${registerCall?.jsonBody}'),
          actions: [
            TextButton(
              onPressed: () => Navigator.pop(alertDialogContext),
              child: const Text('ERROR2 '),
            ),
          ],
        );
      },
    );
    return false;
  } else {
    await showDialog(
      context: context,
      builder: (alertDialogContext) {
        return AlertDialog(
          title: Text(FFLocalizations.of(context).getVariableText(
            enText: 'Error',
            ptText: 'Erro',
          )),
          content: Text(FFLocalizations.of(context).getVariableText(
            enText: 'Please fill in all fields',
            ptText: 'Por favor, preencha todos os campos',
          )),
          actions: [
            TextButton(
              onPressed: () => Navigator.pop(alertDialogContext),
              child: Text(FFLocalizations.of(context).getVariableText(
                ptText: 'Fechar',
                enText: 'Close',
              )),
            ),
          ],
        );
      },
    );
    return false;
  }
}

Future forgotPasswdAction(
  BuildContext context, {
  required String? email,
}) async {
  ApiCallResponse? forgotPasswd;

  forgotPasswd = await PhpGroup.forgotPasswordCall.call(
    email: email,
  );

  if (PhpGroup.forgotPasswordCall.error(
        (forgotPasswd.jsonBody ?? ''),
      ) !=
      false) {
    return;
  }
}

Future cachingLoginActionApp(BuildContext context) async {
  if (FFAppState().isLogged == true) {
    context.pushNamed('homePage');
  } else {
    if (isAndroid == true) {
      FFAppState().device = 'Android';
    } else if (isiOS == true) {
      FFAppState().device = 'iOS';
    } else {
      FFAppState().device = 'Web';
    }
  }
}

Future toggleSignInPage(BuildContext context) async {
  context.pushNamed(
    'signInPage',
    extra: <String, dynamic>{
      kTransitionInfoKey: const TransitionInfo(
        hasTransition: true,
        transitionType: PageTransitionType.fade,
      ),
    },
  );
}

Future toggleSignUpPage(BuildContext context) async {
  context.pushNamed(
    'signUpPage',
    extra: <String, dynamic>{
      kTransitionInfoKey: const TransitionInfo(
        hasTransition: true,
        transitionType: PageTransitionType.fade,
      ),
    },
  );
}

Future toggleHomePage(BuildContext context) async {
  context.goNamed(
    'homePage',
    extra: <String, dynamic>{
      kTransitionInfoKey: const TransitionInfo(
        hasTransition: true,
        transitionType: PageTransitionType.fade,
      ),
    },
  );
}

Future<bool> visitRequestComponentAction(
  BuildContext context, {
  required String? actionValue,
  required String? refUUID,
  required String? responseValue,
  required String? vteUUID,
}) async {
  ApiCallResponse? respondeSolicitacaoCall;

  respondeSolicitacaoCall = await PhpGroup.respondeSolicitacaoCall.call(
    userUUID: FFAppState().userUUID,
    devUUID: FFAppState().devUUID,
    cliUUID: FFAppState().cliUUID,
    atividade: 'respondeSolicitacao',
    referencia: refUUID,
    tarefa: actionValue,
    resposta: responseValue,
    idVisitante: vteUUID,
  );

  if (respondeSolicitacaoCall.statusCode == 200) {
    return true;
  } else {
    log('headers: ${respondeSolicitacaoCall.headers}');
    log('bodyText: ${respondeSolicitacaoCall.bodyText}');
    log('jsonBody: ${respondeSolicitacaoCall.jsonBody}');
    log('userUUID: ${FFAppState().userUUID}');
    log('devUUID: ${FFAppState().devUUID}');
    log('cliUUID: ${FFAppState().cliUUID}');
    log('atividade: respondeSolicitacao');
    log('referencia: $refUUID');
    log('tarefa: $actionValue');
    log('resposta: $responseValue');
    log('idVisitante: $vteUUID');
    return false;
  }
}

Future<void> snackbar(BuildContext context, {required bool opt}) async {
  ScaffoldMessenger.of(context).showSnackBar(
    SnackBar(
      elevation: 10,
      margin: const EdgeInsets.all(50),
      content: Center(
        child: Text(
          opt
              ? FFLocalizations.of(context).getText('asjd2q3k2j4l21')
              : FFLocalizations.of(context).getText('asda2e42fafa'),
          style: TextStyle(
            fontSize: 16.0,
            fontWeight: FontWeight.normal,
            color: FlutterFlowTheme.of(context).info,
          ),
        ),
      ),
      backgroundColor: opt
          ? FlutterFlowTheme.of(context).success.withOpacity(0.5)
          : FlutterFlowTheme.of(context).error.withOpacity(0.5),
      duration: const Duration(seconds: 3),
      behavior: SnackBarBehavior.floating,
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
    ),
  );
}

Future<bool> checkLocals({
  String? cliUUID,
  required BuildContext context,
  required HomePageModel model,
  required void Function(void Function()) safeSetState,
}) async {
  // A chamada para a API permanece a mesma, assumindo que é necessária sempre.
  final response = await PhpGroup.getLocalsCall.call(
    devUUID: FFAppState().devUUID,
    userUUID: FFAppState().userUUID,
  );

  // Verificação rápida de erro para evitar processamento desnecessário.
  if (response.jsonBody['error']) {
    log("checkLocals => Erro encontrado na resposta");
    return false;
  }

  // Uso eficiente de coleções para verificar a condição desejada.
  final String uuid = cliUUID ?? FFAppState().cliUUID;
  final bool itemFound = response.jsonBody['locais'].any(
    (local) => local['CLI_ID'] == uuid && local['CLU_STATUS'] == "A",
  );

  // Log e retorno condicional baseado no resultado da busca.
  if (itemFound) {
    log("checkLocals => Item encontrado com CLI_ID $uuid e CLU_STATUS A");
    return true;
  } else {
    log("checkLocals => Item não encontrado com CLI_ID $uuid e CLU_STATUS A");
    // A chamada para showModalBottomSheet permanece, mas a atualização da UI é otimizada.
    await showModalBottomSheet(
      isScrollControlled: true,
      backgroundColor: Colors.transparent,
      enableDrag: false,
      context: context,
      builder: (context) => GestureDetector(
        onTap: () => model.unfocusNode.canRequestFocus
            ? FocusScope.of(context).requestFocus(model.unfocusNode)
            : FocusScope.of(context).unfocus(),
        child: Padding(
          padding: MediaQuery.viewInsetsOf(context),
          child: const BottomArrowLinkedLocalsComponentWidget(),
        ),
      ),
    );
    safeSetState(
        () {}); // Chamada otimizada fora do then para evitar encadeamentos desnecessários.
    return false;
  }
}

Future changeStatusAction(
  BuildContext context,
  String status,
  String vawREF,
  String msg,
  String vteUUID,
) async {
  log('status: $status');

  switch (status) {
    case 'L':
      Navigator.pop(context, true);

      bool? approveVisitRequest;
      approveVisitRequest = await visitRequestComponentAction(
        context,
        actionValue: status,
        refUUID: vawREF,
        responseValue: msg,
        vteUUID: vteUUID,
      );
      if (!context.mounted) return;
      if (approveVisitRequest == true) {
        log('Aprovado');
      } else {
        log('Erro ao aprovar');
      }
      break;
    case 'B':
      Navigator.pop(context, true);

      bool? blockVisitRequest;
      blockVisitRequest = await visitRequestComponentAction(
        context,
        actionValue: status,
        refUUID: vawREF,
        responseValue: msg,
        vteUUID: vteUUID,
      );
      if (!context.mounted) return;
      if (blockVisitRequest == true) {
        log('Bloqueado');
      } else {
        log('Erro ao bloquear');
      }
      break;
    default:
      break;
  }
}

/// QR Code

Uint8List assembleQRPacket(int direction, String identifier, String password) {
  List<int> packet = [direction];

  String paddedBadge = identifier.padLeft(30, '0');

  log("Badge: $paddedBadge");

  for (var i = 0; i < paddedBadge.length; i += 2) {
    packet.add(int.parse(paddedBadge.substring(i, i + 2), radix: 16));
  }

  DateTime now = DateTime.now();
  int year = now.year % 100;
  int month = now.month;
  int day = now.day;
  int hour = now.hour;
  int minute = now.minute;

  int sum = year + month + day + hour + minute;

  if (sum == int.parse('0D', radix: 16) || sum == int.parse('0A', radix: 16)) {
    packet.add(int.parse('FF', radix: 16));
  } else {
    packet.add(sum);
  }

  String paddedPassword = password.length != 4 ? 'FFFF' : password;

  for (var i = 0; i < paddedPassword.length; i += 2) {
    packet.add(int.parse(paddedPassword.substring(i, i + 2), radix: 16));
  }

  int check = 0x00;

  for (var b in packet) {
    check ^= b;
  }

  if (check == int.parse('0D', radix: 16) ||
      check == int.parse('0A', radix: 16)) {
    packet.add(int.parse('FF', radix: 16));
  } else {
    packet.add(check);
  }

  var bytes =
      packet.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join((' '));

  log("Pacote: $packet");
  log("Bytes: $bytes");
  return Uint8List.fromList(packet);
}

Uint8List hexStringToByteArray(String s) {
  int len = s.length;
  Uint8List data = Uint8List(len ~/ 2);
  for (int i = 0; i < len; i += 2) {
    data[i ~/ 2] =
        ((int.parse(s[i], radix: 16) << 4) + int.parse(s[i + 1], radix: 16));
  }
  return data;
}

String byteToHexa(Uint8List pDados) {
  return pDados
      .map((byte) => byte.toRadixString(16).padLeft(2, '0').toUpperCase())
      .join();
}

Future<String> byteToString(Uint8List bytes) async {
  return String.fromCharCodes(bytes);
}

Widget buildQrCode(
    {
    // required String data,
    // required String type,
    // required int version,
    // required int maskPattern,
    required int errorCorrectLevel,
    required double dimension,
    required String identifier,
    required String pass,
    required int direction}) {
  try {
    log("pass: $pass");
    const Color backgroundColor = Colors.white;
    const Color foregroundColor = Colors.black;
    return QrImageView.withQr(
        qr: QrCode.fromUint8List(
            data: assembleQRPacket(direction, identifier, pass),
            errorCorrectLevel: errorCorrectLevel),
        size: dimension,
        padding: const EdgeInsets.all(10),
        backgroundColor: backgroundColor,
        foregroundColor: foregroundColor);
  } catch (e) {
    return Text("Erro ao gerar QR Code: ${e.toString()}");
  }
}

// // Retorna o conteúdo a ser codificado no QR Code.
// String getContents() {
//   return data;
// }

// // Retorna uma versão do conteúdo otimizada para exibição.
// String getDisplayContents() {
//   return data.trim();
// }

// // Retorna o título baseado no tipo de conteúdo.
// String getTitle() {
//   return type;
// }

// // Codifica o conteúdo em uma string adequada para o QR Code.
// Future<String> encodeContents() async {
//   // Implementação específica para codificar o conteúdo.
//   return data; // Exemplo simplificado.
// }

// // Codifica o conteúdo específico do QR Code.
// Future<Widget> encodeQRCodeContents() async {
//   return getQrCode();
// }

// // Gera o QR Code como um widget.

// // Codifica o conteúdo como um bitmap (pode ser útil para operações de baixo nível).
// // Future<Image> encodeAsBitmap() async {
// //   // Implementação para codificar como bitmap.
// //   return Image(image); // Exemplo simplificado.
// // }

// // Adivinha a codificação apropriada para o conteúdo.
// String guessAppropriateEncoding(String content) {
//   // Implementação para adivinhar a codificação.
//   return "UTF-8"; // Exemplo simplificado.
// }

// // Remove espaços em branco do início e do fim do conteúdo.
// String trim(String content) {
//   return content.trim();
// }

// // Escapa caracteres especiais para o formato MECARD.
// String escapeMECARD(String content) {
//   // Implementação para escapar caracteres.
//   return content.replaceAll(':', '\\:'); // Exemplo simplificado.
// }

/// menu

Future scheduleVisitOptAction(BuildContext context) async {
  await showAdaptiveDialog(
    context: context,
    builder: (context) {
      return Padding(
        padding: MediaQuery.viewInsetsOf(context),
        child: OptionSelectionModalWidget(
          routesListStr: <String>[
            'scheduleCompleteVisitPage',
            'scheduleProvisionalVisitPage',
            'fastPassPage',
          ],
          iconsListIcon: <IconData>[
            Icons.date_range_rounded,
            Icons.date_range_rounded,
            Icons.date_range_rounded,
          ],
          nameListStr: <String>[
            FFLocalizations.of(context).getVariableText(
              ptText: 'Visita\nCompleta',
              enText: 'Complete\nSchedule',
            ),
            FFLocalizations.of(context).getVariableText(
              ptText: 'Visita\nProvisória',
              enText: 'Provisional\nSchedule',
            ),
            FFLocalizations.of(context).getVariableText(
              ptText: 'Visita\nRápida',
              enText: 'Fast\nSchedule',
            ),
          ],
        ),
      );
    },
  );
}

Future registerVisitorOptAction(BuildContext context) async {
  context.pushNamed(
    'registerVisitorPage',
    extra: <String, dynamic>{
      kTransitionInfoKey: const TransitionInfo(
        hasTransition: true,
        transitionType: PageTransitionType.scale,
        alignment: Alignment.bottomCenter,
      ),
    },
  );
}

Future peopleOnThePropertyAction(BuildContext context) async {
  context.pushNamed(
    'peopleOnThePropertyPage',
    extra: <String, dynamic>{
      kTransitionInfoKey: const TransitionInfo(
        hasTransition: true,
        transitionType: PageTransitionType.fade,
      ),
    },
  );
}

Future preferencesSettings(BuildContext context) async {
  context.pushNamed(
    'preferencesSettings',
    extra: <String, dynamic>{
      kTransitionInfoKey: const TransitionInfo(
        hasTransition: true,
        transitionType: PageTransitionType.scale,
        alignment: Alignment.bottomCenter,
      ),
    },
  );
}

Future liberationHistoryOptAction(BuildContext context) async {
  await showAdaptiveDialog(
    // isScrollControlled: true,
    // backgroundColor: Colors.transparent,
    // enableDrag: false,
    context: context,
    builder: (context) {
      return Padding(
        padding: MediaQuery.viewInsetsOf(context),
        child: OptionSelectionModalWidget(
          routesListStr: <String>[
            'liberationHistory',
            'acessHistoryPage',
            'scheduleCompleteVisitPage',
            // 'messageHistoryPage',
          ],
          iconsListIcon: <IconData>[
            Icons.history_rounded,
            Icons.history_rounded,
            Icons.history_rounded,
            // Icons.history_rounded,
          ],
          nameListStr: <String>[
            FFLocalizations.of(context).getVariableText(
              ptText: 'Histórico\nde Liberação',
              enText: 'Liberation\nHistory',
            ),
            FFLocalizations.of(context).getVariableText(
              ptText: 'Histórico\nde Acesso',
              enText: 'Access\nHistory',
            ),
            FFLocalizations.of(context).getVariableText(
              ptText: 'Histórico\nde Visita',
              enText: 'Visit\nHistory',
            ),
            // FFLocalizations.of(context).getVariableText(
            //   ptText: 'Histórico\nde Mensagens',
            //   enText: 'Message\nHistory',
            // ),
          ],
        ),
      );
    },
  );
}

Future accessQRCodeOptAction(BuildContext context) async {
  context.pushNamed(
    'qrCodePage',
    extra: <String, dynamic>{
      kTransitionInfoKey: const TransitionInfo(
        hasTransition: true,
        transitionType: PageTransitionType.scale,
        alignment: Alignment.bottomCenter,
      ),
    },
  );
}
