import 'dart:convert';
import 'dart:io';
import 'package:sefer_driver/constant/api_key.dart';
import 'package:sefer_driver/views/widgets/error_snakbar.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path/path.dart';
import 'package:image/image.dart' as img;

import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:path_provider/path_provider.dart' as path_provider;

import '../../constant/box_name.dart';
import '../../constant/colors.dart';
import '../../constant/info.dart';
import '../../main.dart';
import '../../print.dart';
import 'encrypt_decrypt.dart';

class ImageController extends GetxController {
  File? myImage;
  bool isloading = false;
  CroppedFile? croppedFile;
  final picker = ImagePicker();
  var image;

  Future<img.Image> detectAndCropDocument(File imageFile) async {
    img.Image? image = img.decodeImage(await imageFile.readAsBytes());
    if (image == null) throw Exception('Unable to decode image');

    int left = image.width, top = image.height, right = 0, bottom = 0;

    // Threshold for considering a pixel as part of the document (adjust as needed)
    const int threshold = 240;

    for (int y = 0; y < image.height; y++) {
      for (int x = 0; x < image.width; x++) {
        final pixel = image.getPixel(x, y);
        final luminance = img.getLuminance(pixel);

        if (luminance < threshold) {
          left = x < left ? x : left;
          top = y < top ? y : top;
          right = x > right ? x : right;
          bottom = y > bottom ? y : bottom;
        }
      }
    }

    // Add a small padding
    left = (left - 5).clamp(0, image.width);
    top = (top - 5).clamp(0, image.height);
    right = (right + 5).clamp(0, image.width);
    bottom = (bottom + 5).clamp(0, image.height);

    return img.copyCrop(image,
        x: left, y: top, width: right - left, height: bottom - top);
  }

  Future<File> rotateImageIfNeeded(File imageFile) async {
    img.Image croppedDoc = await detectAndCropDocument(imageFile);

    // Check if the document is in portrait orientation
    bool isPortrait = croppedDoc.height > croppedDoc.width;

    img.Image processedImage;
    if (isPortrait) {
      // Rotate the image by 90 degrees clockwise
      processedImage = img.copyRotate(croppedDoc, angle: 90);
    } else {
      processedImage = croppedDoc;
    }

    // Get temporary directory
    final tempDir = await path_provider.getTemporaryDirectory();
    final tempPath = tempDir.path;

    // Create the processed image file
    File processedFile = File('$tempPath/processed_image.jpg');
    await processedFile.writeAsBytes(img.encodeJpg(processedImage));

    return processedFile;
  }

  Future<File> rotateImage(File imageFile) async {
    // Read the image file
    img.Image? image = img.decodeImage(await imageFile.readAsBytes());

    if (image == null) return imageFile;

    // Rotate the image by 90 degrees clockwise
    img.Image rotatedImage = img.copyRotate(image, angle: 90);

    // Get temporary directory
    final tempDir = await path_provider.getTemporaryDirectory();
    final tempPath = tempDir.path;

    // Create the rotated image file
    File rotatedFile = File('$tempPath/rotated_image.jpg');
    await rotatedFile.writeAsBytes(img.encodeJpg(rotatedImage));

    return rotatedFile;
  }

  choosImage(String link, String imageType) async {
    try {
      final pickedImage = await picker.pickImage(
        source: ImageSource.camera,
        preferredCameraDevice: CameraDevice.rear,
      );

      if (pickedImage == null) return;

      image = File(pickedImage.path);

      croppedFile = await ImageCropper().cropImage(
        sourcePath: image!.path,
        uiSettings: [
          AndroidUiSettings(
            toolbarTitle: 'Cropper'.tr,
            toolbarColor: AppColor.blueColor,
            toolbarWidgetColor: AppColor.yellowColor,
            initAspectRatio: CropAspectRatioPreset.original,
            lockAspectRatio: false,
          ),
          IOSUiSettings(
            title: 'Cropper'.tr,
          ),
        ],
      );

      if (croppedFile == null) return;

      myImage = File(croppedFile!.path);
      isloading = true;
      update();

      // Rotate the compressed image
      File processedImage = await rotateImageIfNeeded(File(croppedFile!.path));
      File compressedImage = await compressImage(processedImage);

      print('link =$link');
      // Log.print('link: ${link}');
//n8u22456
      await uploadImage(
        compressedImage,
        {
          'driverID':
              box.read(BoxName.driverID) ?? box.read(BoxName.passengerID),
          'imageType': imageType,
        },
        link,
      );
    } catch (e) {
      print('Error in choosImage: $e');
      mySnackeBarError('Image Upload Failed'.tr);
      // Get.snackbar('Image Upload Failed'.tr, e.toString(),
      //     backgroundColor: AppColor.primaryColor);
    } finally {
      isloading = false;
      update();
    }
  }

  choosImageNewCAr(String link, String imageType) async {
    try {
      final pickedImage = await picker.pickImage(
        source: ImageSource.camera,
        preferredCameraDevice: CameraDevice.rear,
      );

      if (pickedImage == null) return;

      image = File(pickedImage.path);

      croppedFile = await ImageCropper().cropImage(
        sourcePath: image!.path,
        uiSettings: [
          AndroidUiSettings(
            toolbarTitle: 'Cropper'.tr,
            toolbarColor: AppColor.blueColor,
            toolbarWidgetColor: AppColor.yellowColor,
            initAspectRatio: CropAspectRatioPreset.original,
            lockAspectRatio: false,
          ),
          IOSUiSettings(
            title: 'Cropper'.tr,
          ),
        ],
      );

      if (croppedFile == null) return;

      myImage = File(croppedFile!.path);
      isloading = true;
      update();

      // Rotate the compressed image
      File processedImage = await rotateImageIfNeeded(File(croppedFile!.path));
      File compressedImage = await compressImage(processedImage);

      print('link =$link');
      // Log.print('link: ${link}');
//n8u22456
      await uploadNewCar(
        compressedImage,
        {
          'driverID': box.read(BoxName.driverID) +
              '_' +
              DateTime.now().toIso8601String(),
          'imageType': imageType,
        },
        link,
      );
    } catch (e) {
      print('Error in choosImage: $e');
      // Get.snackbar('Image Upload Failed'.tr, e.toString(),
      //     backgroundColor: AppColor.primaryColor);
      mySnackeBarError('Image Upload Failed'.tr);
    } finally {
      isloading = false;
      update();
    }
  }

  // choosFaceFromDriverLicense(String link, String imageType) async {
  //   final pickedImage = await picker.pickImage(
  //     source: ImageSource.camera,
  //     preferredCameraDevice: CameraDevice.rear,
  //   );

  //   if (pickedImage == null) return;

  //   image = File(pickedImage.path);

  //   File? processedImage;

  //   // For face images, use face detection and cropping
  //   processedImage = await detectAndCropFace(image!);
  //   if (processedImage == null) {
  //     Get.snackbar('Face Detection Failed', 'No face detected in the image.');
  //     return;
  //   }

  //   isloading = true;
  //   update();

  //   File compressedImage = await compressImage(processedImage);

  //   try {
  //     await uploadImage(
  //       compressedImage,
  //       {
  //         'driverID': box.read(BoxName.driverID).toString(),
  //         'imageType': imageType
  //       },
  //       link,
  //     );
  //   } catch (e) {
  //     Get.snackbar('Image Upload Failed'.tr, e.toString(),
  //         backgroundColor: AppColor.redColor);
  //   } finally {
  //     isloading = false;
  //     update();
  //   }
  // }

  choosFace(String link, String imageType) async {
    final pickedImage = await picker.pickImage(
      source: ImageSource.camera,
      preferredCameraDevice: CameraDevice.front,
    );
    if (pickedImage != null) {
      image = File(pickedImage.path);
      isloading = true;
      update();
// Compress the image
      File compressedImage = await compressImage(File(pickedImage.path));

      // Save the picked image directly
      // File savedImage = File(pickedImage.path);
      print('link =$link');
      try {
        await uploadImage(
          compressedImage,
          {
            'driverID':
                box.read(BoxName.driverID) ?? box.read(BoxName.passengerID),
            'imageType': imageType
          },
          link,
        );
      } catch (e) {
        mySnackeBarError('Image Upload Failed'.tr);
        // Get.snackbar('Image Upload Failed'.tr, e.toString(),
        //     backgroundColor: AppColor.redColor);
      } finally {
        isloading = false;
        update();
      }
    }
  }

  uploadImage(File file, Map data, String link) async {
    var request = http.MultipartRequest(
      'POST',
      Uri.parse(link),
    );
    Log.print('request: ${request}');
    var length = await file.length();
    var stream = http.ByteStream(file.openRead());
    final headers = {
      'Authorization':
          'Bearer ${r(box.read(BoxName.jwt)).split(AppInformation.addd)[0]}',
      'X-HMAC-Auth': '${box.read(BoxName.hmac)}',
    };
    var multipartFile = http.MultipartFile(
      'image',
      stream,
      length,
      filename: basename(file.path),
    );
    request.headers.addAll(headers);
    // Set the file name to the driverID

    request.files.add(
      http.MultipartFile(
        'image',
        stream,
        length,
        filename: '${box.read(BoxName.driverID)}.jpg',
      ),
    );
    data.forEach((key, value) {
      request.fields[key] = value;
    });
    var myrequest = await request.send();
    var res = await http.Response.fromStream(myrequest);
    if (res.statusCode == 200) {
      Log.print('jsonDecode(res.body): ${jsonDecode(res.body)}');
      return jsonDecode(res.body);
    } else {
      throw Exception(
          'Failed to upload image: ${res.statusCode} - ${res.body}');
    }
  }

  uploadNewCar(File file, Map data, String link) async {
    var request = http.MultipartRequest(
      'POST',
      Uri.parse(link),
    );

    var length = await file.length();
    var stream = http.ByteStream(file.openRead());
    var multipartFile = http.MultipartFile(
      'image',
      stream,
      length,
      filename: basename(file.path),
    );
    request.headers.addAll({
      'Authorization':
          'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}',
    });
    // Set the file name to the driverID
    request.files.add(
      http.MultipartFile(
        'image',
        stream,
        length,
        filename: '${box.read(BoxName.driverID)}.jpg',
      ),
    );
    data.forEach((key, value) {
      request.fields[key] = value;
    });
    var myrequest = await request.send();
    var res = await http.Response.fromStream(myrequest);
    if (res.statusCode == 200) {
      Log.print('jsonDecode(res.body): ${jsonDecode(res.body)}');
      return jsonDecode(res.body);
    } else {
      throw Exception(
          'Failed to upload image: ${res.statusCode} - ${res.body}');
    }
  }

  choosImagePicture(String link, String imageType) async {
    final pickedImage = await picker.pickImage(
      source: ImageSource.gallery,
      // preferredCameraDevice: CameraDevice.rear,
      // maxHeight: Get.height * .3,
      // maxWidth: Get.width * .9,
      // imageQuality: 100,
    );
    image = File(pickedImage!.path);

    croppedFile = await ImageCropper().cropImage(
      sourcePath: image!.path,
      uiSettings: [
        AndroidUiSettings(
            toolbarTitle: 'Cropper'.tr,
            toolbarColor: AppColor.blueColor,
            toolbarWidgetColor: AppColor.yellowColor,
            initAspectRatio: CropAspectRatioPreset.original,
            lockAspectRatio: false),
        IOSUiSettings(
          title: 'Cropper'.tr,
        ),
      ],
    );
    myImage = File(pickedImage.path);
    isloading = true;
    update();
// Save the cropped image
    // File savedCroppedImage = File(croppedFile!.path);
    File compressedImage = await compressImage(File(croppedFile!.path));
    print('link =$link');
    try {
      await uploadImage(
        compressedImage,
        {'driverID': (box.read(BoxName.driverID)), 'imageType': imageType},
        link,
      );
    } catch (e) {
      Log.print('e: ${e}');
      mySnackeBarError('Image Upload Failed'.tr);
      // Get.snackbar('Image Upload Failed'.tr, e.toString(),
      //     backgroundColor: AppColor.redColor);
    } finally {
      isloading = false;
      update();
    }
  }

  uploadImagePicture(File file, Map data, String link) async {
    var request = http.MultipartRequest(
      'POST',
      Uri.parse(link), //'https://ride.mobile-app.store/uploadImage1.php'
    );

    var length = await file.length();
    var stream = http.ByteStream(file.openRead());
    var multipartFile = http.MultipartFile(
      'image',
      stream,
      length,
      filename: basename(file.path),
    );
    request.headers.addAll({
      'Authorization':
          'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}',
    });
    // Set the file name to the driverID
    request.files.add(
      http.MultipartFile(
        'image',
        stream,
        length,
        filename: '${(box.read(BoxName.driverID))}.jpg',
      ),
    );
    data.forEach((key, value) {
      request.fields[key] = value;
    });
    var myrequest = await request.send();
    var res = await http.Response.fromStream(myrequest);
    if (res.statusCode == 200) {
      return jsonDecode(res.body);
    } else {
      throw Exception(
          'Failed to upload image: ${res.statusCode} - ${res.body}');
    }
  }
}

Future<File> compressImage(File file) async {
  final dir = await path_provider.getTemporaryDirectory();
  final targetPath = "${dir.absolute.path}/temp.jpg";

  var result = await FlutterImageCompress.compressAndGetFile(
    file.absolute.path,
    targetPath,
    quality: 70,
    minWidth: 1024,
    minHeight: 1024,
  );

  return File(result!.path);
}

// Future<File> detectAndCropFace(File imageFile) async {
//   final inputImage = InputImage.fromFilePath(imageFile.path);
//   final options = FaceDetectorOptions(
//     enableClassification: false,
//     enableLandmarks: false,
//     enableTracking: false,
//     minFaceSize: 0.15,
//     performanceMode: FaceDetectorMode.accurate,
//   );
//   final faceDetector = FaceDetector(options: options);

//   try {
//     final List<Face> faces = await faceDetector.processImage(inputImage);
//     final image = img.decodeImage(await imageFile.readAsBytes());

//     if (image == null) throw Exception('Unable to decode image');

//     int left, top, width, height;

//     if (faces.isNotEmpty) {
//       // Face detected, crop around the face
//       final face = faces[0];
//       double padding = 0.2; // 20% padding
//       int paddingX = (face.boundingBox.width * padding).round();
//       int paddingY = (face.boundingBox.height * padding).round();

//       left = (face.boundingBox.left - paddingX).round();
//       top = (face.boundingBox.top - paddingY).round();
//       width = (face.boundingBox.width + 2 * paddingX).round();
//       height = (face.boundingBox.height + 2 * paddingY).round();
//     } else {
//       // No face detected, crop the center of the image
//       int size = min(image.width, image.height);
//       left = (image.width - size) ~/ 2;
//       top = (image.height - size) ~/ 2;
//       width = size;
//       height = size;
//     }

//     // Ensure dimensions are within image bounds
//     left = left.clamp(0, image.width - 1);
//     top = top.clamp(0, image.height - 1);
//     width = width.clamp(1, image.width - left);
//     height = height.clamp(1, image.height - top);

//     final croppedImage =
//         img.copyCrop(image, x: left, y: top, width: width, height: height);

//     // Save the cropped image
//     final tempDir = await path_provider.getTemporaryDirectory();
//     final tempPath = tempDir.path;
//     final croppedFile = File('$tempPath/cropped_image.jpg');
//     await croppedFile.writeAsBytes(img.encodeJpg(croppedImage, quality: 100));

//     return croppedFile;
//   } finally {
//     faceDetector.close();
//   }
// }
