"""
CLI entry point — ``pyr <script.py>`` or ``pyr help``.
"""

import os
import sys
import textwrap
import traceback

from ._config import ENV_ROOT, ENV_SCRIPT, DEFAULT_ROOT_NAME, CONFIG_DEFAULT_FILENAME
from . import __version__ as _VERSION

# ─── Help text ────────────────────────────────────────────────

_HELP = textwrap.dedent(
    f"""\
    pyruns v{_VERSION} — lightweight Python experiment management UI

    USAGE
      pyr <script.py>            Launch web UI for the given script
      pyr dev <script.py>        Launch with hot-reload (development)
      pyr help | -h | --help     Show this message
      pyr version | -v           Show version

    ZERO CONFIG (argparse)
      If your script uses argparse, pyr extracts parameters
      automatically — no extra setup needed:

        $ pyr train.py           # that's it!

    MANUAL CONFIG (pyruns)
      Place a config file next to your script:

        your_project/
        └── {DEFAULT_ROOT_NAME}/
            └── {CONFIG_DEFAULT_FILENAME}   ← your parameters

      Then in your script:
        import pyruns
        config = pyruns.load()   # auto-reads config under pyr
        print(config.lr)

    API MODES
      • pyr mode:    config = pyruns.load()           # just works
      • manual mode: pyruns.read("path/to/cfg.yaml")  # explicit path
                     config = pyruns.load()

    WORKSPACE SETTINGS
      On first launch, pyr creates  {DEFAULT_ROOT_NAME}/_pyruns_.yaml
      Edit it to customise: UI port, refresh intervals, grid columns,
      default workers, execution mode, etc.

    WORKSPACE LAYOUT
      your_project/
      ├── train.py
      └── {DEFAULT_ROOT_NAME}/
          ├── _pyruns_.yaml          ← UI settings (auto-generated)
          ├── {CONFIG_DEFAULT_FILENAME}    ← parameter template
          ├── my-task/               ← generated task folder
          │   ├── task_info.json
          │   ├── config.yaml
          │   └── run_logs/
          │       ├── run1.log
          │       └── run2.log   ← each run gets its own log
          └── .trash/                ← soft-deleted tasks
"""
)


def _print_help():
    print(_HELP)
    sys.exit(0)


def _print_version():
    print(f"pyruns {_VERSION}")
    sys.exit(0)


# ─── Main entry ───────────────────────────────────────────────


def pyr():
    """``pyr <script.py>`` — launch the experiment management UI."""

    if len(sys.argv) < 2:
        _print_help()

    arg = sys.argv[1]

    # Help / version flags
    if arg in ("help", "-h", "--help"):
        _print_help()
    if arg in ("version", "-v", "--version"):
        _print_version()

    # ── Dev mode: pyr dev <script.py> ──
    if arg == "dev":
        if len(sys.argv) < 3:
            print("Usage: pyr dev <script.py>")
            sys.exit(1)
        _launch_dev(sys.argv[2])
        return

    # ── Resolve script path ──
    filepath = os.path.abspath(arg)
    if not os.path.exists(filepath):
        print(f"Error: '{arg}' not found.")
        sys.exit(1)

    try:
        _setup_env(filepath)

        # ── Launch UI ──
        sys.argv = [sys.argv[0]]
        from pyruns.ui.app import main

        main()

    except SystemExit:
        raise
    except Exception:
        traceback.print_exc()
        sys.exit(1)


def _setup_env(filepath: str) -> str:
    """Detect config source, ensure workspace, set env vars.

    Returns the pyruns root directory path.
    """
    from pyruns.utils.parse_utils import (
        detect_config_source_fast,
        extract_argparse_params,
        generate_config_file,
        resolve_config_path,
    )
    from pyruns.utils.settings import ensure_settings_file

    # ── Detect config source ──
    mode, extra = detect_config_source_fast(filepath)

    file_dir = os.path.dirname(filepath)
    pyruns_dir = os.path.join(file_dir, DEFAULT_ROOT_NAME)

    if mode == "argparse":
        params = extract_argparse_params(filepath)
        generate_config_file(filepath, params)

    elif mode == "pyruns_read":
        if extra:
            config_file = resolve_config_path(extra, file_dir)
            if not config_file:
                print(f"Error: Config '{extra}' not found.")
                sys.exit(1)

    os.makedirs(pyruns_dir, exist_ok=True)
    ensure_settings_file(pyruns_dir)

    # ── Set environment ──
    os.environ[ENV_ROOT] = pyruns_dir
    os.environ[ENV_SCRIPT] = filepath
    return pyruns_dir


def _launch_dev(script_arg: str):
    """Launch UI in dev mode with hot-reload via subprocess."""
    import subprocess as _sp

    filepath = os.path.abspath(script_arg)
    if not os.path.exists(filepath):
        print(f"Error: '{script_arg}' not found.")
        sys.exit(1)

    _setup_env(filepath)
    print(f"[pyruns dev] Hot-reload enabled — editing .py files will auto-restart")
    print(f"[pyruns dev] Script: {filepath}")
    _sp.run([sys.executable, "-m", "pyruns.ui.app"])


if __name__ == "__main__":
    pyr()

