# 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, StrictStr, field_validator
from typing import Any, ClassVar, Dict, List, Optional
from typing_extensions import Annotated
from typing import Optional, Set
from typing_extensions import Self

class UniqueKeyConfig(BaseModel):
    """
    Configuration for bucket unique key enforcement.  Enables automatic uniqueness enforcement on one or more fields from the bucket schema. Supports both single field and compound (multi-field) uniqueness constraints.  When configured, the bucket will maintain a lookup table mapping unique key values to document IDs, enabling efficient upsert operations and preventing duplicates.  **Impact on Collection Trigger/Re-processing:** When a collection is triggered (POST /collections/{id}/trigger), the unique_key determines whether documents are overwritten or duplicated: - WITH unique_key: Documents get deterministic IDs → re-triggering OVERWRITES existing docs - WITHOUT unique_key: Documents get random IDs → re-triggering CREATES DUPLICATES  For idempotent pipelines where re-triggering is safe, configure a unique_key.  **Relationship to Extractor position_fields:** The `unique_key` (bucket-level) and `position_fields` (extractor-level) work together to generate deterministic document IDs:  - `unique_key`: Identifies unique SOURCE OBJECTS in the bucket (e.g., video_id) - `position_fields`: Identifies unique OUTPUT DOCUMENTS from a single object (e.g., start_time, end_time)  Document ID Formula:     document_id = hash(source_object_key + extractor_id + collection_id + position_field_values)  Example - Processing a 60-second video with 10-second segments:     - Bucket unique_key: [\"video_id\"] → Identifies the source video     - Extractor position_fields: [\"start_time\", \"end_time\"] → Identifies each segment     - Result: 6 unique document IDs (one per segment), all deterministic  Without position_fields, all segments would get the SAME document_id and overwrite each other. Without unique_key, reprocessing would create DUPLICATE documents instead of updating.  Requirements:     - fields: REQUIRED - Array of field names from bucket schema to use as unique constraint     - default_policy: OPTIONAL - Bucket-level default insertion policy (can be overridden per request)     - All specified fields must exist in the bucket schema     - All fields must be scalar types (string, integer, float, uuid)     - Field values cannot be null or empty in uploaded objects     - Cannot be changed after bucket creation (v1 limitation)  Use Cases:     - Single field uniqueness: [\"video_id\"], [\"product_sku\"], [\"user_email\"]     - Compound uniqueness: [\"sensor_id\", \"timestamp\"], [\"product_id\", \"size\", \"color\"]     - With default policy: Enables idempotent ingestion without per-request policy     - Without default: Requires explicit policy on each upload (safer, more intentional)  Insertion Policies:     - 'insert': Fail with 409 Conflict if key exists (prevents accidental overwrites)     - 'update': Fail with 404 Not Found if key doesn't exist (updates only)     - 'upsert': Update if exists, insert if not (idempotent ingestion)  Policy Resolution (when uploading objects):     1. Use request-level ?policy= parameter if provided (highest priority)     2. Fall back to bucket-level default_policy if configured     3. Return 400 Bad Request if neither is specified (prevents accidental operations)  Examples:     Single field with upsert default (idempotent video ingestion):         {             \"fields\": [\"video_id\"],             \"default_policy\": \"upsert\"         }      Single field with insert default (prevent duplicate products):         {             \"fields\": [\"product_sku\"],             \"default_policy\": \"insert\"         }      Compound fields with upsert (time-series sensor data):         {             \"fields\": [\"sensor_id\", \"timestamp\"],             \"default_policy\": \"upsert\"         }      Compound fields without default (explicit policy required):         {             \"fields\": [\"user_id\", \"session_id\"]         }
    """ # noqa: E501
    fields: Annotated[List[StrictStr], Field(min_length=1)] = Field(description="Field name(s) from bucket schema to use as unique constraint. REQUIRED - must provide at least one field name.   Single field example: ['video_id'] - Enforces uniqueness on video_id alone. Compound example: ['sensor_id', 'timestamp'] - Uniqueness requires BOTH fields to match.   All specified fields must:   - Exist in the bucket schema   - Be scalar types (string, integer, float, uuid - NOT objects or arrays)   - Have non-null, non-empty values in all uploaded objects   - Be 255 characters or less per string field value   Field order doesn't matter (sorted internally for consistency). ['timestamp', 'sensor_id'] is equivalent to ['sensor_id', 'timestamp'].")
    default_policy: Optional[StrictStr] = Field(default=None, description="Default insertion policy for this bucket when not specified per request. OPTIONAL - if omitted, you must provide ?policy= parameter on each upload request.  Policies:   - 'insert': Create new object only. Fail with 409 Conflict if unique key already exists.               Use when: You want to prevent accidental overwrites (safest option).    - 'update': Update existing object only. Fail with 404 Not Found if unique key doesn't exist.               Use when: You only want to update existing records, never create new ones.    - 'upsert': Update if exists, create if not (idempotent operation).               Use when: You want idempotent ingestion (re-running is safe).  Policy Resolution:   1. Request-level ?policy= parameter takes precedence (if provided)   2. Falls back to this default_policy (if configured)   3. Returns 400 Bad Request if neither is specified  Recommendation: Omit default_policy if you want explicit control on each upload. Set default_policy='upsert' for idempotent pipelines.")
    __properties: ClassVar[List[str]] = ["fields", "default_policy"]

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

        if value not in set(['insert', 'update', 'upsert']):
            raise ValueError("must be one of enum values ('insert', 'update', 'upsert')")
        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 UniqueKeyConfig 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 UniqueKeyConfig from a dict"""
        if obj is None:
            return None

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

        _obj = cls.model_validate({
            "fields": obj.get("fields"),
            "default_policy": obj.get("default_policy")
        })
        return _obj


