"""Typed argument parsing for MCP tool calls.

Supports:
  - JSON string: '{"key": "value"}'
  - Key=value pairs: key=value key2=value2
  - Raw JSON values: key:='{"nested": true}'
  - File input: -f args.json
  - Stdin: --stdin
"""

import json
import sys
from pathlib import Path


class ArgParseError(Exception):
    pass


def parse_tool_args(
    args: tuple[str, ...],
    file_path: str | None = None,
    from_stdin: bool = False,
) -> dict:
    """Parse mixed argument formats into a dict for call_tool."""
    if from_stdin:
        raw = sys.stdin.read().strip()
        if not raw:
            return {}
        try:
            return json.loads(raw)
        except json.JSONDecodeError as exc:
            raise ArgParseError(f"Invalid JSON from stdin: {exc}") from exc

    if file_path:
        path = Path(file_path)
        if not path.exists():
            raise ArgParseError(f"File not found: {file_path}")
        try:
            return json.loads(path.read_text())
        except json.JSONDecodeError as exc:
            raise ArgParseError(f"Invalid JSON in {file_path}: {exc}") from exc

    if not args:
        return {}

    if len(args) == 1 and args[0].strip().startswith("{"):
        try:
            return json.loads(args[0])
        except json.JSONDecodeError as exc:
            raise ArgParseError(f"Invalid JSON argument: {exc}") from exc

    result: dict = {}
    for arg in args:
        if ":=" in arg:
            key, raw_val = arg.split(":=", 1)
            try:
                result[key] = json.loads(raw_val)
            except json.JSONDecodeError as exc:
                raise ArgParseError(f"Invalid JSON in {key}:= value: {exc}") from exc
        elif "=" in arg:
            key, val = arg.split("=", 1)
            result[key] = _coerce_value(val)
        else:
            raise ArgParseError(
                f"Invalid argument '{arg}'. Use key=value, key:='{{json}}', or a JSON string."
            )
    return result


def _coerce_value(val: str):
    """Coerce a string value to the appropriate Python type."""
    if val.lower() == "true":
        return True
    if val.lower() == "false":
        return False
    if val.lower() == "null":
        return None

    # Strip surrounding quotes → force string
    if (val.startswith('"') and val.endswith('"')) or (val.startswith("'") and val.endswith("'")):
        return val[1:-1]

    try:
        return int(val)
    except ValueError:
        pass
    try:
        return float(val)
    except ValueError:
        pass

    return val
