#!/usr/bin/env python
"""
Assign issue plugin for jira-creator.

This plugin implements the assign command, allowing users to assign
Jira issues to specific users.
"""

from argparse import ArgumentParser, Namespace
from typing import Any, Dict, List

from jira_creator.core.plugin_base import JiraPlugin


class AssignIssueError(Exception):
    """Exception raised when trying to assign an issue."""


class AssignPlugin(JiraPlugin):
    """Plugin for assigning Jira issues to users."""

    @property
    def command_name(self) -> str:
        """Return the command name."""
        return "assign"

    @property
    def help_text(self) -> str:
        """Return help text for the command."""
        return "Assign a Jira issue to a user"

    @property
    def category(self) -> str:
        """Return the category for help organization."""
        return "Issue Modification"

    @property
    def example_commands(self) -> List[str]:
        """Return example commands."""
        return ["assign AAP-12345 jsmith"]

    def get_plugin_exceptions(self) -> Dict[str, type[Exception]]:
        """Register this plugin's custom exceptions."""
        return {
            "AssignIssueError": AssignIssueError,
        }

    def register_arguments(self, parser: ArgumentParser) -> None:
        """Register command-specific arguments."""
        parser.add_argument("issue_key", help="The Jira issue key (e.g., PROJ-123)")
        parser.add_argument("assignee", help="Username of the person to assign the issue to")

    def execute(self, client: Any, args: Namespace) -> bool:
        """
        Execute the assign command.

        Arguments:
            client: JiraClient instance
            args: Parsed command arguments

        Returns:
            bool: True if successful
        """
        try:
            self.rest_operation(client, issue_key=args.issue_key, assignee=args.assignee)
            print(f"✅ Issue {args.issue_key} assigned to {args.assignee}")
            return True

        except AssignIssueError as e:
            msg = f"❌ Failed to assign issue: {e}"
            print(msg)
            raise AssignIssueError(e) from e

    def rest_operation(self, client: Any, **kwargs) -> Dict[str, Any]:
        """
        Perform the REST API operation to assign an issue.

        Arguments:
            client: JiraClient instance
            **kwargs: Contains 'issue_key' and 'assignee'

        Returns:
            Dict[str, Any]: API response
        """
        issue_key = kwargs["issue_key"]
        assignee = kwargs["assignee"]

        path = f"/rest/api/2/issue/{issue_key}"
        payload = {"fields": {"assignee": {"name": assignee}}}

        return client.request("PUT", path, json_data=payload)

    def get_fix_capabilities(self) -> List[Dict[str, Any]]:
        """Register fix capabilities for automated issue fixing."""
        return [
            {
                "method_name": "assign_to_current_user",
                "description": "Assign an unassigned issue to the current user",
                "params": {"issue_key": "str - The JIRA issue key"},
                "conditions": {
                    "problem_patterns": ["not assigned", "Unassigned", "❌ In Progress but not assigned"],
                    "required_status": ["In Progress"],
                },
            }
        ]

    def execute_fix(self, client: Any, method_name: str, args: Dict[str, Any]) -> bool:
        """
        Execute a fix method for automated issue fixing.

        Arguments:
            client: JiraClient instance
            method_name: The fix method to execute
            args: Arguments for the fix

        Returns:
            bool: True if fix succeeded, False otherwise
        """
        if method_name == "assign_to_current_user":
            issue_key = args["issue_key"]

            try:
                # Get current user
                user = client.request("GET", "/rest/api/2/myself")
                assignee = user.get("name")

                # Assign the issue
                ns = Namespace(issue_key=issue_key, assignee=assignee)
                return self.execute(client, ns)
            except Exception:  # pylint: disable=broad-exception-caught
                return False

        return False
