"""
==================================================
Smart Attendance AI
Detector Service
==================================================
Converts raw InsightFace detections into
FaceResult objects after validation.
==================================================
"""

from typing import List

from config.settings import settings

from core.face_result import FaceResult
from core.image_data import ImageData

from services.inference_service import InferenceService

from utils.exceptions import (
    NoFaceDetectedException,
)


class DetectorService:

    @staticmethod
    def detect(
        image_data: ImageData
    ) -> List[FaceResult]:
        """
        Detect faces in an image and return
        validated FaceResult objects.
        """

        # ------------------------------------------
        # Run AI Inference
        # ------------------------------------------

        raw_faces = InferenceService.infer(
            image_data
        )

        if not raw_faces:
            raise NoFaceDetectedException()

        results = []

        # ------------------------------------------
        # Process Each Face
        # ------------------------------------------

        for face in raw_faces:

            confidence = float(
                face.det_score
            )

            # Minimum confidence
            if (
                confidence <
                settings.MIN_FACE_CONFIDENCE
            ):
                continue

            bbox = [
                int(value)
                for value in face.bbox
            ]

            width = bbox[2] - bbox[0]
            height = bbox[3] - bbox[1]

            # Ignore very small faces
            if (
                width < settings.MIN_FACE_WIDTH
                or
                height < settings.MIN_FACE_HEIGHT
            ):
                continue

            landmarks = []

            if hasattr(face, "kps") and face.kps is not None:

                landmarks = [

                    [
                        float(point[0]),
                        float(point[1])
                    ]

                    for point in face.kps

                ]

            results.append(

                FaceResult(

                    bbox=bbox,

                    confidence=confidence,

                    face_width=width,

                    face_height=height,

                    landmarks=landmarks

                )

            )

        # ------------------------------------------
        # Final Validation
        # ------------------------------------------

        if not results:
            raise NoFaceDetectedException()

        if len(results) > settings.MAX_FACES_PER_IMAGE:

            results = results[
                :settings.MAX_FACES_PER_IMAGE
            ]

        return results