# 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
from typing import Any, ClassVar, Dict, List, Optional
from typing_extensions import Annotated
from mixpeek.models.auth_config import AuthConfig
from mixpeek.models.error_handling import ErrorHandling
from mixpeek.models.logical_operator import LogicalOperator
from mixpeek.models.rate_limit_config import RateLimitConfig
from typing import Optional, Set
from typing_extensions import Self

class StageParamsApiCall(BaseModel):
    """
    Configuration for API call enrichment stage.  **Stage Category**: ENRICH (1-1 Enrichment)  **⚠️ CRITICAL SECURITY WARNINGS ⚠️**:  1. **SSRF Risk**: This stage makes external HTTP requests which can be exploited    for Server-Side Request Forgery attacks. ALWAYS use `allowed_domains` allowlist.  2. **Data Exfiltration**: Malicious configurations could send internal data to    external endpoints. Audit all configurations before deployment.  3. **Credential Safety**: NEVER store credentials directly in configuration.    Always use `auth.secret_ref` to reference vault-stored credentials.  4. **Rate Limiting**: Set rate limits to prevent abuse and excessive costs.  5. **Domain Allowlist**: REQUIRED. Explicitly list allowed domains. Never use \"*\".  **Transformation**: N documents → N documents (same count, expanded schema)  **Purpose**: Enriches documents by calling external HTTP APIs. Enables integration with third-party services (Stripe, GitHub, weather APIs, etc.) to augment documents with real-time data. Due to security risks, this stage implements strict controls including domain allowlisting, SSRF protection, rate limiting, and secure credential management.  **When to Use**:     - Enrich documents with data from external APIs     - Integrate third-party services (Stripe, GitHub, Salesforce)     - Fetch real-time data (weather, stocks, currency rates)     - Validate data against external systems     - Lookup additional context from APIs  **When NOT to Use**:     - For untrusted/user-provided URLs (major security risk)     - When API credentials can't be securely stored     - For high-volume enrichment (rate limits apply)     - When response time is critical (network latency)     - For internal-only APIs behind firewalls  Requirements:     - url: REQUIRED, API endpoint URL (supports templates)     - allowed_domains: REQUIRED, domain allowlist (NEVER use \"*\")     - method: OPTIONAL, HTTP method (default: GET)     - auth: OPTIONAL, authentication configuration     - headers: OPTIONAL, additional headers     - body: OPTIONAL, request body (for POST/PUT)     - output_field: REQUIRED, where to store response     - timeout: OPTIONAL, request timeout (default: 10s)     - max_response_size: OPTIONAL, max response size (default: 10MB)     - when: OPTIONAL, conditional enrichment filter     - on_error: OPTIONAL, error handling (skip/remove/raise)  Use Cases:     - Stripe customer lookup: Enrich with billing data     - GitHub repo info: Fetch commit stats     - Weather API: Add location-based weather     - Currency conversion: Real-time exchange rates     - Address validation: Verify and standardize addresses
    """ # noqa: E501
    url: Optional[StrictStr] = Field(default='https://httpbin.org/get', description="API endpoint URL to call. Supports template variables: {INPUT.field}, {DOC.field}. Must be HTTP/HTTPS. Domain must be in allowed_domains list. Default uses httpbin.org for testing. Examples: 'https://api.stripe.com/v1/customers/{DOC.metadata.customer_id}'")
    allowed_domains: Optional[Annotated[List[StrictStr], Field(min_length=1)]] = Field(default=None, description="Allowlist of domains that can be called. CRITICAL FOR SECURITY - prevents SSRF attacks. Supports wildcards: '*.example.com' matches subdomains. NEVER use '*' (all domains) in production. Default allows httpbin.org for testing. Examples: ['api.stripe.com', '*.github.com', 'api.weatherapi.com']")
    method: Optional[StrictStr] = Field(default='GET', description="HTTP method: GET, POST, PUT, PATCH, DELETE. Default: GET.")
    auth: Optional[AuthConfig] = Field(default=None, description="OPTIONAL. Authentication configuration. Uses organization vault for credential storage. See AuthConfig for details.")
    headers: Optional[Dict[str, StrictStr]] = Field(default=None, description="OPTIONAL. Additional HTTP headers to include. Do NOT include authentication headers here - use 'auth' field. Supports template variables in values. Example: {'Content-Type': 'application/json', 'X-Custom': '{{INPUT.value}}'}")
    body: Optional[Dict[str, Any]] = Field(default=None, description="OPTIONAL. Request body (for POST/PUT/PATCH). Serialized as JSON. Supports template variables in values. Only used for non-GET requests.")
    output_field: Optional[StrictStr] = Field(default='metadata.api_response', description="Dot-path where API response should be stored. Creates nested structure if needed. Response stored as-is (JSON object/array/primitive). Example: 'metadata.api_data'")
    timeout: Optional[Annotated[int, Field(le=60, strict=True, ge=1)]] = Field(default=10, description="Request timeout in seconds. Range: 1-60. Default: 10.")
    max_response_size: Optional[Annotated[int, Field(strict=True, ge=1024)]] = Field(default=10485760, description="Maximum response size in bytes. Prevents memory exhaustion. Default: 10MB.")
    rate_limit: Optional[RateLimitConfig] = Field(default=None, description="OPTIONAL. Rate limiting configuration per domain.")
    response_path: Optional[StrictStr] = Field(default='null', description="OPTIONAL. JSONPath expression to extract specific field from response. If not specified, stores entire response. Examples: '$.data', '$.results[0]', '$.customer.email'")
    when: Optional[LogicalOperator] = Field(default=None, description="OPTIONAL. Conditional filter for selective enrichment. Only documents matching condition will call API. RECOMMENDED for cost/performance optimization.")
    on_error: Optional[ErrorHandling] = Field(default=None, description="Error handling strategy: 'skip': Pass document through unchanged. 'remove': Remove failed documents. 'raise': Halt pipeline on error. Default: 'skip'.")
    __properties: ClassVar[List[str]] = ["url", "allowed_domains", "method", "auth", "headers", "body", "output_field", "timeout", "max_response_size", "rate_limit", "response_path", "when", "on_error"]

    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 StageParamsApiCall 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 auth
        if self.auth:
            _dict['auth'] = self.auth.to_dict()
        # override the default output from pydantic by calling `to_dict()` of rate_limit
        if self.rate_limit:
            _dict['rate_limit'] = self.rate_limit.to_dict()
        # override the default output from pydantic by calling `to_dict()` of when
        if self.when:
            _dict['when'] = self.when.to_dict()
        return _dict

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

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

        _obj = cls.model_validate({
            "url": obj.get("url") if obj.get("url") is not None else 'https://httpbin.org/get',
            "allowed_domains": obj.get("allowed_domains"),
            "method": obj.get("method") if obj.get("method") is not None else 'GET',
            "auth": AuthConfig.from_dict(obj["auth"]) if obj.get("auth") is not None else None,
            "headers": obj.get("headers"),
            "body": obj.get("body"),
            "output_field": obj.get("output_field") if obj.get("output_field") is not None else 'metadata.api_response',
            "timeout": obj.get("timeout") if obj.get("timeout") is not None else 10,
            "max_response_size": obj.get("max_response_size") if obj.get("max_response_size") is not None else 10485760,
            "rate_limit": RateLimitConfig.from_dict(obj["rate_limit"]) if obj.get("rate_limit") is not None else None,
            "response_path": obj.get("response_path") if obj.get("response_path") is not None else 'null',
            "when": LogicalOperator.from_dict(obj["when"]) if obj.get("when") is not None else None,
            "on_error": obj.get("on_error")
        })
        return _obj


