import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/services.dart';
import 'package:tflite_flutter/tflite_flutter.dart';
import 'package:image/image.dart' as img;
import '../models/prediction_result.dart';

class ClassifierService {
  Interpreter? _interpreter;
  List<String>? _labels;

  Future<void> loadModel() async {
    try {
      _interpreter = await Interpreter.fromAsset(
        'assets/model/best_model_epoch15.tflite',
      );
      final labelData = await rootBundle.loadString('assets/model/label.txt');
      _labels = labelData
          .split(RegExp(r'\r?\n'))
          .where((l) => l.trim().isNotEmpty)
          .toList();
      print("✅ Model Load Success");
    } catch (e) {
      print("❌ Model Load Failed: $e");
    }
  }

  /// REPLIKASI TOTAL LOGIKA PYTHON
  img.Image syncPreprocessing(img.Image image) {
    img.Image fixedImage = img.bakeOrientation(image);

    // 2. Hitung Dimensi Target Zoom 80%
    double zoomFactor = 0.8;
    int targetW = (fixedImage.width * zoomFactor).toInt();
    int targetH = (fixedImage.height * zoomFactor).toInt();

    // 3. Tentukan Titik Tengah Absolut
    int centerX = fixedImage.width ~/ 2;
    int centerY = fixedImage.height ~/ 2;

    // 4. Hitung Sisi-Sisi Potongan
    int left = centerX - (targetW ~/ 2);
    int top = centerY - (targetH ~/ 2);

    // 5. Eksekusi Manual Crop
    img.Image cropped = img.copyCrop(
      fixedImage,
      x: left,
      y: top,
      width: targetW,
      height: targetH,
    );

    int side = (cropped.width < cropped.height)
        ? cropped.width
        : cropped.height;
    int startX = (cropped.width - side) ~/ 2;
    int startY = (cropped.height - side) ~/ 2;

    img.Image squareImage = img.copyCrop(
      cropped,
      x: startX,
      y: startY,
      width: side,
      height: side,
    );

    // 7. Final Resize ke 224x224
    return img.copyResize(
      squareImage,
      width: 224,
      height: 224,
      interpolation: img.Interpolation.cubic,
    );
  }

  Future<PredictionResult> classify(File imageFile) async {
    if (_interpreter == null) return _errorResult("Model belum dimuat");

    final bytes = await imageFile.readAsBytes();
    final decodedImage = img.decodeImage(bytes);

    if (decodedImage == null) return _errorResult("Gambar rusak");

    // PROSES: Samakan dengan dataset Python
    img.Image finalImage = syncPreprocessing(decodedImage);

    // Persiapan Tensor Input
    var input = Float32List(1 * 224 * 224 * 3);
    int buffer = 0;
    for (int y = 0; y < 224; y++) {
      for (int x = 0; x < 224; x++) {
        var pixel = finalImage.getPixel(x, y);
        input[buffer++] = pixel.r.toDouble();
        input[buffer++] = pixel.g.toDouble();
        input[buffer++] = pixel.b.toDouble();
      }
    }

    var output = List.filled(1 * 6, 0.0).reshape([1, 6]);
    _interpreter!.run(
      input.buffer.asFloat32List().reshape([1, 224, 224, 3]),
      output,
    );

    return _processResults(output[0]);
  }

  // --- Helper Functions ---

  Future<File> preprocessImageForDisplay(File imageFile) async {
    final bytes = await imageFile.readAsBytes();
    final decodedImage = img.decodeImage(bytes);
    if (decodedImage == null) return imageFile;

    img.Image processed = syncPreprocessing(decodedImage);

    final tempPath =
        "${Directory.systemTemp.path}/view_${DateTime.now().millisecondsSinceEpoch}.jpg";
    File(tempPath).writeAsBytesSync(img.encodeJpg(processed, quality: 95));
    return File(tempPath);
  }

  PredictionResult _errorResult(String msg) => PredictionResult(
    jenisKopi: "Error",
    tingkatRoasting: msg,
    akurasi: 0.0,
    top3Predictions: [],
    isValid: false,
  );

  PredictionResult _processResults(List<dynamic> results) {
    List<Map<String, dynamic>> temp = [];
    for (int i = 0; i < _labels!.length; i++) {
      temp.add({"label": _labels![i], "score": results[i]});
    }
    temp.sort((a, b) => b['score'].compareTo(a['score']));

    if (temp[0]['score'] < 0.5) return _errorResult("Kopi tidak dikenali");

    List<String> split = temp[0]['label'].split(" ");
    return PredictionResult(
      jenisKopi: split[0],
      tingkatRoasting: split.length > 1 ? split.sublist(1).join(" ") : "",
      akurasi: temp[0]['score'] * 100,
      top3Predictions: temp.take(3).toList(),
      isValid: true,
    );
  }
}
// import 'dart:io';
// import 'dart:typed_data';
// import 'package:flutter/services.dart';
// import 'package:tflite_flutter/tflite_flutter.dart';
// import 'package:image/image.dart' as img;
// import '../models/prediction_result.dart';

// class ClassifierService {
//   Interpreter? _interpreter;
//   List<String>? _labels;

//   Future<void> loadModel() async {
//     try {
//       // Pastikan file model di assets sudah sesuai dengan versi terbaru
//       _interpreter = await Interpreter.fromAsset(
//         'assets/model/best_model_epoch15.tflite',
//       );

//       final labelData = await rootBundle.loadString('assets/model/label.txt');
//       // Perbaikan: Gunakan split RegExp untuk menangani \n atau \r\n agar label bersih
//       _labels = labelData
//           .split(RegExp(r'\r?\n'))
//           .where((label) => label.trim().isNotEmpty)
//           .toList();

//       print("✅ Model dan ${_labels?.length} Label berhasil dimuat!");
//     } catch (e) {
//       print("❌ Gagal memuat model: $e");
//     }
//   }

//   bool _checkImageAuthenticity(img.Image image) {
//     int rSum = 0, gSum = 0, bSum = 0;
//     int sampleStep = 10;
//     int count = 0;

//     int startX = (image.width * 0.25).toInt();
//     int startY = (image.height * 0.25).toInt();
//     int endX = (image.width * 0.75).toInt();
//     int endY = (image.height * 0.75).toInt();

//     for (int y = startY; y < endY; y += sampleStep) {
//       for (int x = startX; x < endX; x += sampleStep) {
//         var pixel = image.getPixel(x, y);
//         rSum += pixel.r.toInt();
//         gSum += pixel.g.toInt();
//         bSum += pixel.b.toInt();
//         count++;
//       }
//     }

//     if (count == 0) return false;

//     double avgR = rSum / count;
//     double avgG = gSum / count;
//     double avgB = bSum / count;
//     double brightness = (0.299 * avgR + 0.587 * avgG + 0.114 * avgB);

//     if (brightness < 20 || brightness > 235) return false;
//     if (avgG > avgR * 1.3 || avgB > avgR * 1.3) return false;
//     return true;
//   }

//   Future<PredictionResult> classify(File imageFile) async {
//     if (_interpreter == null) {
//       return PredictionResult(
//         jenisKopi: "Error",
//         tingkatRoasting: "Model belum dimuat",
//         akurasi: 0.0,
//         top3Predictions: [],
//         isValid: false,
//       );
//     }

//     final bytes = await imageFile.readAsBytes();
//     final decodedImage = img.decodeImage(bytes);

//     if (decodedImage == null || !_checkImageAuthenticity(decodedImage)) {
//       return PredictionResult(
//         jenisKopi: "Invalid",
//         tingkatRoasting: "",
//         akurasi: 0.0,
//         top3Predictions: [],
//         isValid: false,
//       );
//     }

//     // --- SINKRONISASI PREPROCESSING ---
//     // Menggunakan copyResizeCropSquare agar identik dengan ImageOps.fit (Center Crop)
//     // Interpolation.cubic memberikan kualitas tajam mirip LANCZOS di PIL
//     var resized = img.copyResizeCropSquare(
//       decodedImage,
//       size: 224,
//       interpolation: img.Interpolation.cubic,
//     );

//     // --- INPUT TENSOR ---
//     // Menggunakan Float32List untuk menjamin presisi data saat masuk ke TFLite
//     var input = Float32List(1 * 224 * 224 * 3);
//     var buffer = 0;

//     for (var y = 0; y < 224; y++) {
//       for (var x = 0; x < 224; x++) {
//         var pixel = resized.getPixel(x, y);

//         // Nilai mentah 0-255 sesuai setingan Python (tanpa normalisasi manual)
//         input[buffer++] = pixel.r.toDouble();
//         input[buffer++] = pixel.g.toDouble();
//         input[buffer++] = pixel.b.toDouble();
//       }
//     }

//     // Output buffer sesuai jumlah kelas (6)
//     var output = List.filled(1 * 6, 0.0).reshape([1, 6]);

//     // Jalankan Inferensi
//     _interpreter!.run(
//       input.buffer.asFloat32List().reshape([1, 224, 224, 3]),
//       output,
//     );

//     List<double> results = List<double>.from(output[0]);

//     // Mapping & Ranking
//     List<Map<String, dynamic>> temp = [];
//     for (int i = 0; i < _labels!.length; i++) {
//       temp.add({"label": _labels![i].trim(), "score": results[i]});
//     }

//     temp.sort((a, b) => b['score'].compareTo(a['score']));

//     double topScore = temp[0]['score'];

//     // Threshold keyakinan model (Sesuai Python CONFIDENCE_THRESHOLD = 0.5)
//     if (topScore < 0.50) {
//       return PredictionResult(
//         jenisKopi: "Unknown",
//         tingkatRoasting: "",
//         akurasi: topScore * 100,
//         top3Predictions: temp.take(3).toList(),
//         isValid: false,
//       );
//     }

//     // Memisahkan Jenis Kopi dan Roasting (Contoh: "Arabica Dark")
//     List<String> split = temp[0]['label'].split(" ");
//     return PredictionResult(
//       jenisKopi: split[0],
//       tingkatRoasting: split.length > 1 ? split.sublist(1).join(" ") : "",
//       akurasi: topScore * 100,
//       top3Predictions: temp.take(3).toList(),
//       isValid: true,
//     );
//   }
// }
