# coding: utf-8

"""
    STACKIT CDN API

    API used to create and manage your CDN distributions.

    The version of the OpenAPI document: 1.0.0
    Generated by OpenAPI Generator (https://openapi-generator.tech)

    Do not edit the class manually.
"""  # noqa: E501

from __future__ import annotations

import json
import pprint
from typing import Any, ClassVar, Dict, List, Optional, Set

from pydantic import BaseModel, ConfigDict, Field, StrictStr
from typing_extensions import Annotated, Self

from stackit.cdn.models.waf_mode import WafMode
from stackit.cdn.models.waf_paranoia_level import WafParanoiaLevel
from stackit.cdn.models.waf_type import WafType


class WafConfig(BaseModel):
    """
    Configuration of the WAF of a distribution  A WAF Config always contains a WAF Mode and Type. If a WAF was never enabled, most of the properties are not present. To **enable** the WAF for your Distribution, you must set the `mode` to `ENABLED` or `LOG_ONLY`.   This causes the other properties to be populated.  ## Rules There are 9 properties used to control which Rules are enabled, disabled or set to Log-Only. These properties can be grouped in 3 groups of 3. Each of these groups varies in specificity: Rules are more specific than Rule Groups, which in turn are more specific than Collections. More specific definitions override more generic definitions.  ### Collections - `enabledRuleCollectionIds` - `disabledRuleCollectionIds` - `logOnlyRuleCollectionIds` These are the least specific selectors. As of 2025, only two collections exist:   - `@builtin/crs/response`, containing all Rules regarding Responses   - `@builtin/crs/request`, containing all Rules regarding Requests     More collections may be added in the future ### Rule Groups - `enabledRuleGroupIds` - `disabledRuleGroupIds` - `logOnlyRuleGroupIds`   These are more specific than Collections and will override their selector. You can find all available Rule Groups by calling the `ListWafCollections` Operation. ### Rules - `enabledRuleIds` - `disabledRuleIds` - `logOnlyRuleGds`   Being the most specific selectors, these will override both Collection and Rule Group selectors. You can find all available Rule Groups by calling the `ListWafCollections` Operation.  ### TIP: Review resolved config If you call `GetDistribution` with `?withWafStatus=true`, you get back a resolved WAF Rules Config which contains a `waf` property which you can inspect to see why a Rule is either enabled, disabled or logOnly.
    """  # noqa: E501

    allowed_http_methods: Optional[Annotated[List[StrictStr], Field(min_length=1)]] = Field(
        default=None,
        description="This whitelist restricts which HTTP methods the distribution accepts. Requests using non-whitelisted methods are blocked by the WAF before reaching the origin.  Common methods: `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS`, `CONNECT`, `TRACE`  Validation ensures: 1. At least one method is allowed 2. No duplicate methods (e.g., `GET` appearing twice) 3. Each method is valid per HTTP standards ",
        alias="allowedHttpMethods",
    )
    allowed_http_versions: Optional[Annotated[List[StrictStr], Field(min_length=1)]] = Field(
        default=None, alias="allowedHttpVersions"
    )
    allowed_request_content_types: Optional[Annotated[List[StrictStr], Field(min_length=1)]] = Field(
        default=None,
        description="This allow list restricts which Content-Type headers are accepted in request bodies.  Format: Must be `type/subtype` with no spaces.  Common content types: - `application/json` - `application/x-www-form-urlencoded` - `multipart/form-data` - `text/html` - `text/plain` - `application/xml` ",
        alias="allowedRequestContentTypes",
    )
    disabled_rule_collection_ids: Optional[List[StrictStr]] = Field(
        default=None, description="Ids of WAF Collections to mark as disabled ", alias="disabledRuleCollectionIds"
    )
    disabled_rule_group_ids: Optional[List[StrictStr]] = Field(
        default=None, description="Ids of WAF Rule Groups to mark as disabled ", alias="disabledRuleGroupIds"
    )
    disabled_rule_ids: Optional[List[StrictStr]] = Field(
        default=None,
        description="Ids of WAF Rules that are **explicitly** disabled for this distribution. ",
        alias="disabledRuleIds",
    )
    enabled_rule_collection_ids: Optional[List[StrictStr]] = Field(
        default=None, description="Ids of WAF Collections to mark as enabled ", alias="enabledRuleCollectionIds"
    )
    enabled_rule_group_ids: Optional[List[StrictStr]] = Field(
        default=None, description="Ids of WAF Rule Groups to mark as enabled ", alias="enabledRuleGroupIds"
    )
    enabled_rule_ids: List[StrictStr] = Field(
        description="Ids of the WAF rules that are **explicitly** enabled for this distribution.  If this rule is in a disabled / log Only RuleGroup or Collection, it will be enabled regardless as `enabledRuleIds` overrides those in specificity.  Do note that rules can also be enabled because a Rulegroup or Collection is enabled.  **DO NOT** use this property to find all active rules. Instead, pass `?withWafStatus=true` as a query parameter to `GetDistribution` or `ListDistributions`. This will expose the `waf` Property on distribution Level.  From there you can `$.waf.enabledRules.map(e => e.id)` to get a list of all enabled rules. ",
        alias="enabledRuleIds",
    )
    log_only_rule_collection_ids: Optional[List[StrictStr]] = Field(
        default=None, description="Ids of WAF Collections to mark as log Only. ", alias="logOnlyRuleCollectionIds"
    )
    log_only_rule_group_ids: Optional[List[StrictStr]] = Field(
        default=None, description="Ids of WAF Rule Groups to mark as log Only. ", alias="logOnlyRuleGroupIds"
    )
    log_only_rule_ids: Optional[List[StrictStr]] = Field(
        default=None,
        description="Ids of WAF Rules that are **explicitly** marked as Log Only for this distribution. ",
        alias="logOnlyRuleIds",
    )
    mode: WafMode
    paranoia_level: Optional[WafParanoiaLevel] = Field(default=None, alias="paranoiaLevel")
    type: WafType
    __properties: ClassVar[List[str]] = [
        "allowedHttpMethods",
        "allowedHttpVersions",
        "allowedRequestContentTypes",
        "disabledRuleCollectionIds",
        "disabledRuleGroupIds",
        "disabledRuleIds",
        "enabledRuleCollectionIds",
        "enabledRuleGroupIds",
        "enabledRuleIds",
        "logOnlyRuleCollectionIds",
        "logOnlyRuleGroupIds",
        "logOnlyRuleIds",
        "mode",
        "paranoiaLevel",
        "type",
    ]

    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 WafConfig 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 WafConfig from a dict"""
        if obj is None:
            return None

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

        _obj = cls.model_validate(
            {
                "allowedHttpMethods": obj.get("allowedHttpMethods"),
                "allowedHttpVersions": obj.get("allowedHttpVersions"),
                "allowedRequestContentTypes": obj.get("allowedRequestContentTypes"),
                "disabledRuleCollectionIds": obj.get("disabledRuleCollectionIds"),
                "disabledRuleGroupIds": obj.get("disabledRuleGroupIds"),
                "disabledRuleIds": obj.get("disabledRuleIds"),
                "enabledRuleCollectionIds": obj.get("enabledRuleCollectionIds"),
                "enabledRuleGroupIds": obj.get("enabledRuleGroupIds"),
                "enabledRuleIds": obj.get("enabledRuleIds"),
                "logOnlyRuleCollectionIds": obj.get("logOnlyRuleCollectionIds"),
                "logOnlyRuleGroupIds": obj.get("logOnlyRuleGroupIds"),
                "logOnlyRuleIds": obj.get("logOnlyRuleIds"),
                "mode": obj.get("mode"),
                "paranoiaLevel": obj.get("paranoiaLevel"),
                "type": obj.get("type"),
            }
        )
        return _obj
