# coding: utf-8

"""
    Mixpeek API

    This is the Mixpeek API, providing access to various endpoints for data processing and retrieval.

    The version of the OpenAPI document: 1.3.0
    Contact: info@mixpeek.com
    Generated by OpenAPI Generator (https://openapi-generator.tech)

    Do not edit the class manually.
"""  # noqa: E501


from __future__ import annotations
import pprint
import re  # noqa: F401
import json

from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr, field_validator
from typing import Any, ClassVar, Dict, List, Optional, Union
from typing_extensions import Annotated
from typing import Optional, Set
from typing_extensions import Self

class FaceIdentityExtractorParams(BaseModel):
    """
    Parameters for the Face Identity Extractor.  The Face Identity Extractor processes images or video frames to detect, align, and embed faces using production-grade SOTA models (SCRFD + ArcFace).  Core Pipeline: 1. SCRFD Detection → Bounding boxes + 5 landmarks 2. 5-Point Affine Alignment → 112×112 canonical face 3. ArcFace Embedding → 512-d L2-normalized vector 4. Optional Quality Scoring → Filter low-quality faces  Use Cases:     - Face verification (1:1 matching)     - Face identification (1:N search)     - Face clustering (group photos by person)     - Duplicate face detection
    """ # noqa: E501
    extractor_type: Optional[StrictStr] = Field(default='face_identity_extractor', description="Discriminator field for parameter type identification. Must be 'face_identity_extractor'.")
    detection_model: Optional[StrictStr] = Field(default='scrfd_2.5g', description="SCRFD model for face detection. 'scrfd_500m': Fastest (2-3ms). 'scrfd_2.5g': Balanced (5-7ms), recommended. 'scrfd_10g': Highest accuracy (10-15ms).")
    min_face_size: Optional[Annotated[int, Field(le=200, strict=True, ge=10)]] = Field(default=20, description="Minimum face size in pixels to detect. 20px: Balanced. 40px: Higher quality. 10px: Maximum recall.")
    detection_threshold: Optional[Union[Annotated[float, Field(le=1.0, strict=True, ge=0.0)], Annotated[int, Field(le=1, strict=True, ge=0)]]] = Field(default=0.5, description="Confidence threshold for face detection (0.0-1.0).")
    max_faces_per_image: Optional[Annotated[int, Field(strict=True, ge=1)]] = Field(default=None, description="Maximum number of faces to process per image. None: Process all.")
    normalize_embeddings: Optional[StrictBool] = Field(default=True, description="L2-normalize embeddings to unit vectors (recommended).")
    enable_quality_scoring: Optional[StrictBool] = Field(default=True, description="Compute quality scores (blur, size, landmarks). Adds ~5ms per face.")
    quality_threshold: Optional[Union[Annotated[float, Field(le=1.0, strict=True, ge=0.0)], Annotated[int, Field(le=1, strict=True, ge=0)]]] = Field(default=None, description="Minimum quality score to index faces. None: Index all faces. 0.5: Moderate filtering. 0.7: High quality only.")
    max_video_length: Optional[Annotated[int, Field(le=300, strict=True, ge=1)]] = Field(default=60, description="Maximum video length in seconds. 60: Default. 10: Recommended for retrieval. 300: Maximum (extraction only).")
    video_sampling_fps: Optional[Union[Annotated[float, Field(le=60.0, strict=True, ge=0.1)], Annotated[int, Field(le=60, strict=True, ge=1)]]] = Field(default=1.0, description="Frames per second to sample from video. 1.0: One frame per second (recommended).")
    video_deduplication: Optional[StrictBool] = Field(default=True, description="Remove duplicate faces across video frames (extraction only). Reduces 90-95% redundancy. NOT used in retrieval.")
    video_deduplication_threshold: Optional[Union[Annotated[float, Field(le=1.0, strict=True, ge=0.0)], Annotated[int, Field(le=1, strict=True, ge=0)]]] = Field(default=0.8, description="Cosine similarity threshold for deduplication. 0.8: Conservative (default).")
    output_mode: Optional[StrictStr] = Field(default='per_face', description="'per_face': One document per face (recommended). 'per_image': One doc per image with faces array.")
    include_face_crops: Optional[StrictBool] = Field(default=False, description="Include aligned 112×112 face crops as base64. Adds ~5KB per face.")
    store_detection_metadata: Optional[StrictBool] = Field(default=True, description="Store bbox, landmarks, detection scores. Recommended for debugging.")
    __properties: ClassVar[List[str]] = ["extractor_type", "detection_model", "min_face_size", "detection_threshold", "max_faces_per_image", "normalize_embeddings", "enable_quality_scoring", "quality_threshold", "max_video_length", "video_sampling_fps", "video_deduplication", "video_deduplication_threshold", "output_mode", "include_face_crops", "store_detection_metadata"]

    @field_validator('extractor_type')
    def extractor_type_validate_enum(cls, value):
        """Validates the enum"""
        if value is None:
            return value

        if value not in set(['face_identity_extractor']):
            raise ValueError("must be one of enum values ('face_identity_extractor')")
        return value

    @field_validator('detection_model')
    def detection_model_validate_enum(cls, value):
        """Validates the enum"""
        if value is None:
            return value

        if value not in set(['scrfd_500m', 'scrfd_2.5g', 'scrfd_10g']):
            raise ValueError("must be one of enum values ('scrfd_500m', 'scrfd_2.5g', 'scrfd_10g')")
        return value

    @field_validator('output_mode')
    def output_mode_validate_enum(cls, value):
        """Validates the enum"""
        if value is None:
            return value

        if value not in set(['per_face', 'per_image']):
            raise ValueError("must be one of enum values ('per_face', 'per_image')")
        return value

    model_config = ConfigDict(
        populate_by_name=True,
        validate_assignment=True,
        protected_namespaces=(),
    )


    def to_str(self) -> str:
        """Returns the string representation of the model using alias"""
        return pprint.pformat(self.model_dump(by_alias=True))

    def to_json(self) -> str:
        """Returns the JSON representation of the model using alias"""
        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
        return json.dumps(self.to_dict())

    @classmethod
    def from_json(cls, json_str: str) -> Optional[Self]:
        """Create an instance of FaceIdentityExtractorParams from a JSON string"""
        return cls.from_dict(json.loads(json_str))

    def to_dict(self) -> Dict[str, Any]:
        """Return the dictionary representation of the model using alias.

        This has the following differences from calling pydantic's
        `self.model_dump(by_alias=True)`:

        * `None` is only added to the output dict for nullable fields that
          were set at model initialization. Other fields with value `None`
          are ignored.
        """
        excluded_fields: Set[str] = set([
        ])

        _dict = self.model_dump(
            by_alias=True,
            exclude=excluded_fields,
            exclude_none=True,
        )
        return _dict

    @classmethod
    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
        """Create an instance of FaceIdentityExtractorParams from a dict"""
        if obj is None:
            return None

        if not isinstance(obj, dict):
            return cls.model_validate(obj)

        _obj = cls.model_validate({
            "extractor_type": obj.get("extractor_type") if obj.get("extractor_type") is not None else 'face_identity_extractor',
            "detection_model": obj.get("detection_model") if obj.get("detection_model") is not None else 'scrfd_2.5g',
            "min_face_size": obj.get("min_face_size") if obj.get("min_face_size") is not None else 20,
            "detection_threshold": obj.get("detection_threshold") if obj.get("detection_threshold") is not None else 0.5,
            "max_faces_per_image": obj.get("max_faces_per_image"),
            "normalize_embeddings": obj.get("normalize_embeddings") if obj.get("normalize_embeddings") is not None else True,
            "enable_quality_scoring": obj.get("enable_quality_scoring") if obj.get("enable_quality_scoring") is not None else True,
            "quality_threshold": obj.get("quality_threshold"),
            "max_video_length": obj.get("max_video_length") if obj.get("max_video_length") is not None else 60,
            "video_sampling_fps": obj.get("video_sampling_fps") if obj.get("video_sampling_fps") is not None else 1.0,
            "video_deduplication": obj.get("video_deduplication") if obj.get("video_deduplication") is not None else True,
            "video_deduplication_threshold": obj.get("video_deduplication_threshold") if obj.get("video_deduplication_threshold") is not None else 0.8,
            "output_mode": obj.get("output_mode") if obj.get("output_mode") is not None else 'per_face',
            "include_face_crops": obj.get("include_face_crops") if obj.get("include_face_crops") is not None else False,
            "store_detection_metadata": obj.get("store_detection_metadata") if obj.get("store_detection_metadata") is not None else True
        })
        return _obj


