from __future__ import annotations

import json
from pathlib import Path
from typing import Any

from click import Option
from click.core import ParameterSource


def parse_csv(value: str | None) -> list[str]:
    if not value:
        return []
    return [item.strip() for item in value.split(",") if item and item.strip()]


def load_json_input(path_or_dash: str | None) -> dict[str, Any]:
    if not path_or_dash:
        return {}
    if path_or_dash == "-":
        import sys

        raw = sys.stdin.read()
        return json.loads(raw) if raw.strip() else {}
    path = Path(path_or_dash).expanduser().resolve()
    if not path.exists():
        raise FileNotFoundError(f"input 文件不存在: {path}")
    return json.loads(path.read_text(encoding="utf-8"))


def pick_value(value: Any, fallback_dict: dict[str, Any], key: str) -> Any:
    if value is not None:
        return value
    return fallback_dict.get(key)


def pick_cli_or_input(
    *,
    ctx: Any,
    param_name: str,
    cli_value: Any,
    payload: dict[str, Any],
    payload_key: str,
) -> Any:
    """Resolve value precedence: explicit CLI option > --input JSON > CLI default."""
    try:
        source = ctx.get_parameter_source(param_name)
    except Exception:
        source = None

    if source == ParameterSource.DEFAULT and payload_key in payload:
        return payload[payload_key]
    if cli_value is not None:
        return cli_value
    return payload.get(payload_key)


def all_option_params_are_default(*, ctx: Any) -> bool:
    """Return True when all option params are from default source (no CLI override)."""
    command = getattr(ctx, "command", None)
    params = getattr(command, "params", None) or []
    for param in params:
        if not isinstance(param, Option):
            continue
        name = getattr(param, "name", None)
        if not name:
            continue
        try:
            source = ctx.get_parameter_source(name)
        except Exception:
            return False
        if source != ParameterSource.DEFAULT:
            return False
    return True
