"""Jira client wrapper using the jira library."""

import sys
import tomllib
from functools import lru_cache
from pathlib import Path

from jira import JIRA
from platformdirs import user_cache_dir, user_config_dir

from zaira.project import load_config
from zaira.types import Credentials

CONFIG_DIR = Path(user_config_dir("zaira", appauthor=False))
CACHE_DIR = Path(user_cache_dir("zaira", appauthor=False))


CREDENTIALS_FILE = CONFIG_DIR / "credentials.toml"
CONFIG_FILE = CONFIG_DIR / "config.toml"


def get_schema_path() -> Path:
    """Get path to instance schema file (~/.cache/zaira/schema.json)."""
    return CACHE_DIR / "schema.json"


def get_editmeta_path(project: str, issue_type: str) -> Path:
    """Get path to editmeta cache file (~/.cache/zaira/editmeta_PROJECT_ISSUETYPE.yaml)."""
    safe_type = issue_type.replace(" ", "-").lower()
    return CACHE_DIR / f"editmeta_{project}_{safe_type}.yaml"


def get_project_schema_path(project: str) -> Path:
    """Get path to project schema file (~/.cache/zaira/zproject_PROJECT.json)."""
    return CACHE_DIR / f"zproject_{project}.json"


def get_server_from_config() -> str | None:
    """Get Jira server URL from credentials."""
    creds = load_credentials()
    site = creds.get("site")

    if site:
        if not site.startswith("https://"):
            site = f"https://{site}"
        return site
    return None


def load_credentials() -> Credentials:
    """Load credentials from the platform config directory."""
    if not CREDENTIALS_FILE.exists():
        return {}

    with open(CREDENTIALS_FILE, "rb") as f:
        return tomllib.load(f)


def save_credentials(email: str, api_token: str) -> None:
    """Save credentials to the platform config directory."""
    CONFIG_DIR.mkdir(parents=True, exist_ok=True)

    content = f'email = "{email}"\napi_token = "{api_token}"\n'
    CREDENTIALS_FILE.write_text(content)

    # Secure the file
    CREDENTIALS_FILE.chmod(0o600)


def get_credentials() -> tuple[str, str, str]:
    """Get Jira credentials from config files.

    Server comes from zproject.toml, credentials from the platform config directory.

    Returns:
        Tuple of (server_url, email, api_token)
    """
    server = get_server_from_config()
    creds = load_credentials()
    email = creds.get("email")
    token = creds.get("api_token")

    if not server or not email or not token:
        print(
            f"Error: Credentials not configured in {CREDENTIALS_FILE}", file=sys.stderr
        )
        print("\nRun 'zaira init' to set up credentials.", file=sys.stderr)
        sys.exit(1)

    return server, email, token


# Injected client for testing
_jira_client: JIRA | None = None


def get_jira() -> JIRA:
    """Get the JIRA client instance (cached or injected).

    Returns:
        Authenticated JIRA client
    """
    global _jira_client
    if _jira_client is not None:
        return _jira_client
    return _get_default_jira()


@lru_cache(maxsize=1)
def _get_default_jira() -> JIRA:
    """Create the default JIRA client from credentials.

    Returns:
        Authenticated JIRA client
    """
    server, email, token = get_credentials()
    return JIRA(server=server, basic_auth=(email, token))


def set_jira(client: JIRA | None) -> None:
    """Inject a JIRA client for testing. Pass None to reset."""
    global _jira_client
    _jira_client = client


def reset_jira() -> None:
    """Reset to default client and clear cache."""
    global _jira_client
    _jira_client = None
    _get_default_jira.cache_clear()


def get_server_url() -> str:
    """Get the Jira server URL."""
    server, _, _ = get_credentials()
    return server


def get_jira_site() -> str:
    """Get Jira site name (without https://)."""
    creds = load_credentials()
    site = creds.get("site", "")
    return site.replace("https://", "").replace("http://", "")


def format_jira_error(e: Exception) -> str:
    """Extract a clean error message from a JIRAError, stripping headers/response noise."""
    from jira.exceptions import JIRAError

    if isinstance(e, JIRAError):
        if e.response is not None and hasattr(e.response, "json"):
            try:
                data = e.response.json()
                msgs = data.get("errorMessages", [])
                errs = data.get("errors", {})
                parts = [m for m in msgs if m]
                parts += [f"{k}: {v}" for k, v in errs.items()]
                if parts:
                    return "; ".join(parts)
            except Exception:
                pass
        if e.text:
            return e.text
    return str(e)
