#!/usr/bin/env python3
"""REST API client tool for ScadaLink test infrastructure."""

import argparse
import json
import sys

import requests


DEFAULT_URL = "http://localhost:5200"
DEFAULT_API_KEY = "scadalink-test-key-1"


def cmd_check(args):
    """Test API server connectivity and report status."""
    headers = {"X-API-Key": args.api_key}

    # Test health endpoint (no auth required)
    try:
        resp = requests.get(f"{args.url}/api/Ping", timeout=5)
        ping_ok = resp.status_code == 200
    except Exception as e:
        ping_ok = False
        ping_err = str(e)

    print(f"Ping ({args.url}/api/Ping): {'OK' if ping_ok else 'FAILED - ' + ping_err}")

    if not ping_ok:
        sys.exit(1)

    # Test authenticated endpoint
    try:
        resp = requests.post(f"{args.url}/api/GetStatus", json={}, headers=headers, timeout=5)
        if resp.status_code == 200:
            data = resp.json()
            print(f"Status: {data.get('status', 'unknown')}")
            print(f"Uptime: {data.get('uptime', 0)}s")
            auth_ok = True
        elif resp.status_code == 401:
            print("Auth: FAILED - invalid API key")
            auth_ok = False
        else:
            print(f"Status check: HTTP {resp.status_code}")
            auth_ok = False
    except Exception as e:
        print(f"Status check: FAILED - {e}")
        auth_ok = False

    # List available methods
    try:
        resp = requests.get(f"{args.url}/api/methods", headers=headers, timeout=5)
        if resp.status_code == 200:
            methods = resp.json().get("methods", [])
            print(f"Available methods: {len(methods)}")
    except Exception:
        pass

    if ping_ok and auth_ok:
        print("\nREST API server is healthy.")
    else:
        sys.exit(1)


def cmd_call(args):
    """Call an API method."""
    headers = {"X-API-Key": args.api_key, "Content-Type": "application/json"}
    url = f"{args.url}/api/{args.method}"

    params = {}
    if args.params:
        try:
            params = json.loads(args.params)
        except json.JSONDecodeError as e:
            print(f"Error: invalid JSON params: {e}", file=sys.stderr)
            sys.exit(1)

    try:
        if args.method == "Ping":
            resp = requests.get(url, headers=headers, timeout=args.timeout)
        else:
            resp = requests.post(url, json=params, headers=headers, timeout=args.timeout)
    except requests.exceptions.Timeout:
        print(f"Error: request timed out after {args.timeout}s", file=sys.stderr)
        sys.exit(1)
    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(1)

    print(f"HTTP {resp.status_code}")
    try:
        print(json.dumps(resp.json(), indent=2))
    except Exception:
        print(resp.text)

    if resp.status_code >= 400:
        sys.exit(1)


def cmd_methods(args):
    """List all available API methods."""
    headers = {"X-API-Key": args.api_key}

    try:
        resp = requests.get(f"{args.url}/api/methods", headers=headers, timeout=5)
        if resp.status_code != 200:
            print(f"Error: HTTP {resp.status_code}", file=sys.stderr)
            sys.exit(1)
    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(1)

    methods = resp.json().get("methods", [])
    print(f"{'Method':<25} {'HTTP':<6} {'Path':<30} {'Description'}")
    print("-" * 95)

    for m in methods:
        print(f"{m['method']:<25} {m['httpMethod']:<6} {m['path']:<30} {m.get('description', '')}")
        if m.get("params"):
            params_str = ", ".join(f"{k}: {v}" for k, v in m["params"].items())
            print(f"  {'Params:':<23} {params_str}")


def main():
    parser = argparse.ArgumentParser(description="REST API client tool for ScadaLink test infrastructure")
    parser.add_argument("--url", default=DEFAULT_URL, help=f"API base URL (default: {DEFAULT_URL})")
    parser.add_argument("--api-key", default=DEFAULT_API_KEY, help=f"API key (default: {DEFAULT_API_KEY})")

    sub = parser.add_subparsers(dest="command", required=True)

    sub.add_parser("check", help="Test API connectivity and report status")

    call_p = sub.add_parser("call", help="Call an API method")
    call_p.add_argument("--method", required=True, help="Method name (e.g. Add, GetProductionReport)")
    call_p.add_argument("--params", help="JSON params (e.g. '{\"a\": 2, \"b\": 3}')")
    call_p.add_argument("--timeout", type=float, default=30, help="Request timeout in seconds (default: 30)")

    sub.add_parser("methods", help="List all available API methods")

    args = parser.parse_args()

    commands = {
        "check": cmd_check,
        "call": cmd_call,
        "methods": cmd_methods,
    }

    commands[args.command](args)


if __name__ == "__main__":
    main()
