import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:image_picker/image_picker.dart';
import 'package:http/http.dart' as http;
import 'package:siro_driver/constant/api_key.dart';
import 'package:siro_driver/constant/colors.dart';
import 'package:siro_driver/constant/info.dart';
import 'package:siro_driver/constant/style.dart';
import 'package:siro_driver/constant/table_names.dart';
import 'package:siro_driver/main.dart';
import 'package:siro_driver/print.dart';
import 'package:siro_driver/views/widgets/elevated_btn.dart';

import '../../constant/box_name.dart';
import '../../constant/links.dart';
import '../auth/captin/register_captin_controller.dart';
import 'launch.dart';

//
// class TextExtractionController extends GetxController {
//   String extractedText = '';
//   bool isloading = false;
//   File? _scannedImage;
// // Convert the extracted text to JSON
// // Convert the extracted text to JSON
//   String getTextAsJSON(String text) {
//     final lines = text.split('\n');
//     final jsonList = lines.map((line) {
//       return {
//         'line_text': line,
//         'num_words': line.trim().split(' ').length,
//       };
//     }).toList();
//
//     final json = {
//       'lines': jsonList,
//       'num_lines': lines.length,
//     };
//
//     return jsonEncode(json);
//   }
//
// // Convert the extracted text to blocks by line
//   List<String> getTextBlocks(String text) {
//     return text.split('\n');
//   }
//
// //   Future<void> pickAndExtractText() async {
// //     final pickedImage = await ImagePicker().pickImage(
// //       source: ImageSource.camera,
// //       preferredCameraDevice: CameraDevice.rear,
// //       maxHeight: Get.height * .3,
// //       maxWidth: Get.width * .8,
// //       imageQuality: 99,
// //     );
// //     if (pickedImage != null) {
// //       isloading = true;
// //       update();
// //       final imagePath = pickedImage.path;
// //       final languages = [
// //         'eng',
// //         'ara'
// //       ]; // Specify the languages you want to use for text extraction
//
// //       try {
// //         final text = await FlutterTesseractOcr.extractText(imagePath,
// //             language:
// //                 languages.join('+'), // Combine multiple languages with '+'
// //             args: {
// //               "psm": "4",
// //               "preserve_interword_spaces": "1",
// //               // "rectangle": const Rect.fromLTWH(100, 100, 200, 200),
// //             } // Additional options if needed
// //             );
// //         isloading = false;
// //         final jsonText = getTextAsJSON(text);
// //         final textBlocks = getTextBlocks(text);
// //         update();
// //         extractedText =
// //             textBlocks.toString(); // Convert the extracted text to JSON.
//
// // // Print the JSON to the console.
// //         update();
// //       } catch (e) {
// //         extractedText = '';
// //       }
// //     }
// //   }
// }

// class TextMLGoogleRecognizerController extends GetxController {
//   @override
//   void onInit() {
//     scanText();
//     super.onInit();
//   }
//
//   // The ImagePicker instance
//   final ImagePicker _imagePicker = ImagePicker();
//
//   // The GoogleMlKit TextRecognizer instance
//   final TextRecognizer _textRecognizer = TextRecognizer();
//
//   // The scanned text
//   String? scannedText;
//   String? jsonOutput;
//   final List<Map<String, dynamic>> lines = [];
//
//   Map decode = {};
//
//   Future<void> scanText() async {
//     // Pick an image from the camera or gallery
//     final XFile? image =
//         await _imagePicker.pickImage(source: ImageSource.gallery);
//
//     // If no image was picked, return
//     if (image == null) {
//       return;
//     }
//
//     // Convert the XFile object to an InputImage object
//     final InputImage inputImage = InputImage.fromFile(File(image.path));
//
//     // Recognize the text in the image
//     final RecognizedText recognizedText =
//         await _textRecognizer.processImage(inputImage);
//     scannedText = recognizedText.text;
//     Map extractedData = {};
//     // Extract the scanned text line by line
//     for (var i = 0; i < recognizedText.blocks.length; i++) {
//       final block = recognizedText.blocks[i];
//       for (final line in block.lines) {
//         final lineText = line.text;
//
//         if (lineText.contains('DL')) {
//           final dlNumber = lineText.split('DL')[1].trim();
//           extractedData['dl_number'] = dlNumber;
//         }
//         if (lineText.contains('USA')) {
//           final usa = lineText.split('USA')[1].trim();
//           extractedData['USA'] = usa;
//         }
//         if (lineText.contains('DRIVER LICENSE')) {
//           final driverl = lineText;
//           extractedData['DRIVER_LICENSE'] = driverl;
//         }
//
//         if (lineText.contains('EXP')) {
//           final expiryDate = lineText.split('EXP')[1].trim();
//           extractedData['expiry_date'] = expiryDate;
//         }
//
//         if (lineText.contains('DOB')) {
//           final dob = lineText.split('DOB')[1].trim();
//           extractedData['dob'] = dob;
//         }
//
//         if (lineText.contains("LN")) {
//           if ((lineText.indexOf("LN") == 0)) {
//             final lastName = lineText.split('LN')[1].trim();
//             extractedData['lastName'] = lastName;
//           }
//         }
//         if (lineText.contains("FN")) {
//           final firstName = lineText.split('FN')[1].trim();
//           extractedData['firstName'] = firstName;
//         }
//         if (lineText.contains("RSTR")) {
//           final rstr = lineText.split('RSTR')[1].trim();
//           extractedData['rstr'] = rstr;
//         }
//         if (lineText.contains("CLASS")) {
//           final class1 = lineText.split('CLASS')[1].trim();
//           extractedData['class'] = class1;
//         }
//         if (lineText.contains("END")) {
//           final end = lineText.split('END')[1].trim();
//           extractedData['end'] = end;
//         }
//         if (lineText.contains("DD")) {
//           final dd = lineText.split('DD')[1].trim();
//           extractedData['dd'] = dd;
//         }
//         if (lineText.contains("EYES")) {
//           final eyes = lineText.split('EYES')[1].trim();
//           extractedData['eyes'] = eyes;
//         }
//         if (lineText.contains("SEX")) {
//           final parts = lineText.split("SEX ")[1];
//           extractedData['sex'] = parts[0];
//         }
//         if (lineText.contains("HAIR")) {
//           final hair = lineText.split('HAIR')[1].trim();
//           extractedData['hair'] = hair;
//         }
//
//         if (lineText.contains('STREET') || lineText.contains(',')) {
//           final address = lineText;
//           extractedData['address'] = address;
//         }
//
//         // Repeat this process for other relevant data fields
//       }
//     }
//
//     // Convert the list of lines to a JSON string
//     jsonOutput = jsonEncode(extractedData);
//     decode = jsonDecode(jsonOutput!);
//
//     update();
//   }
// }

class ScanDocumentsByApi extends GetxController {
  bool isLoading = false;
  Map<String, dynamic> responseMap = {};
  final ImagePicker imagePicker = ImagePicker();
  late Uint8List imagePortrait;
  late Uint8List imageSignature;
  late Uint8List imageDocumentFrontSide;
  XFile? image;
  XFile? imagePortraitFile;
  XFile? imageFace;
  late File tempFile;
  late String imagePath;
  DateTime now = DateTime.now();
  late String name;
  late String licenseClass;
  late String documentNo;
  late String address;
  late String stateCode;
  late String height;
  late String sex;
  late String postalCode;
  late String dob;
  late String expireDate;

  // ///////////////////////
  // late CameraController cameraController;
  // late List<CameraDescription> cameras;
  // bool isCameraInitialized = false;
  // // final TextRecognizer _textRecognizer = TextRecognizer();
  // String? scannedText;

  // Future<void> initializeCamera(int cameraID) async {
  //   try {
  //     cameras = await availableCameras();
  //     //update();
  //     cameraController = CameraController(
  //       cameras[cameraID],
  //       ResolutionPreset.medium,
  //       enableAudio: false,
  //     );
  //     await cameraController.initialize();
  //     isCameraInitialized = true;
  //     update();
  //   } catch (e) {
  //     if (e is CameraException) {
  //       switch (e.code) {
  //         case 'CameraAccessDenied':
  //           Get.defaultDialog(
  //             title: 'Camera Access Denied.'.tr,
  //             middleText: '',
  //             confirm:
  //                 MyElevatedButton(title: 'Open Settings', onPressed: () {}),
  //           );
  //           break;
  //         default:
  //           // Handle other errors here.
  //           break;
  //       }
  //     }
  //   }
  // }

  ///

  Future<void> scanDocumentsByApi() async {
    // String? visionApi = await storage.read(key: BoxName.visionApi);
    // String? visionApi = AK.visionApi;
    // Pick an image from the camera or gallery
    image = await imagePicker.pickImage(source: ImageSource.camera); //

    // If no image was picked, return
    if (image == null) {
      return;
    }

    isLoading = true;
    update();
    var headers = {'X-BLOBR-KEY': AK.visionApi};
    var request = http.MultipartRequest('POST',
        Uri.parse('https://api.faceonlive.com/j2y3q25y1b6maif1/api/iddoc'));
    request.files.add(await http.MultipartFile.fromPath('image', image!.path));
    request.headers.addAll(headers);

    http.StreamedResponse response = await request.send();

    if (response.statusCode == 200) {
      String responseString = await response.stream.bytesToString();
      responseMap = jsonDecode(responseString);
      var ocrData = responseMap['data']['ocr'];
      name = ocrData['name'].toString();
      licenseClass = ocrData['dlClass'].toString();
      documentNo = ocrData['documentNumber'].toString();
      address = ocrData['address'].toString();
      height = ocrData['height'].toString();
      postalCode = ocrData['addressPostalCode'].toString();
      sex = ocrData['sex'].toString();
      stateCode = ocrData['addressJurisdictionCode'].toString();
      expireDate = ocrData['dateOfExpiry'].toString();
      dob = ocrData['dateOfBirth'].toString();
      if (responseMap['data'] != null &&
          responseMap['data']['image'] != null &&
          responseMap['data']['image']['portrait'] != null) {
        imagePortrait = base64Decode(responseMap['data']['image']['portrait']);
        String tempPath = Directory.systemTemp.path;
        tempFile = File('$tempPath/image.jpg');
        await tempFile.writeAsBytes(imagePortrait);

        imagePath = tempFile.path;
        // imagePortraitFile=File(imagePath) ;
        update();
      } else {
        // Handle error or provide a default value
      }

      if (responseMap['data']['image']['signature'] != null) {
        imageSignature =
            base64Decode(responseMap['data']['image']['signature']);
      } else {
        imageSignature = imagePortrait;
        // Handle error or provide a default value
      }

      if (responseMap['data'] != null &&
          responseMap['data']['image'] != null &&
          responseMap['data']['image']['documentFrontSide'] != null) {
        imageDocumentFrontSide =
            base64Decode(responseMap['data']['image']['documentFrontSide']);
      } else {
        // Handle error or provide a default value
      }

      isLoading = false;
      update();
    } else {}
  }

  late int times;
  Future checkMatchFaceApi() async {
    sql.getAllData(TableName.faceDetectTimes).then((value) {
      if (value.isEmpty || value == null) {
        sql.insertData({'faceDetectTimes': 1}, TableName.faceDetectTimes);
        sql.getAllData(TableName.faceDetectTimes).then((value) {
          times = value[0]['faceDetectTimes'];
          update();
        });
      } else {
        if (times < 4) {
          times++;
          matchFaceApi();
          sql.updateData(
              {'faceDetectTimes': times}, TableName.faceDetectTimes, 1);
        } else {
          Get.defaultDialog(
              barrierDismissible: false,
              title: 'You have finished all times '.tr,
              titleStyle: AppStyle.title,
              middleText: 'if you want help you can email us here'.tr,
              middleTextStyle: AppStyle.title,
              cancel: MyElevatedButton(
                title: 'Thanks'.tr,
                kolor: AppColor.greenColor,
                onPressed: () => Get.back(),
              ),
              confirm: MyElevatedButton(
                title: 'Email Us'.tr,
                kolor: AppColor.yellowColor, //
                onPressed: () {
                  launchCommunication('email', 'support@mobile-app.store',
                      '${'Hi'.tr} ${AppInformation.appName}\n${'I cant register in your app in face detection '.tr}');
                  Get.back();
                },
              ));
        }
      }
    });
  }

  Map res = {};
  Future matchFaceApi() async {
    // String? visionApi = await storage.read(key: BoxName.visionApi);
    imageFace = await imagePicker.pickImage(
      source: ImageSource.camera,
      preferredCameraDevice: CameraDevice.front,
    );

    // If no image was picked, return
    if (image == null) {
      return;
    }
    final imageFile = File(imageFace!.path);
    // Uint8List imageBytes = await imageFile.readAsBytes();
    var headers = {'X-BLOBR-KEY': AK.visionApi};
    var request = http.MultipartRequest(
        'POST',
        Uri.parse(
            'https://api.faceonlive.com/sntzbspfsdupgid1/api/face_compare'));
    request.files
        .add(await http.MultipartFile.fromPath('image1', imageFile.path));
    request.files.add(await http.MultipartFile.fromPath('image2', imagePath));
    request.headers.addAll(headers);

    http.StreamedResponse response = await request.send();

    if (response.statusCode == 200) {
      res = jsonDecode(await response.stream.bytesToString());

      update();
      res['data']['result'].toString().contains('No face detected in image')
          ? Get.defaultDialog(
              barrierDismissible: false,
              title: 'No face detected'.tr,
              middleText: ''.tr,
              titleStyle: AppStyle.title,
              confirm: MyElevatedButton(
                kolor: AppColor.yellowColor,
                title: 'Back'.tr,
                onPressed: () {
                  Get.back();
                },
              )) //
          : Get.defaultDialog(
              // barrierDismissible: false,
              title: 'Image detecting result is '.tr,
              titleStyle: AppStyle.title,
              content: Column(
                children: [
                  Text(
                    res['data']['result'].toString(),
                    style: res['data']['result'].toString() == 'Different'
                        ? AppStyle.title.copyWith(color: AppColor.redColor)
                        : AppStyle.title.copyWith(color: AppColor.greenColor),
                  ),
                  res['data']['result'].toString() == 'Different'
                      ? Text(
                          '${'Be sure for take accurate images please\nYou have'.tr} $times ${'from 3 times Take Attention'.tr}',
                          style: AppStyle.title,
                        )
                      : Text(
                          'image verified'.tr,
                          style: AppStyle.title,
                        )
                ],
              ),
              confirm: res['data']['result'].toString() == 'Different'
                  ? MyElevatedButton(
                      title: 'Back'.tr,
                      onPressed: () => Get.back(),
                      kolor: AppColor.redColor,
                    )
                  : MyElevatedButton(
                      title: 'Next'.tr,
                      onPressed: () async {
                        RegisterCaptainController registerCaptainController =
                            Get.put(RegisterCaptainController());

                        await registerCaptainController.register();
                        await registerCaptainController.addLisence();
                        await uploadImagePortrate();
                        // Get.to(() => CarLicensePage());
                      },
                      // {
                      //   await uploadImage(
                      //       tempFile, AppLink.uploadImagePortrate);
                      //   Get.to(() => CarLicensePage());
                      // },
                      kolor: AppColor.greenColor,
                    ));
    } else {}
  }

  Future<String> uploadImagePortrate() async {
    isLoading = true;
    update();

    final String token =
        box.read(BoxName.jwt)?.toString().split(AppInformation.addd)[0] ?? '';
    final String fingerPrint =
        box.read(BoxName.deviceFingerprint)?.toString() ?? '';
    final String driverID = box.read(BoxName.driverID).toString();
    final String link = AppLink.uploadImagePortrate;

    int maxRetries = 3;
    int attempt = 0;
    String responseString = '';

    while (attempt < maxRetries) {
      attempt++;
      final client = http.Client();
      try {
        Log.print(
            '[UPLOAD_LOGGER] 🚀 [uploadImagePortrate] Attempt $attempt/$maxRetries started. Link: $link, Image Size: ${imagePortrait.length} bytes');

        var request = http.MultipartRequest('POST', Uri.parse(link));
        request.files.add(
          http.MultipartFile.fromBytes('image', imagePortrait,
              filename: '$driverID.jpg'),
        );

        request.headers.addAll({
          'Authorization': 'Bearer $token',
          'X-Device-FP': fingerPrint,
        });
        request.fields['driverID'] = driverID;

        final startTime = DateTime.now();
        var streamedResponse =
            await client.send(request).timeout(const Duration(seconds: 120));
        var res = await http.Response.fromStream(streamedResponse);
        final duration = DateTime.now().difference(startTime);

        Log.print(
            '[UPLOAD_LOGGER] 📥 [uploadImagePortrate] Attempt $attempt response received in ${duration.inSeconds}s. Status Code: ${res.statusCode}');
        Log.print(
            '[UPLOAD_LOGGER] 📥 [uploadImagePortrate] Response Body: ${res.body}');

        if (res.statusCode == 200) {
          responseString = res.body;
          break; // Success
        } else {
          throw Exception(
              'Failed to upload portrait: ${res.statusCode} - ${res.body}');
        }
      } catch (e, st) {
        Log.print(
            '[UPLOAD_LOGGER] ⚠️ [uploadImagePortrate] Attempt $attempt failed. Error: $e',
            stackTrace: st);
        if (attempt >= maxRetries) {
          isLoading = false;
          update();
          rethrow;
        }
        final waitSeconds = attempt * 2;
        Log.print(
            '[UPLOAD_LOGGER] ⏳ Waiting $waitSeconds seconds before retrying...');
        await Future.delayed(Duration(seconds: waitSeconds));
      } finally {
        client.close();
      }
    }

    isLoading = false;
    update();

    return responseString;
  }

  @override
  void onInit() {
    // scanDocumentsByApi();
    // initializeCamera(0);
    sql.getAllData(TableName.faceDetectTimes).then((value) {
      if (value.isEmpty) {
        times = 0;
        update();
        // sql.insertData({'faceDetectTimes': 1}, TableName.faceDetectTimes);
      } else {
        times = value[0]['faceDetectTimes'];
      }
    });
    super.onInit();
  }
}

// class PassportDataExtractor extends GetxController {
//   @override
//   void onInit() {
//     extractPassportData();
//     super.onInit();
//   }
//
//   final ImagePicker _imagePicker = ImagePicker();
//   late final XFile? image;
//   final TextRecognizer _textRecognizer = TextRecognizer();
//
//   Future<Map<String, dynamic>> extractPassportData() async {
//     image = await _imagePicker.pickImage(source: ImageSource.gallery);
//     update();
//     if (image == null) {
//       throw Exception('No image picked');
//     }
//
//     final InputImage inputImage = InputImage.fromFile(File(image!.path));
//     final RecognizedText recognisedText =
//         await _textRecognizer.processImage(inputImage);
//
//     final Map<String, dynamic> extractedData = {};
//     final List<Map<String, dynamic>> extractedTextWithCoordinates = [];
//
//     for (TextBlock block in recognisedText.blocks) {
//       for (TextLine line in block.lines) {
//         final String lineText = line.text;
//         final Rect lineBoundingBox = line.boundingBox!;
//
//         extractedTextWithCoordinates.add({
//           'text': lineText,
//           'boundingBox': {
//             'left': lineBoundingBox.left,
//             'top': lineBoundingBox.top,
//             'width': lineBoundingBox.width,
//             'height': lineBoundingBox.height,
//           },
//         });
//
//         // if (lineText.contains('Passport Number')) {
//         //   final String passportNumber =
//         //       lineText.split('Passport Number')[1].trim();
//         //   extractedData['passportNumber'] = passportNumber;
//         // }
//         // if (lineText.contains('Given Names')) {
//         //   final String givenNames = lineText.split('Given Names')[1].trim();
//         //   extractedData['givenNames'] = givenNames;
//         // }
//         // if (lineText.contains('Surname')) {
//         //   final String surname = lineText.split('Surname')[1].trim();
//         //   extractedData['surname'] = surname;
//         // }
//         // if (lineText.contains('Nationality')) {
//         //   final String nationality = lineText.split('Nationality')[1].trim();
//         //   extractedData['nationality'] = nationality;
//         // }
//         // if (lineText.contains('Date of Birth')) {
//         //   final String dob = lineText.split('Date of Birth')[1].trim();
//         //   extractedData['dateOfBirth'] = dob;
//         // }
//         // Add more field extraction conditions as needed
//       }
//     }
//
//     extractedData['extractedTextWithCoordinates'] =
//         extractedTextWithCoordinates;
//     return extractedData;
//   }
// }
//
// class PassportDataController extends GetxController {
//   PassportDataExtractor passportDataExtractor = PassportDataExtractor();
//   List<Map<String, dynamic>> extractedTextWithCoordinates = [];
//
//   Future<void> extractDataAndDrawBoundingBoxes() async {
//     try {
//       Map<String, dynamic> extractedData =
//           await passportDataExtractor.extractPassportData();
//       extractedTextWithCoordinates =
//           extractedData['extractedTextWithCoordinates'];
//       update(); // Notify GetX that the state has changed
//     } catch (e) {
//     }
//   }
// }
//
// class BoundingBoxPainter extends CustomPainter {
//   final List<Map<String, dynamic>> boundingBoxes;
//
//   BoundingBoxPainter(this.boundingBoxes);
//
//   @override
//   void paint(Canvas canvas, Size size) {
//     final Paint paint = Paint()
//       ..color = Colors.red
//       ..style = PaintingStyle.stroke
//       ..strokeWidth = 2.0;
//
//     for (Map<String, dynamic> boundingBox in boundingBoxes) {
//       double left = boundingBox['left'];
//       double top = boundingBox['top'];
//       double width = boundingBox['width'];
//       double height = boundingBox['height'];
//
//       Rect rect = Rect.fromLTWH(left, top, width, height);
//       canvas.drawRect(rect, paint);
//     }
//   }
//
//   @override
//   bool shouldRepaint(covariant CustomPainter oldDelegate) {
//     return false;
//   }
// }
