# coding: utf-8

"""
    STACKIT File Storage (SFS)

    API used to create and manage NFS Shares.

    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
import re  # noqa: F401
from datetime import datetime
from typing import Any, ClassVar, Dict, List, Optional, Set

from pydantic import (
    BaseModel,
    ConfigDict,
    Field,
    StrictBool,
    StrictInt,
    StrictStr,
    field_validator,
)
from typing_extensions import Self

from stackit.sfs.models.resource_pool_performance_class import (
    ResourcePoolPerformanceClass,
)
from stackit.sfs.models.resource_pool_space import ResourcePoolSpace


class ResourcePool(BaseModel):
    """
    ResourcePool
    """  # noqa: E501

    availability_zone: Optional[StrictStr] = Field(
        default=None, description="Name of the respective availability zone", alias="availabilityZone"
    )
    count_shares: Optional[StrictInt] = Field(
        default=None, description="Number of Shares in the Resource Pool", alias="countShares"
    )
    created_at: Optional[datetime] = Field(default=None, alias="createdAt")
    id: Optional[StrictStr] = Field(default=None, description="ID of the Resource Pool")
    ip_acl: Optional[List[StrictStr]] = Field(
        default=None,
        description='List of IPs that can mount the Resource Pool in read-only; IPs must have a subnet mask (e.g. "172.16.0.0/24" for a range of IPs,  or "172.16.0.250/32" for a specific IP)',
        alias="ipAcl",
    )
    labels: Optional[Dict[str, StrictStr]] = None
    mount_path: Optional[StrictStr] = Field(
        default=None,
        description="Mount path of the Resource Pool, used to mount the Resource Pool   Note that a Resource Pool can only be mounted in read-only",
        alias="mountPath",
    )
    name: Optional[StrictStr] = Field(default=None, description="Name of the Resource Pool")
    performance_class: Optional[ResourcePoolPerformanceClass] = Field(
        default=None, description="Information about the performance class", alias="performanceClass"
    )
    performance_class_downgradable_at: Optional[datetime] = Field(
        default=None,
        description="Time when the performance class can be downgraded again.",
        alias="performanceClassDowngradableAt",
    )
    size_reducible_at: Optional[datetime] = Field(
        default=None, description="Time when the size can be reduced again.", alias="sizeReducibleAt"
    )
    snapshots_are_visible: Optional[StrictBool] = Field(
        default=False,
        description="Whether the .snapshot directory is visible when mounting the resource pool.  Setting this value to false might prevent you from accessing the snapshots (e.g.  for security reasons). Additionally, the access to the snapshots is always controlled  by the export policy of the resource pool. That means, if snapshots are visible and  the export policy allows for reading the resource pool, then it also allows reading  the snapshot of all shares.",
        alias="snapshotsAreVisible",
    )
    space: Optional[ResourcePoolSpace] = Field(default=None, description="Space information")
    state: Optional[StrictStr] = Field(
        default=None,
        description='State of the Resource Pool   (possible values: ["pending", "creating", "created", "updating", "error", "deleting"])',
    )
    __properties: ClassVar[List[str]] = [
        "availabilityZone",
        "countShares",
        "createdAt",
        "id",
        "ipAcl",
        "labels",
        "mountPath",
        "name",
        "performanceClass",
        "performanceClassDowngradableAt",
        "sizeReducibleAt",
        "snapshotsAreVisible",
        "space",
        "state",
    ]

    @field_validator("created_at", mode="before")
    def created_at_change_year_zero_to_one(cls, value):
        """Workaround which prevents year 0 issue"""
        if isinstance(value, str):
            # Check for year "0000" at the beginning of the string
            # This assumes common date formats like YYYY-MM-DDTHH:MM:SS+00:00 or YYYY-MM-DDTHH:MM:SSZ
            if value.startswith("0000-01-01T") and re.match(
                r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\+\d{2}:\d{2}|Z)$", value
            ):
                # Workaround: Replace "0000" with "0001"
                return "0001" + value[4:]  # Take "0001" and append the rest of the string
        return value

    @field_validator("performance_class_downgradable_at", mode="before")
    def performance_class_downgradable_at_change_year_zero_to_one(cls, value):
        """Workaround which prevents year 0 issue"""
        if isinstance(value, str):
            # Check for year "0000" at the beginning of the string
            # This assumes common date formats like YYYY-MM-DDTHH:MM:SS+00:00 or YYYY-MM-DDTHH:MM:SSZ
            if value.startswith("0000-01-01T") and re.match(
                r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\+\d{2}:\d{2}|Z)$", value
            ):
                # Workaround: Replace "0000" with "0001"
                return "0001" + value[4:]  # Take "0001" and append the rest of the string
        return value

    @field_validator("size_reducible_at", mode="before")
    def size_reducible_at_change_year_zero_to_one(cls, value):
        """Workaround which prevents year 0 issue"""
        if isinstance(value, str):
            # Check for year "0000" at the beginning of the string
            # This assumes common date formats like YYYY-MM-DDTHH:MM:SS+00:00 or YYYY-MM-DDTHH:MM:SSZ
            if value.startswith("0000-01-01T") and re.match(
                r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\+\d{2}:\d{2}|Z)$", value
            ):
                # Workaround: Replace "0000" with "0001"
                return "0001" + value[4:]  # Take "0001" and append the rest of the string
        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 ResourcePool 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 performance_class
        if self.performance_class:
            _dict["performanceClass"] = self.performance_class.to_dict()
        # override the default output from pydantic by calling `to_dict()` of space
        if self.space:
            _dict["space"] = self.space.to_dict()
        return _dict

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

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

        _obj = cls.model_validate(
            {
                "availabilityZone": obj.get("availabilityZone"),
                "countShares": obj.get("countShares"),
                "createdAt": obj.get("createdAt"),
                "id": obj.get("id"),
                "ipAcl": obj.get("ipAcl"),
                "labels": obj.get("labels"),
                "mountPath": obj.get("mountPath"),
                "name": obj.get("name"),
                "performanceClass": (
                    ResourcePoolPerformanceClass.from_dict(obj["performanceClass"])
                    if obj.get("performanceClass") is not None
                    else None
                ),
                "performanceClassDowngradableAt": obj.get("performanceClassDowngradableAt"),
                "sizeReducibleAt": obj.get("sizeReducibleAt"),
                "snapshotsAreVisible": (
                    obj.get("snapshotsAreVisible") if obj.get("snapshotsAreVisible") is not None else False
                ),
                "space": ResourcePoolSpace.from_dict(obj["space"]) if obj.get("space") is not None else None,
                "state": obj.get("state"),
            }
        )
        return _obj
