# 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 mixpeek.models.index import Index
from typing import Optional, Set
from typing_extensions import Self

class VectorIndexDefinition(BaseModel):
    """
    Complete vector index definition that can be either single or multi-vector.  This is the USER-FACING representation that appears in feature extractor definitions and API responses. It wraps a VectorIndex (or MultiVectorIndex) and adds metadata.  Key Concepts - Two-Name System:     - VectorIndexDefinition.name: SHORT user-facing name (e.g., \"embedding\")       Used in feature URIs: mixpeek://text_extractor@v1/multilingual_e5_large_instruct_v1                                                         ^^^^^^^^^^      - VectorIndex.name: FULL storage name (e.g., \"text_extractor_v1_embedding\")       Used as Qdrant collection name for namespace isolation  This two-level naming allows clean URIs while preventing storage collisions.  Use Cases:     - Define extractor outputs in feature extractor definitions     - Expose available vector indexes in collection metadata     - Enable feature URI resolution (short name → full storage name)  Requirements:     - name: REQUIRED - Short output name for feature URIs     - description: REQUIRED - Explain what this output produces     - type: REQUIRED - \"single\" (most common) or \"multi\" (rare)     - index: REQUIRED - Nested VectorIndex or MultiVectorIndex     - feature_uri: OPTIONAL - Populated at collection creation time
    """ # noqa: E501
    feature_uri: Optional[StrictStr] = Field(default=None, description="Full feature URI for this vector index. Format: mixpeek://{extractor}@{version}/{output_name}. Populated at collection creation time. Use this URI in retriever feature_filter stages.")
    name: Annotated[str, Field(min_length=1, strict=True)] = Field(description="REQUIRED. Short user-facing output name used in feature URIs. This is NOT the Qdrant collection name - it's the clean identifier for this output. Format: Simple snake_case name (e.g., 'embedding', 'video_embedding', 'sparse_embedding'). Used in feature URIs: mixpeek://{extractor}@{version}/{THIS_NAME}. Must be unique within this extractor's outputs.")
    description: Annotated[str, Field(min_length=10, strict=True)] = Field(description="REQUIRED. Human-readable description of this vector output. Explain what content this output embeds and when to use it. Appears in API documentation and helps users choose the right feature URI. Be specific about the embedding type and use cases.")
    type: StrictStr = Field(description="REQUIRED. Index type - 'single' or 'multi'. 'single': One vector per document (most common). Use for standard embeddings. 'multi': Multiple named vectors per document (rare). Use for hybrid/ensemble. Determines whether 'index' field contains VectorIndex or MultiVectorIndex.")
    index: Index
    __properties: ClassVar[List[str]] = ["feature_uri", "name", "description", "type", "index"]

    @field_validator('type')
    def type_validate_enum(cls, value):
        """Validates the enum"""
        if value not in set(['single', 'multi']):
            raise ValueError("must be one of enum values ('single', 'multi')")
        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 VectorIndexDefinition 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,
        )
        # override the default output from pydantic by calling `to_dict()` of index
        if self.index:
            _dict['index'] = self.index.to_dict()
        return _dict

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

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

        _obj = cls.model_validate({
            "feature_uri": obj.get("feature_uri"),
            "name": obj.get("name"),
            "description": obj.get("description"),
            "type": obj.get("type"),
            "index": Index.from_dict(obj["index"]) if obj.get("index") is not None else None
        })
        return _obj


