from __future__ import annotations

import argparse
import json
import sys
from typing import Any

from ...errors import QingflowApiError
from ..json_io import load_json_list, load_json_object, load_optional_json_list, load_optional_json_object


def parse_bool_text(value: str) -> bool:
    normalized = value.strip().lower()
    if normalized in {"true", "1", "yes", "y", "on"}:
        return True
    if normalized in {"false", "0", "no", "n", "off"}:
        return False
    raise argparse.ArgumentTypeError("expected one of: true, false, 1, 0, yes, no")


def load_list_arg(path: str | None, *, option_name: str) -> list[Any]:
    return load_optional_json_list(path, option_name=option_name)


def load_object_arg(path: str | None, *, option_name: str) -> dict[str, Any] | None:
    return load_optional_json_object(path, option_name=option_name)


def require_list_arg(path: str | None, *, option_name: str) -> list[Any]:
    if not path:
        raise QingflowApiError.config_error(f"{option_name} is required")
    return load_json_list(path, option_name=option_name)


def require_object_arg(path: str | None, *, option_name: str) -> dict[str, Any]:
    if not path:
        raise QingflowApiError.config_error(f"{option_name} is required")
    return load_json_object(path, option_name=option_name)


def read_secret_arg(value: str | None, *, stdin_enabled: bool, label: str) -> str:
    if stdin_enabled:
        secret = sys.stdin.read().strip()
        if secret:
            return secret
    if value:
        return value
    raise QingflowApiError.config_error(f"{label} is required")


def raise_config_error(
    message: str,
    *,
    fix_hint: str | None = None,
    error_code: str = "CONFIG_ERROR",
    details: dict[str, Any] | None = None,
) -> None:
    error_details: dict[str, Any] = {"fix_hint": fix_hint or message}
    if details:
        error_details.update(details)
    raise RuntimeError(
        json.dumps(
            {
                "category": "config",
                "message": message,
                "error_code": error_code,
                "details": error_details,
            },
            ensure_ascii=False,
        )
    )
