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

class SnowflakeConfig(BaseModel):
    """
    Snowflake data warehouse configuration for table-based sync.  Enables syncing Snowflake table rows as JSON objects in Mixpeek buckets. Each row becomes one object, with incremental sync via watermark columns.  Authentication Options:     - Key Pair: Recommended for production (secure, password-less)     - Username/Password: Fallback option (simpler setup)  Requirements:     - Snowflake account with read access to target tables     - Warehouse with compute resources     - SELECT permissions on target tables/schemas     - USAGE permissions on database, schema, warehouse  Use Cases:     - Sync customer data tables for AI/ML pipelines     - Ingest product catalog for search/recommendations     - Process transaction logs for analytics     - Mirror metadata tables for vector search  Example:     Production setup with key pair auth:     ```python     config = {         \"provider_type\": \"snowflake\",         \"credentials\": {             \"type\": \"key_pair\",             \"username\": \"MIXPEEK_SYNC\",             \"private_key\": \"-----BEGIN PRIVATE KEY-----\\n...\\n-----END PRIVATE KEY-----\\n\",         },         \"account\": \"xy12345.us-east-1\",         \"warehouse\": \"MIXPEEK_SYNC_WH\",         \"database\": \"PRODUCTION\",         \"schema\": \"PUBLIC\",         \"role\": \"SYNC_ROLE\",         \"incremental_column\": \"updated_at\",         \"primary_key_columns\": [\"id\"],     }     ```
    """ # noqa: E501
    provider_type: Optional[StrictStr] = 'snowflake'
    credentials: Credentials3
    account: StrictStr = Field(description="REQUIRED. Snowflake account identifier. Format: {account_locator}.{cloud_region} or {org_name}-{account_name} Find in: Snowflake UI > Account dropdown > Account URL")
    warehouse: StrictStr = Field(description="REQUIRED. Warehouse name for compute resources. Must have USAGE privilege on this warehouse. Warehouse will be used for all sync queries. Consider: Use dedicated warehouse for sync operations to isolate costs.")
    database: Optional[StrictStr] = Field(default=None, description="NOT REQUIRED if fully qualified table name used in source_path. Database name for default context. Can be omitted if source_path uses {DATABASE}.{SCHEMA}.{TABLE} format. Must have USAGE privilege if specified.")
    var_schema: Optional[StrictStr] = Field(default=None, description="NOT REQUIRED if fully qualified table name used in source_path. Schema name for default context. Can be omitted if source_path uses {SCHEMA}.{TABLE} or {DATABASE}.{SCHEMA}.{TABLE}. Must have USAGE privilege if specified.", alias="schema")
    role: Optional[StrictStr] = Field(default=None, description="NOT REQUIRED. Snowflake role to use for operations. If omitted, uses user's default role. Role must have SELECT on target tables and USAGE on database/schema/warehouse. Best practice: Create dedicated read-only role for sync operations.")
    incremental_column: Optional[StrictStr] = Field(default=None, description="NOT REQUIRED. Column name for incremental sync watermark. Should be a TIMESTAMP, TIMESTAMP_NTZ, or DATE column that tracks row modifications. When set, only rows with {incremental_column} > last_sync_watermark are synced. Common values: updated_at, modified_at, last_updated, ingestion_timestamp. If omitted, full table scan on every sync (not recommended for large tables).")
    primary_key_columns: Optional[List[StrictStr]] = Field(default=None, description="NOT REQUIRED. Column names forming the primary key for stable object IDs. Used to generate deterministic file_id for deduplication. If omitted, uses hash of entire row content (less stable). Recommendation: Always specify for production to ensure idempotent syncs.")
    query_timeout_seconds: Optional[Annotated[int, Field(le=3600, strict=True, ge=30)]] = Field(default=300, description="Query timeout in seconds. Prevents long-running queries from blocking sync operations. Default: 300 seconds (5 minutes). Increase for large tables or complex queries.")
    fetch_size: Optional[Annotated[int, Field(le=10000, strict=True, ge=100)]] = Field(default=1000, description="Number of rows to fetch per network round-trip. Higher values reduce network overhead but increase memory usage. Default: 1000 rows. Tune based on row size and available memory.")
    __properties: ClassVar[List[str]] = ["provider_type", "credentials", "account", "warehouse", "database", "schema", "role", "incremental_column", "primary_key_columns", "query_timeout_seconds", "fetch_size"]

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

        if value not in set(['snowflake']):
            raise ValueError("must be one of enum values ('snowflake')")
        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 SnowflakeConfig 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 credentials
        if self.credentials:
            _dict['credentials'] = self.credentials.to_dict()
        return _dict

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

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

        _obj = cls.model_validate({
            "provider_type": obj.get("provider_type") if obj.get("provider_type") is not None else 'snowflake',
            "credentials": Credentials3.from_dict(obj["credentials"]) if obj.get("credentials") is not None else None,
            "account": obj.get("account"),
            "warehouse": obj.get("warehouse"),
            "database": obj.get("database"),
            "schema": obj.get("schema"),
            "role": obj.get("role"),
            "incremental_column": obj.get("incremental_column"),
            "primary_key_columns": obj.get("primary_key_columns"),
            "query_timeout_seconds": obj.get("query_timeout_seconds") if obj.get("query_timeout_seconds") is not None else 300,
            "fetch_size": obj.get("fetch_size") if obj.get("fetch_size") is not None else 1000
        })
        return _obj


