"""Pulse CLI — command-line interface."""

import argparse
import json
import os
import sys
import time
from typing import List, Optional

try:
    from . import __version__
    from .checker import Checker, VitalResult, format_duration
    from .config import load_config, validate_config
except ImportError:
    # Direct execution support
    sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
    from pulse import __version__
    from pulse.checker import Checker, VitalResult, format_duration
    from pulse.config import load_config, validate_config


HISTORY_FILE = ".pulse_history.json"
EXAMPLE_YAML = """\
# Pulse configuration — define your vital signs
# Each vital groups related checks for a single process/service

vitals:
  - name: "My Service"
    checks:
      - type: file_freshness
        path: "data/output.json"
        max_age: "2h"
      - type: log_entry
        path: "logs/service.log"
        pattern: "completed successfully"
        max_age: "4h"

  - name: "Background Worker"
    checks:
      - type: json_key_changed
        path: "data/state.json"
        key: "processed_count"
        max_age: "24h"
      - type: process_output
        command: "pgrep -f worker"
        exit_code: 0
"""

EXAMPLE_JSON = """\
{
  "vitals": [
    {
      "name": "My Service",
      "checks": [
        {
          "type": "file_freshness",
          "path": "data/output.json",
          "max_age": "2h"
        },
        {
          "type": "log_entry",
          "path": "logs/service.log",
          "pattern": "completed successfully",
          "max_age": "4h"
        }
      ]
    },
    {
      "name": "Background Worker",
      "checks": [
        {
          "type": "json_key_changed",
          "path": "data/state.json",
          "key": "processed_count",
          "max_age": "24h"
        },
        {
          "type": "process_output",
          "command": "pgrep -f worker",
          "exit_code": 0
        }
      ]
    }
  ]
}
"""


def _severity_icon(severity: str) -> str:
    icons = {"OK": "  OK", "WARN": "WARN", "CRIT": "CRIT"}
    return icons.get(severity, "????")


def _check_icon(passed: bool) -> str:
    return "\u2713" if passed else "\u2717"


def format_results(results: List[VitalResult]) -> str:
    """Format results for terminal display."""
    lines = []
    for r in results:
        icon = _severity_icon(r.severity)
        activity = format_duration(r.last_activity_seconds) if r.last_activity_seconds is not None else "unknown"

        if r.passed:
            lines.append(
                f"[{icon}] {r.name} \u2014 All {r.total_count} checks passed "
                f"(last activity: {activity})"
            )
        elif r.severity == "WARN":
            lines.append(
                f"[{icon}] {r.name} \u2014 {r.failed_count}/{r.total_count} checks failed"
            )
        else:
            lines.append(
                f"[{icon}] {r.name} \u2014 All checks failed "
                f"(last activity: {activity})"
            )

        # Show individual check details if not all OK
        if not r.passed:
            for c in r.checks:
                ci = _check_icon(c.passed)
                lines.append(f"       {ci} {c.check_type}: {c.message}")

    return "\n".join(lines)


def _save_history(results: List[VitalResult], history_path: str) -> None:
    """Append check results to history file."""
    entry = {
        "timestamp": time.time(),
        "iso": time.strftime("%Y-%m-%dT%H:%M:%S"),
        "results": [r.to_dict() for r in results],
    }

    history = []
    if os.path.exists(history_path):
        try:
            with open(history_path, "r", encoding="utf-8") as f:
                history = json.load(f)
        except (json.JSONDecodeError, IOError):
            history = []

    history.append(entry)
    # Keep last 1000 entries
    history = history[-1000:]

    with open(history_path, "w", encoding="utf-8") as f:
        json.dump(history, f, indent=2)


def cmd_check(args: argparse.Namespace) -> int:
    """Run checks and display results."""
    try:
        config = load_config(args.config)
    except FileNotFoundError as e:
        print(f"Error: {e}", file=sys.stderr)
        return 2

    errors = validate_config(config)
    if errors:
        print("Configuration errors:", file=sys.stderr)
        for err in errors:
            print(f"  - {err}", file=sys.stderr)
        return 2

    base_dir = os.path.dirname(os.path.abspath(args.config)) if args.config else "."
    state_path = os.path.join(base_dir, ".pulse_state.json")
    checker = Checker(base_dir=base_dir, state_path=state_path)

    name_filter = args.name if hasattr(args, "name") and args.name else None
    results = checker.run_all(config, name_filter=name_filter)

    if not results:
        if name_filter:
            print(f"No vital named '{name_filter}' found in config.", file=sys.stderr)
            return 2
        print("No vitals defined in config.", file=sys.stderr)
        return 2

    # Save to history
    history_path = os.path.join(base_dir, HISTORY_FILE)
    _save_history(results, history_path)

    if args.json:
        output = {
            "timestamp": time.time(),
            "healthy": all(r.passed for r in results),
            "results": [r.to_dict() for r in results],
        }
        print(json.dumps(output, indent=2))
    else:
        print(format_results(results))

    return 0 if all(r.passed for r in results) else 1


def cmd_init(args: argparse.Namespace) -> int:
    """Create example configuration file."""
    if args.json:
        filename = "pulse.json"
        content = EXAMPLE_JSON
    else:
        filename = "pulse.yaml"
        content = EXAMPLE_YAML

    if os.path.exists(filename) and not args.force:
        print(f"Error: {filename} already exists. Use --force to overwrite.", file=sys.stderr)
        return 1

    with open(filename, "w", encoding="utf-8") as f:
        f.write(content)
    print(f"Created {filename}")
    return 0


def cmd_history(args: argparse.Namespace) -> int:
    """Show recent check results."""
    base_dir = os.path.dirname(os.path.abspath(args.config)) if args.config else "."
    history_path = os.path.join(base_dir, HISTORY_FILE)

    if not os.path.exists(history_path):
        print("No history found. Run 'pulse check' first.")
        return 0

    try:
        with open(history_path, "r", encoding="utf-8") as f:
            history = json.load(f)
    except (json.JSONDecodeError, IOError) as e:
        print(f"Error reading history: {e}", file=sys.stderr)
        return 1

    count = args.count if hasattr(args, "count") else 10
    entries = history[-count:]

    if args.json:
        print(json.dumps(entries, indent=2))
        return 0

    for entry in entries:
        ts = entry.get("iso", "unknown")
        results = entry.get("results", [])
        statuses = []
        for r in results:
            sev = r.get("severity", "?")
            name = r.get("name", "?")
            statuses.append(f"{sev}:{name}")
        summary = " | ".join(statuses)
        print(f"[{ts}] {summary}")

    return 0


def main(argv: Optional[List[str]] = None) -> int:
    """Main CLI entry point."""
    parser = argparse.ArgumentParser(
        prog="pulse",
        description="Detect when processes are alive but not doing meaningful work.",
    )
    parser.add_argument("--version", action="version", version=f"pulse {__version__}")
    parser.add_argument("-c", "--config", default=None, help="Path to config file")

    subparsers = parser.add_subparsers(dest="command")

    # check
    check_parser = subparsers.add_parser("check", help="Run all checks")
    check_parser.add_argument("--json", action="store_true", help="JSON output")
    check_parser.add_argument("--name", help="Check single vital by name")

    # init
    init_parser = subparsers.add_parser("init", help="Create example config")
    init_parser.add_argument("--json", action="store_true", help="Create JSON config instead of YAML")
    init_parser.add_argument("--force", action="store_true", help="Overwrite existing config")

    # history
    hist_parser = subparsers.add_parser("history", help="Show recent check results")
    hist_parser.add_argument("--json", action="store_true", help="JSON output")
    hist_parser.add_argument("-n", "--count", type=int, default=10, help="Number of entries")

    args = parser.parse_args(argv)

    if not args.command:
        parser.print_help()
        return 0

    dispatch = {
        "check": cmd_check,
        "init": cmd_init,
        "history": cmd_history,
    }

    return dispatch[args.command](args)


if __name__ == "__main__":
    sys.exit(main())
