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

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

from atlassian.errors import SerializationError

JIRA_ISSUE_BY_KEY_QUERY = """query JiraIssueByKey(
  $cloudId: ID!,
  $key: String!
) {
  issueByKey(key: $key, cloudId: $cloudId) {
    key
    issueType { name }
    status { name }
    projectField {
      project { key cloudId }
    }
    createdField { dateTime }
    updatedField { dateTime }
    resolutionDateField { dateTime }
    assigneeField {
      user { accountId name }
    }
    reporter { accountId name }
  }
}
"""


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_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


@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 JiraIssueType:
    name: str

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


@dataclass(frozen=True)
class JiraStatus:
    name: str

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


@dataclass(frozen=True)
class JiraProject:
    key: str
    cloud_id: str

    @staticmethod
    def from_dict(obj: Any, path: str) -> "JiraProject":
        raw = _expect_dict(obj, path)
        return JiraProject(
            key=_expect_str(raw.get("key"), f"{path}.key"),
            cloud_id=_expect_str(raw.get("cloudId"), f"{path}.cloudId"),
        )


@dataclass(frozen=True)
class JiraProjectField:
    project: JiraProject

    @staticmethod
    def from_dict(obj: Any, path: str) -> "JiraProjectField":
        raw = _expect_dict(obj, path)
        return JiraProjectField(
            project=JiraProject.from_dict(raw.get("project"), f"{path}.project"),
        )


@dataclass(frozen=True)
class JiraDateTimePickerField:
    date_time: Optional[str]

    @staticmethod
    def from_dict(obj: Any, path: str) -> "JiraDateTimePickerField":
        raw = _expect_dict(obj, path)
        return JiraDateTimePickerField(
            date_time=_expect_optional_str(raw.get("dateTime"), f"{path}.dateTime")
        )


@dataclass(frozen=True)
class JiraSingleSelectUserPickerField:
    user: Optional[JiraUser]

    @staticmethod
    def from_dict(obj: Any, path: str) -> "JiraSingleSelectUserPickerField":
        raw = _expect_dict(obj, path)
        user_raw = raw.get("user")
        user = JiraUser.from_dict(user_raw, f"{path}.user") if user_raw is not None else None
        return JiraSingleSelectUserPickerField(user=user)


@dataclass(frozen=True)
class JiraIssueNode:
    key: str
    issue_type: JiraIssueType
    status: JiraStatus
    project_field: JiraProjectField
    created_field: JiraDateTimePickerField
    updated_field: JiraDateTimePickerField
    resolution_date_field: Optional[JiraDateTimePickerField]
    assignee_field: Optional[JiraSingleSelectUserPickerField]
    reporter: Optional[JiraUser]

    @staticmethod
    def from_dict(obj: Any, path: str) -> "JiraIssueNode":
        raw = _expect_dict(obj, path)
        resolution_raw = raw.get("resolutionDateField")
        assignee_raw = raw.get("assigneeField")
        reporter_raw = raw.get("reporter")
        return JiraIssueNode(
            key=_expect_str(raw.get("key"), f"{path}.key"),
            issue_type=JiraIssueType.from_dict(raw.get("issueType"), f"{path}.issueType"),
            status=JiraStatus.from_dict(raw.get("status"), f"{path}.status"),
            project_field=JiraProjectField.from_dict(raw.get("projectField"), f"{path}.projectField"),
            created_field=JiraDateTimePickerField.from_dict(raw.get("createdField"), f"{path}.createdField"),
            updated_field=JiraDateTimePickerField.from_dict(raw.get("updatedField"), f"{path}.updatedField"),
            resolution_date_field=JiraDateTimePickerField.from_dict(
                resolution_raw, f"{path}.resolutionDateField"
            )
            if resolution_raw is not None
            else None,
            assignee_field=JiraSingleSelectUserPickerField.from_dict(
                assignee_raw, f"{path}.assigneeField"
            )
            if assignee_raw is not None
            else None,
            reporter=JiraUser.from_dict(reporter_raw, f"{path}.reporter") if reporter_raw is not None else None,
        )


def parse_jira_issue_by_key(data: Any) -> JiraIssueNode:
    root = _expect_dict(data, "data")
    issue = root.get("issueByKey")
    if issue is None:
        raise SerializationError("Missing data.issueByKey")
    return JiraIssueNode.from_dict(issue, "data.issueByKey")
