"""Jira CLI executor utility for running jira-cli commands."""

import json
import logging
import os
import subprocess
from typing import Any

from pydantic import BaseModel, Field

logger: logging.Logger = logging.getLogger(__name__)


class CommandResult(BaseModel):
    """Result of a jira-cli command execution."""

    stdout: str = Field(description="The stdout of the jira-cli command.")
    stderr: str = Field(description="The stderr of the jira-cli command.")
    exit_code: int = Field(description="The exit code of the jira-cli command.")


def get_jira_cli_path() -> str:
    """Get the path to the jira-cli executable."""
    return os.getenv("JIRA_CLI_PATH", "jira")


def execute_jira_command(
    args: list[str], stdin_input: str | None = None
) -> CommandResult:
    """Execute a jira-cli command and return the result.

    Args:
        args: Command arguments to pass to jira-cli.
        stdin_input: Optional input to pass to stdin.

    Returns:
        CommandResult with stdout, stderr, and exit_code.

    Raises:
        JiraCliError: If jira-cli is not found.
    """
    jira_path: str = get_jira_cli_path()
    command: str = [jira_path] + args

    logger.debug("Running jira command: %s", " ".join(command))

    try:
        process: subprocess.CompletedProcess[str] = subprocess.run(
            command,
            capture_output=True,
            text=True,
            input=stdin_input,
            timeout=20,  # In seconds.
            env=os.environ,  # Needed for the JIRA_API_TOKEN environment variable to be set.
        )

        result: CommandResult = CommandResult(
            stdout=process.stdout,
            stderr=process.stderr,
            exit_code=process.returncode,
        )

        logger.debug("Command result: exit_code=%d", result.exit_code)

        return result

    except FileNotFoundError:
        raise FileNotFoundError(
            f"jira-cli not found at path: {jira_path}. "
            "Please install jira-cli or set JIRA_CLI_PATH environment variable.",
        )


def execute_jira_command_json(args: list[str]) -> Any:
    """Execute a jira-cli command and parse JSON output.

    Args:
        args: Command arguments to pass to jira-cli.

    Returns:
        Parsed JSON response.

    Raises:
        JiraCliError: If command fails.
        ValueError: If JSON parsing fails.
    """
    result: CommandResult = execute_jira_command(args)

    if result.exit_code != 0:
        raise ValueError(f"jira command failed: {result.stderr}")

    try:
        return json.loads(result.stdout)
    except json.JSONDecodeError as e:
        raise ValueError(
            f"Failed to parse jira output as JSON: {result.stdout}"
        ) from e
