# 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 datetime import datetime
from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictFloat, StrictInt, StrictStr
from typing import Any, ClassVar, Dict, List, Optional, Union
from mixpeek.models.collection_diagnostic import CollectionDiagnostic
from mixpeek.models.performance_insight import PerformanceInsight
from mixpeek.models.tier_diagnostic import TierDiagnostic
from typing import Optional, Set
from typing_extensions import Self

class BatchDiagnostics(BaseModel):
    """
    Comprehensive batch diagnostics response.  Combines batch status, task progress, collection info, and performance insights into a single response for easy frontend rendering.
    """ # noqa: E501
    batch_id: StrictStr = Field(description="Batch ID")
    batch_name: StrictStr = Field(description="Batch name")
    status: StrictStr = Field(description="Overall batch status")
    bucket_id: StrictStr = Field(description="Source bucket ID")
    current_tier: Optional[StrictInt] = Field(default=0, description="Current tier being processed")
    total_tiers: Optional[StrictInt] = Field(default=1, description="Total number of tiers")
    overall_progress: Optional[Union[StrictFloat, StrictInt]] = Field(default=0.0, description="Overall progress percentage (0-100)")
    created_at: Optional[datetime] = Field(default=None, description="When batch was created")
    submitted_at: Optional[datetime] = Field(default=None, description="When batch was submitted")
    started_at: Optional[datetime] = Field(default=None, description="When processing started")
    completed_at: Optional[datetime] = Field(default=None, description="When processing completed")
    duration_seconds: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Total duration in seconds")
    estimated_completion: Optional[datetime] = Field(default=None, description="Estimated completion time")
    tiers: Optional[List[TierDiagnostic]] = Field(default=None, description="Diagnostic info for each tier")
    collections: Optional[List[CollectionDiagnostic]] = Field(default=None, description="Status of target collections")
    performance_summary: Optional[Dict[str, Any]] = Field(default=None, description="Performance metrics summary (available after completion)")
    insights: Optional[List[PerformanceInsight]] = Field(default=None, description="Performance insights and recommendations")
    has_failures: Optional[StrictBool] = Field(default=False, description="Whether batch has any failures")
    failed_tier_count: Optional[StrictInt] = Field(default=0, description="Number of failed tiers")
    total_objects: Optional[StrictInt] = Field(default=0, description="Total objects in batch")
    next_actions: Optional[List[StrictStr]] = Field(default=None, description="Recommended next steps for user")
    __properties: ClassVar[List[str]] = ["batch_id", "batch_name", "status", "bucket_id", "current_tier", "total_tiers", "overall_progress", "created_at", "submitted_at", "started_at", "completed_at", "duration_seconds", "estimated_completion", "tiers", "collections", "performance_summary", "insights", "has_failures", "failed_tier_count", "total_objects", "next_actions"]

    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 BatchDiagnostics 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 each item in tiers (list)
        _items = []
        if self.tiers:
            for _item_tiers in self.tiers:
                if _item_tiers:
                    _items.append(_item_tiers.to_dict())
            _dict['tiers'] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in collections (list)
        _items = []
        if self.collections:
            for _item_collections in self.collections:
                if _item_collections:
                    _items.append(_item_collections.to_dict())
            _dict['collections'] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in insights (list)
        _items = []
        if self.insights:
            for _item_insights in self.insights:
                if _item_insights:
                    _items.append(_item_insights.to_dict())
            _dict['insights'] = _items
        return _dict

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

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

        _obj = cls.model_validate({
            "batch_id": obj.get("batch_id"),
            "batch_name": obj.get("batch_name"),
            "status": obj.get("status"),
            "bucket_id": obj.get("bucket_id"),
            "current_tier": obj.get("current_tier") if obj.get("current_tier") is not None else 0,
            "total_tiers": obj.get("total_tiers") if obj.get("total_tiers") is not None else 1,
            "overall_progress": obj.get("overall_progress") if obj.get("overall_progress") is not None else 0.0,
            "created_at": obj.get("created_at"),
            "submitted_at": obj.get("submitted_at"),
            "started_at": obj.get("started_at"),
            "completed_at": obj.get("completed_at"),
            "duration_seconds": obj.get("duration_seconds"),
            "estimated_completion": obj.get("estimated_completion"),
            "tiers": [TierDiagnostic.from_dict(_item) for _item in obj["tiers"]] if obj.get("tiers") is not None else None,
            "collections": [CollectionDiagnostic.from_dict(_item) for _item in obj["collections"]] if obj.get("collections") is not None else None,
            "performance_summary": obj.get("performance_summary"),
            "insights": [PerformanceInsight.from_dict(_item) for _item in obj["insights"]] if obj.get("insights") is not None else None,
            "has_failures": obj.get("has_failures") if obj.get("has_failures") is not None else False,
            "failed_tier_count": obj.get("failed_tier_count") if obj.get("failed_tier_count") is not None else 0,
            "total_objects": obj.get("total_objects") if obj.get("total_objects") is not None else 0,
            "next_actions": obj.get("next_actions")
        })
        return _obj


