# Code generated by python/tools/generate_jira_worklog_models.py. DO NOT EDIT.
from __future__ import annotations

from dataclasses import dataclass
from typing import Any, Dict, List, Optional

from atlassian.errors import SerializationError

PAGEINFO_HAS_END_CURSOR = True
WORKLOGS_EDGE_HAS_CURSOR = True

JIRA_ISSUE_WORKLOGS_PAGE_QUERY = """query JiraIssueWorklogsPage(
  $cloudId: ID!,
  $key: String!,
  $first: Int!,
  $after: String
) {
  issue: issueByKey(key: $key, cloudId: $cloudId) {
    worklogs(first: $first, after: $after) {
      pageInfo { hasNextPage endCursor }
      edges {
        cursor
        node {
          worklogId
          author { accountId name }
          timeSpent { timeInSeconds }
          created
          updated
          startDate
        }
      }
    }
  }
}
"""


def _expect_dict(obj: Any, path: str) -> Dict[str, Any]:
    if not isinstance(obj, dict):
        raise SerializationError(f"Expected object at {path}")
    return obj


def _expect_list(obj: Any, path: str) -> List[Any]:
    if not isinstance(obj, list):
        raise SerializationError(f"Expected list at {path}")
    return obj


def _expect_str(obj: Any, path: str) -> str:
    if not isinstance(obj, str):
        raise SerializationError(f"Expected string at {path}")
    return obj


def _expect_optional_str(obj: Any, path: str) -> Optional[str]:
    if obj is None:
        return None
    if not isinstance(obj, str):
        raise SerializationError(f"Expected string at {path}")
    if not obj:
        raise SerializationError(f"Expected non-empty string at {path}")
    return obj


def _expect_int(obj: Any, path: str) -> int:
    if not isinstance(obj, int) or isinstance(obj, bool):
        raise SerializationError(f"Expected integer at {path}")
    return obj


@dataclass(frozen=True)
class PageInfo:
    has_next_page: bool
    end_cursor: Optional[str] = None

    @staticmethod
    def from_dict(obj: Any, path: str) -> "PageInfo":
        raw = _expect_dict(obj, path)
        has_next = raw.get("hasNextPage")
        if not isinstance(has_next, bool):
            raise SerializationError(f"Expected boolean at {path}.hasNextPage")
        end_cursor: Optional[str] = None
        if PAGEINFO_HAS_END_CURSOR:
            value = raw.get("endCursor")
            if value is not None:
                end_cursor = _expect_str(value, f"{path}.endCursor")
        return PageInfo(has_next_page=has_next, end_cursor=end_cursor)


@dataclass(frozen=True)
class JiraUser:
    account_id: str
    name: str

    @staticmethod
    def from_dict(obj: Any, path: str) -> "JiraUser":
        raw = _expect_dict(obj, path)
        return JiraUser(
            account_id=_expect_str(raw.get("accountId"), f"{path}.accountId"),
            name=_expect_str(raw.get("name"), f"{path}.name"),
        )


@dataclass(frozen=True)
class JiraEstimate:
    time_in_seconds: Optional[int]

    @staticmethod
    def from_dict(obj: Any, path: str) -> "JiraEstimate":
        raw = _expect_dict(obj, path)
        value = raw.get("timeInSeconds")
        if value is None:
            return JiraEstimate(time_in_seconds=None)
        return JiraEstimate(time_in_seconds=_expect_int(value, f"{path}.timeInSeconds"))


@dataclass(frozen=True)
class JiraWorklogNode:
    worklog_id: str
    author: Optional[JiraUser]
    time_spent: JiraEstimate
    created: str
    updated: Optional[str]
    started: Optional[str]

    @staticmethod
    def from_dict(obj: Any, path: str) -> "JiraWorklogNode":
        raw = _expect_dict(obj, path)
        author_raw = raw.get("author")
        return JiraWorklogNode(
            worklog_id=_expect_str(raw.get("worklogId"), f"{path}.worklogId"),
            author=JiraUser.from_dict(author_raw, f"{path}.author") if author_raw is not None else None,
            time_spent=JiraEstimate.from_dict(raw.get("timeSpent"), f"{path}.timeSpent"),
            created=_expect_str(raw.get("created"), f"{path}.created"),
            updated=_expect_optional_str(raw.get("updated"), f"{path}.updated"),
            started=_expect_optional_str(raw.get("startDate"), f"{path}.startDate"),
        )


@dataclass(frozen=True)
class JiraWorklogEdge:
    cursor: Optional[str]
    node: JiraWorklogNode

    @staticmethod
    def from_dict(obj: Any, path: str) -> "JiraWorklogEdge":
        raw = _expect_dict(obj, path)
        cursor: Optional[str] = None
        if WORKLOGS_EDGE_HAS_CURSOR:
            value = raw.get("cursor")
            if value is not None:
                cursor = _expect_str(value, f"{path}.cursor")
        node = JiraWorklogNode.from_dict(raw.get("node"), f"{path}.node")
        return JiraWorklogEdge(cursor=cursor, node=node)


@dataclass(frozen=True)
class JiraWorklogConnection:
    page_info: PageInfo
    edges: List[JiraWorklogEdge]

    @staticmethod
    def from_dict(obj: Any, path: str) -> "JiraWorklogConnection":
        raw = _expect_dict(obj, path)
        page_info = PageInfo.from_dict(raw.get("pageInfo"), f"{path}.pageInfo")
        edges_list = _expect_list(raw.get("edges"), f"{path}.edges")
        edges = [
            JiraWorklogEdge.from_dict(item, f"{path}.edges[{idx}]")
            for idx, item in enumerate(edges_list)
        ]
        return JiraWorklogConnection(page_info=page_info, edges=edges)


def parse_issue_worklogs_page(data: Any) -> JiraWorklogConnection:
    root = _expect_dict(data, "data")
    issue = root.get("issue")
    if issue is None:
        raise SerializationError("Missing data.issue")
    issue_obj = _expect_dict(issue, "data.issue")
    worklogs = issue_obj.get("worklogs")
    if worklogs is None:
        raise SerializationError("Missing data.issue.worklogs")
    return JiraWorklogConnection.from_dict(worklogs, "data.issue.worklogs")
