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

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

from atlassian.errors import SerializationError

PAGEINFO_HAS_END_CURSOR = True
PROJECTS_EDGE_HAS_CURSOR = True
OPSGENIE_EDGE_HAS_CURSOR = True
PROJECT_HAS_ID = True
REFETCH_STRATEGY = "node"

JIRA_PROJECTS_PAGE_QUERY_TEMPLATE = """query JiraProjectsPage(
  $cloudId: ID!,
  $first: Int!,
  $after: String,
  $opsFirst: Int!
) {
  jira {
    projects: allJiraProjects(
      cloudId: $cloudId,
      filter: { types: [__PROJECT_TYPES__] },
      first: $first,
      after: $after
    ) {
      pageInfo { hasNextPage endCursor }
      edges {
        cursor
        node {
          id
          key
          name
          opsgenieTeams: opsgenieTeamsAvailableToLinkWith(first: $opsFirst) {
            pageInfo { hasNextPage endCursor }
            edges {
              cursor
              node {
                id
                name
              }
            }
          }
        }
      }
    }
  }
}
"""

JIRA_PROJECT_OPSGENIE_TEAMS_PAGE_QUERY = """query JiraProjectOpsgenieTeamsPage(
  $projectId: ID!,
  $first: Int!,
  $after: String
) {
  project: node(id: $projectId) {
    ... on JiraProject {
      opsgenieTeams: opsgenieTeamsAvailableToLinkWith(first: $first, after: $after) {
        pageInfo { hasNextPage endCursor }
        edges {
          cursor
          node {
            id
            name
          }
        }
      }
    }
  }
}
"""


def build_jira_projects_page_query(project_types: Sequence[str]) -> str:
    if not project_types:
        raise ValueError("project_types must be non-empty")
    cleaned: List[str] = []
    for raw in project_types:
        if not isinstance(raw, str):
            raise ValueError("project_types must be strings")
        value = raw.strip().upper()
        if not value or not value.replace("_", "").isalnum() or not value[0].isalpha():
            raise ValueError(f"invalid Jira project type enum token: {raw!r}")
        cleaned.append(value)
    return JIRA_PROJECTS_PAGE_QUERY_TEMPLATE.replace("__PROJECT_TYPES__", ", ".join(cleaned))


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_bool(obj: Any, path: str) -> bool:
    if not isinstance(obj, bool):
        raise SerializationError(f"Expected boolean 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 = _expect_bool(raw.get("hasNextPage"), f"{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 OpsgenieTeamNode:
    id: str
    name: str

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


@dataclass(frozen=True)
class OpsgenieTeamEdge:
    cursor: Optional[str]
    node: OpsgenieTeamNode

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


@dataclass(frozen=True)
class OpsgenieTeamsConnection:
    page_info: PageInfo
    edges: List[OpsgenieTeamEdge]

    @staticmethod
    def from_dict(obj: Any, path: str) -> "OpsgenieTeamsConnection":
        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 = [
            OpsgenieTeamEdge.from_dict(item, f"{path}.edges[{idx}]")
            for idx, item in enumerate(edges_list)
        ]
        return OpsgenieTeamsConnection(page_info=page_info, edges=edges)


@dataclass(frozen=True)
class JiraProjectNode:
    id: Optional[str]
    key: str
    name: str
    opsgenie_teams: OpsgenieTeamsConnection

    @staticmethod
    def from_dict(obj: Any, path: str) -> "JiraProjectNode":
        raw = _expect_dict(obj, path)
        project_id: Optional[str] = None
        if PROJECT_HAS_ID:
            value = raw.get("id")
            if value is not None:
                project_id = _expect_str(value, f"{path}.id")
        return JiraProjectNode(
            id=project_id,
            key=_expect_str(raw.get("key"), f"{path}.key"),
            name=_expect_str(raw.get("name"), f"{path}.name"),
            opsgenie_teams=OpsgenieTeamsConnection.from_dict(
                raw.get("opsgenieTeams"), f"{path}.opsgenieTeams"
            ),
        )


@dataclass(frozen=True)
class JiraProjectEdge:
    cursor: Optional[str]
    node: JiraProjectNode

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


@dataclass(frozen=True)
class JiraProjectsConnection:
    page_info: PageInfo
    edges: List[JiraProjectEdge]

    @staticmethod
    def from_dict(obj: Any, path: str) -> "JiraProjectsConnection":
        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 = [
            JiraProjectEdge.from_dict(item, f"{path}.edges[{idx}]")
            for idx, item in enumerate(edges_list)
        ]
        return JiraProjectsConnection(page_info=page_info, edges=edges)


@dataclass(frozen=True)
class JiraProjectsPageData:
    projects: JiraProjectsConnection

    @staticmethod
    def from_dict(obj: Any, path: str = "data.jira") -> "JiraProjectsPageData":
        raw = _expect_dict(obj, path)
        return JiraProjectsPageData(
            projects=JiraProjectsConnection.from_dict(
                raw.get("projects"), f"{path}.projects"
            ),
        )


def parse_jira_projects_page(data: Any) -> JiraProjectsPageData:
    root = _expect_dict(data, "data")
    jira = root.get("jira")
    if jira is None:
        raise SerializationError("Missing data.jira")
    return JiraProjectsPageData.from_dict(jira, "data.jira")


def parse_project_opsgenie_teams(data: Any) -> OpsgenieTeamsConnection:
    root = _expect_dict(data, "data")
    if REFETCH_STRATEGY == "node":
        project = root.get("project")
        if project is None:
            raise SerializationError("Missing data.project")
        project_obj = _expect_dict(project, "data.project")
        inner = project_obj.get("opsgenieTeams")
        if inner is None:
            raise SerializationError("Missing data.project.opsgenieTeams")
        return OpsgenieTeamsConnection.from_dict(inner, "data.project.opsgenieTeams")

    jira = root.get("jira")
    if jira is None:
        raise SerializationError("Missing data.jira")
    jira_obj = _expect_dict(jira, "data.jira")
    project = jira_obj.get("project")
    if project is None:
        raise SerializationError("Missing data.jira.project")
    project_obj = _expect_dict(project, "data.jira.project")
    inner = project_obj.get("opsgenieTeams")
    if inner is None:
        raise SerializationError("Missing data.jira.project.opsgenieTeams")
    return OpsgenieTeamsConnection.from_dict(inner, "data.jira.project.opsgenieTeams")
