"""
aiel_sdk.jira.types
===================

Stable datatypes for the AIEL Jira SDK.

These types provide a small, JSON-friendly, framework-agnostic surface for Jira
tool actions executed via the AIEL Integrations API.

Actions covered
---------------
- jira.myself
- jira.list_sites
- jira.create_issue
- jira.add_comment
- jira.transition_issue

Notes on validation
-------------------
These dataclasses implement light client-side validation to fail fast. Backends
may still enforce their own validation rules.
"""

from __future__ import annotations

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

Json = Dict[str, Any]


# ----------------------------
# Requests
# ----------------------------

@dataclass(frozen=True)
class JiraCreateIssueRequest:
    """
    Create-issue request payload.

    Backend behavior:
    - If `fields` is provided, it is forwarded as-is: {"fields": fields}
    - Otherwise backend requires project_key + summary, issue_type defaults to "Task"
      and optional description is added.
    """

    project_key: Optional[str] = None
    summary: Optional[str] = None
    issue_type: str = "Task"
    description: Optional[dict] = None
    fields: Optional[Json] = None

    def validate(self) -> None:
        if self.fields is not None:
            if not isinstance(self.fields, dict) or not self.fields:
                raise ValueError("JiraCreateIssueRequest.fields must be a non-empty dict when provided")
            return

        if not (self.project_key or "").strip():
            raise ValueError("JiraCreateIssueRequest.project_key is required when fields is not provided")
        if not (self.summary or "").strip():
            raise ValueError("JiraCreateIssueRequest.summary is required when fields is not provided")
        if not (self.issue_type or "").strip():
            raise ValueError("JiraCreateIssueRequest.issue_type must be non-empty")

    def to_params(self) -> Json:
        self.validate()
        if self.fields is not None:
            return {"fields": dict(self.fields)}
        out: Json = {
            "project_key": str(self.project_key),
            "summary": str(self.summary),
            "issue_type": str(self.issue_type),
        }
        if self.description:
            out["description"] = self.description
        return out


@dataclass(frozen=True)
class JiraAddCommentRequest:
    """Add-comment request payload: requires issue_key and body."""
    issue_key: str
    body: str

    def validate(self) -> None:
        if not (self.issue_key or "").strip():
            raise ValueError("JiraAddCommentRequest.issue_key must be non-empty")
        if not (self.body or "").strip():
            raise ValueError("JiraAddCommentRequest.body must be non-empty")

    def to_params(self) -> Json:
        self.validate()
        return {"issue_key": self.issue_key, "body": self.body}


@dataclass(frozen=True)
class JiraTransitionIssueRequest:
    """Transition-issue request payload: requires issue_key and transition_id."""
    issue_key: str
    transition_id: str

    def validate(self) -> None:
        if not (self.issue_key or "").strip():
            raise ValueError("JiraTransitionIssueRequest.issue_key must be non-empty")
        if not (self.transition_id or "").strip():
            raise ValueError("JiraTransitionIssueRequest.transition_id must be non-empty")

    def to_params(self) -> Json:
        self.validate()
        return {"issue_key": self.issue_key, "transition_id": str(self.transition_id)}


# ----------------------------
# Convenience response views
# ----------------------------

@dataclass(frozen=True)
class JiraMyself:
    """
    Minimal typed view for jira.myself output.
    Keeps raw for full fidelity (payload varies by scopes/privacy).
    """
    account_id: Optional[str] = None
    display_name: Optional[str] = None
    email: Optional[str] = None
    raw: Json = field(default_factory=dict)

    @staticmethod
    def from_json(payload: Json) -> "JiraMyself":
        return JiraMyself(
            account_id=payload.get("accountId") or payload.get("account_id"),
            display_name=payload.get("displayName") or payload.get("display_name"),
            email=payload.get("emailAddress") or payload.get("email"),
            raw=dict(payload or {}),
        )


@dataclass(frozen=True)
class JiraAccessibleSite:
    """
    Single entry from Atlassian accessible-resources list.
    """
    id: Optional[str] = None
    name: Optional[str] = None
    url: Optional[str] = None
    raw: Json = field(default_factory=dict)

    @staticmethod
    def from_json(payload: Json) -> "JiraAccessibleSite":
        return JiraAccessibleSite(
            id=payload.get("id"),
            name=payload.get("name"),
            url=payload.get("url"),
            raw=dict(payload or {}),
        )


# ----------------------------
# Capability metadata (stable surface)
# ----------------------------

@dataclass(frozen=True)
class JiraCapability:
    id: str
    label: str
    description: str
    group: str
    group_label: str
    action: str


@dataclass(frozen=True)
class JiraCapabilities:
    items: Tuple[JiraCapability, ...]

    def ids(self) -> List[str]:
        return [c.id for c in self.items]

    def actions(self) -> List[str]:
        return [c.action for c in self.items]


DEFAULT_JIRA_CAPABILITIES = JiraCapabilities(
    items=(
        JiraCapability(
            id="jira:identity:read",
            label="Read Jira Identity",
            description="Read the current Jira/Atlassian user profile (myself).",
            group="Identity",
            group_label="Jira integration",
            action="jira.myself",
        ),
        JiraCapability(
            id="jira:sites:list",
            label="List Accessible Sites",
            description="List Atlassian sites accessible to the connection token.",
            group="Discovery",
            group_label="Jira integration",
            action="jira.list_sites",
        ),
        JiraCapability(
            id="jira:issue:create",
            label="Create Issue",
            description="Create a Jira issue in a project.",
            group="Issues",
            group_label="Jira integration",
            action="jira.create_issue",
        ),
        JiraCapability(
            id="jira:comment:create",
            label="Add Comment",
            description="Add a comment to a Jira issue.",
            group="Issues",
            group_label="Jira integration",
            action="jira.add_comment",
        ),
        JiraCapability(
            id="jira:issue:transition",
            label="Transition Issue",
            description="Transition a Jira issue to a new workflow state.",
            group="Issues",
            group_label="Jira integration",
            action="jira.transition_issue",
        ),
    )
)