package com.dspread.pos.faceID;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Rect;

import com.google.mlkit.vision.common.InputImage;
import com.google.mlkit.vision.face.Face;
import com.google.mlkit.vision.face.FaceDetection;
import com.google.mlkit.vision.face.FaceDetector;
import com.google.mlkit.vision.face.FaceDetectorOptions;
import java.util.List;

public class RealFaceDetector {

    private FaceDetector faceDetector;
    private FaceDetectionCallback callback;
    private boolean isDetecting = false;

    public interface FaceDetectionCallback {
        void onFaceDetected();
        void onFaceDetectionError(String error);
        void onNoFaceDetected();
    }

    public RealFaceDetector(Context context, FaceDetectionCallback callback) {
        this.callback = callback;
        initializeFaceDetector();
    }

    private void initializeFaceDetector() {
        // High-accuracy landmark detection and face classification
        FaceDetectorOptions options = new FaceDetectorOptions.Builder()
                .setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_ACCURATE)
                .setContourMode(FaceDetectorOptions.CONTOUR_MODE_ALL)
                .setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_ALL)
                .setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL)
                .setMinFaceSize(0.15f) // Minimum face size (15% of image width)
                .enableTracking() // Enable face tracking for better performance
                .build();
////        Use a different face detection approach (offline-only)
////        the bundled version:
//        .setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_FAST)
//                .setContourMode(FaceDetectorOptions.CONTOUR_MODE_NONE)
//                .setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_NONE)
//                .setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_NONE)
//                .build();

        faceDetector = FaceDetection.getClient(options);
    }

    public void detectFaces(Bitmap bitmap) {
        if (isDetecting) return;

        isDetecting = true;
        InputImage image = InputImage.fromBitmap(bitmap, 0); // 0 rotation

        faceDetector.process(image)
                .addOnSuccessListener(faces -> {
                    isDetecting = false;
                    handleDetectionResult(faces);
                })
                .addOnFailureListener(e -> {
                    isDetecting = false;
                    if (callback != null) {
                        callback.onFaceDetectionError("Face detection failed: " + e.getMessage());
                    }
                });
    }

    private void handleDetectionResult(List<Face> faces) {
        if (faces == null || faces.isEmpty()) {
            if (callback != null) {
                callback.onNoFaceDetected();
            }
            return;
        }

        // Check if we have at least one good quality face
        for (Face face : faces) {
            if (isGoodQualityFace(face)) {
                if (callback != null) {
                    callback.onFaceDetected();
                }
                return;
            }
        }

        // If we reach here, faces were detected but not good quality
        if (callback != null) {
            callback.onNoFaceDetected();
        }
    }

    private boolean isGoodQualityFace(Face face) {
        // Check if face has good confidence (not occluded, good lighting)
        // You can adjust these thresholds based on your requirements

        // Check if eyes are open (if classification is available)
        if (face.getLeftEyeOpenProbability() != null &&
                face.getLeftEyeOpenProbability() < 0.3f) {
            return false; // Eye probably closed
        }

        if (face.getRightEyeOpenProbability() != null &&
                face.getRightEyeOpenProbability() < 0.3f) {
            return false; // Eye probably closed
        }

        // Check if smiling (optional, depends on your use case)
        if (face.getSmilingProbability() != null &&
                face.getSmilingProbability() < 0.1f) {
            // Not smiling, but this might not be necessary for payment
        }

        // Check face bounding box size (should be reasonably large)
        Rect bounds = face.getBoundingBox();
        float sizeRatio = (float) bounds.width() * bounds.height() / (1000 * 1000); // Example ratio
        if (sizeRatio < 0.1f) {
            return false; // Face too small
        }

        return true; // Good quality face
    }

    public void stop() {
        if (faceDetector != null) {
            faceDetector.close();
        }
        isDetecting = false;
    }
}