# 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
from typing_extensions import Annotated
from typing import Optional, Set
from typing_extensions import Self

class CreateUploadRequest(BaseModel):
    """
    Request to generate a presigned URL for direct S3 upload.  ⚠️  ⚠️  ⚠️  THIS IS THE PRESIGNED URL SYSTEM ⚠️  ⚠️  ⚠️  This endpoint (POST /buckets/{id}/uploads) is the COMPLETE presigned URL system. It handles: - ✅ Presigned URL generation (S3 PUT URLs) - ✅ Upload tracking and status management - ✅ Validation (quotas, file size, content type, schema) - ✅ Duplicate detection - ✅ Auto object creation on confirmation - ✅ Returns upload_id for later reference  DO NOT CREATE A NEW PRESIGNED UPLOAD ENDPOINT! If you need presigned URLs, use this existing system.  If you think you need a new endpoint: 1. Check if this system already does it (it probably does) 2. Extend this system instead of creating redundancy 3. See api/buckets/uploads/services.py for implementation  Integration Points: - Object creation: Use upload_id in CreateBlobRequest.upload_id field - See: shared/buckets/objects/blobs/models.py::CreateBlobRequest - See: api/buckets/objects/canonicalization.py::resolve_upload_reference()  Workflow: 1. POST /buckets/{id}/uploads → Returns presigned_url + upload_id 2. PUT presigned_url with file content (client uploads directly to S3) 3. POST /uploads/{upload_id}/confirm → REQUIRED to finalize upload 4. Object is created automatically (default behavior)  ⚠️  IMPORTANT: Step 3 (confirm) is REQUIRED! S3 presigned URLs have no callback mechanism - the API cannot detect when your upload to S3 completes. You MUST call the confirm endpoint to: - Verify the file exists in S3 - Validate integrity (ETag/size) - Create the bucket object - Mark upload as COMPLETED  If you don't confirm: - Upload stays in PENDING status forever - No object is created - File exists in S3 but is orphaned - Presigned URL expires (default: 1 hour)  Use Cases:     - Simple: Upload → confirm → object created automatically (default)     - Advanced: Upload multiple files with create_object_on_confirm=false,       then POST /buckets/{id}/objects with all upload_ids to create one object  Requirements:     - filename: REQUIRED, will be validated (no path traversal)     - content_type: REQUIRED, must be valid MIME type     - bucket_id: Comes from URL path parameter, not request body     - All other fields: OPTIONAL with sensible defaults  Note:     The bucket_id comes from the URL path (/v1/buckets/{bucket_id}/uploads),     not from the request body. The bucket is validated before generating presigned URL.
    """ # noqa: E501
    filename: Annotated[str, Field(min_length=1, strict=True, max_length=255)] = Field(description="Name of the file to upload. REQUIRED. Must be a valid filename without path traversal characters (../, \\). The filename is used to derive the blob_property if not explicitly provided. Examples: 'product_video.mp4', 'thumbnail.jpg', 'transcript.txt'")
    content_type: StrictStr = Field(description="MIME type of the file. REQUIRED. Must be a valid MIME type (e.g., 'video/mp4', 'image/jpeg', 'application/pdf'). The presigned URL will enforce this content type during upload. Used to validate compatibility with bucket schema if create_object_on_confirm=true.")
    file_size_bytes: Optional[Annotated[int, Field(strict=True, ge=1)]] = Field(default=None, description="Expected file size in bytes. OPTIONAL but RECOMMENDED. If provided, will be validated against: 1. Tier-based file size limits (100MB free, 5GB pro, 50GB enterprise) 2. Storage quota availability 3. Actual uploaded file size during confirmation. If not provided, quota checking is skipped until confirmation.")
    presigned_url_expiration: Optional[Annotated[int, Field(le=86400, strict=True, ge=60)]] = Field(default=3600, description="How long the presigned URL is valid, in seconds. OPTIONAL, defaults to 3600 (1 hour). Valid range: 60 seconds (1 minute) to 86400 seconds (24 hours). After expiration, the URL cannot be used and you must request a new one. Recommendation: Use shorter expiration (300-900 seconds) for security-sensitive files, longer expiration (3600-7200 seconds) for large files that take time to upload.")
    metadata: Optional[Dict[str, Any]] = Field(default=None, description="Custom metadata for tracking purposes. OPTIONAL. Stored with the upload record for filtering and analytics. Does NOT affect the created bucket object (use object_metadata for that). Common uses: campaign tracking, user identification, upload source.")
    create_object_on_confirm: Optional[StrictBool] = Field(default=True, description="Whether to automatically create a bucket object when upload is confirmed. OPTIONAL, defaults to TRUE (object is created automatically). If true (default):   - Bucket MUST have a schema defined   - blob_property must exist in bucket schema   - content_type must match schema field type   - Validation happens BEFORE generating presigned URL   - Object is created automatically on confirmation. If false:   - Upload is confirmed but no object is created   - Use this when combining multiple uploads into one object   - Reference the upload_id later in POST /buckets/{id}/objects.")
    object_metadata: Optional[Dict[str, Any]] = Field(default=None, description="Metadata to attach to the created bucket object. OPTIONAL. Only used if create_object_on_confirm=true. This metadata will be:   1. Validated against bucket schema (if keys match schema fields)   2. Attached to the bucket object   3. Passed to downstream documents in connected collections. Example: {'priority': 'high', 'category': 'products', 'tags': ['featured']}")
    blob_property: Optional[Annotated[str, Field(strict=True)]] = Field(default=None, description="Property name for the blob in the bucket object. OPTIONAL. Defaults to filename without extension (e.g., 'product_video.mp4' → 'product_video'). If create_object_on_confirm=true:   - Must exist in bucket schema   - Must be alphanumeric with underscores only   - Will be validated BEFORE generating presigned URL. Common values: 'video', 'image', 'thumbnail', 'transcript', 'content'.")
    blob_type: Optional[StrictStr] = Field(default=None, description="Type of blob. OPTIONAL. Defaults to type derived from content_type (e.g., 'video/mp4' → 'VIDEO'). Must be a valid BucketSchemaFieldType if provided. Valid values: IMAGE, VIDEO, AUDIO, TEXT, PDF, DOCUMENT, etc. If create_object_on_confirm=true, will be validated against bucket schema field type.")
    file_hash: Optional[Annotated[str, Field(min_length=64, strict=True, max_length=64)]] = Field(default=None, description="SHA256 hash of the file content for duplicate detection. OPTIONAL. If provided:   - System checks for existing confirmed uploads with same hash   - If duplicate found and skip_duplicates=true, returns existing upload   - Hash will be validated against actual S3 ETag during confirmation. If not provided:   - Hash is calculated from S3 ETag after upload   - Duplicate detection only happens during confirmation. Use case: Pre-calculate hash client-side to avoid uploading duplicates. Format: 64-character hexadecimal string (SHA256).")
    skip_duplicates: Optional[StrictBool] = Field(default=True, description="Skip upload if a file with the same hash already exists. OPTIONAL, defaults to TRUE. If true (default):   - If file_hash provided: System checks MongoDB for existing completed upload with same hash   - If duplicate found: Returns existing upload details WITHOUT generating new presigned URL   - If file_hash NOT provided: Duplicate check happens during confirmation using S3 ETag   - Saves bandwidth, storage, and upload time by reusing existing files. If false:   - Always generates new presigned URL even if file already uploaded   - Creates separate upload record for same file content   - Useful when you need distinct upload tracking for identical files. Recommendation: Keep default (true) unless you specifically need multiple upload records for same file.")
    __properties: ClassVar[List[str]] = ["filename", "content_type", "file_size_bytes", "presigned_url_expiration", "metadata", "create_object_on_confirm", "object_metadata", "blob_property", "blob_type", "file_hash", "skip_duplicates"]

    @field_validator('blob_property')
    def blob_property_validate_regular_expression(cls, value):
        """Validates the regular expression"""
        if value is None:
            return value

        if not re.match(r"^[a-zA-Z0-9_]+$", value):
            raise ValueError(r"must validate the regular expression /^[a-zA-Z0-9_]+$/")
        return value

    @field_validator('file_hash')
    def file_hash_validate_regular_expression(cls, value):
        """Validates the regular expression"""
        if value is None:
            return value

        if not re.match(r"^[a-f0-9]{64}$", value):
            raise ValueError(r"must validate the regular expression /^[a-f0-9]{64}$/")
        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 CreateUploadRequest 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 CreateUploadRequest from a dict"""
        if obj is None:
            return None

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

        _obj = cls.model_validate({
            "filename": obj.get("filename"),
            "content_type": obj.get("content_type"),
            "file_size_bytes": obj.get("file_size_bytes"),
            "presigned_url_expiration": obj.get("presigned_url_expiration") if obj.get("presigned_url_expiration") is not None else 3600,
            "metadata": obj.get("metadata"),
            "create_object_on_confirm": obj.get("create_object_on_confirm") if obj.get("create_object_on_confirm") is not None else True,
            "object_metadata": obj.get("object_metadata"),
            "blob_property": obj.get("blob_property"),
            "blob_type": obj.get("blob_type"),
            "file_hash": obj.get("file_hash"),
            "skip_duplicates": obj.get("skip_duplicates") if obj.get("skip_duplicates") is not None else True
        })
        return _obj


